| 
									
										
										
										
											2008-11-29 13:36:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-16 16:17:20 +00:00
										 |  |  | #include <stdio.h>
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-29 13:36:08 +00:00
										 |  |  | #include <Python.h>
 | 
					
						
							|  |  |  | #include "compile.h"		/* for the PyCodeObject */
 | 
					
						
							|  |  |  | #include "eval.h"		/* for PyEval_EvalCode */
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-21 08:53:36 +00:00
										 |  |  | #include "BKE_context.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-29 13:36:08 +00:00
										 |  |  | #include "bpy_compat.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "bpy_rna.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-21 08:53:36 +00:00
										 |  |  | #include "bpy_operator.h"
 | 
					
						
							| 
									
										
										
										
											2009-02-28 13:27:45 +00:00
										 |  |  | #include "bpy_ui.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "DNA_space_types.h"
 | 
					
						
							| 
									
										
										
										
											2008-11-29 13:36:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-04 13:26:33 +00:00
										 |  |  | #include "BKE_text.h"
 | 
					
						
							|  |  |  | #include "DNA_text_types.h"
 | 
					
						
							|  |  |  | #include "MEM_guardedalloc.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void BPY_free_compiled_text( struct Text *text ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if( text->compiled ) { | 
					
						
							|  |  |  | 		Py_DECREF( ( PyObject * ) text->compiled ); | 
					
						
							|  |  |  | 		text->compiled = NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2008-11-29 13:36:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /*****************************************************************************
 | 
					
						
							|  |  |  | * Description: This function creates a new Python dictionary object. | 
					
						
							|  |  |  | *****************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-21 08:53:36 +00:00
										 |  |  | static PyObject *CreateGlobalDictionary( bContext *C ) | 
					
						
							| 
									
										
										
										
											2008-11-29 13:36:08 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-03-13 07:50:07 +00:00
										 |  |  | 	PyObject *mod; | 
					
						
							| 
									
										
										
										
											2008-11-29 13:36:08 +00:00
										 |  |  | 	PyObject *dict = PyDict_New(  ); | 
					
						
							|  |  |  | 	PyObject *item = PyUnicode_FromString( "__main__" ); | 
					
						
							|  |  |  | 	PyDict_SetItemString( dict, "__builtins__", PyEval_GetBuiltins(  ) ); | 
					
						
							|  |  |  | 	PyDict_SetItemString( dict, "__name__", item ); | 
					
						
							|  |  |  | 	Py_DECREF(item); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-03-13 07:50:07 +00:00
										 |  |  | 	/* add bpy to global namespace */ | 
					
						
							|  |  |  | 	mod = PyModule_New("bpy"); | 
					
						
							|  |  |  | 	PyDict_SetItemString( dict, "bpy", mod ); | 
					
						
							|  |  |  | 	Py_DECREF(mod); | 
					
						
							| 
									
										
										
										
											2009-02-16 16:17:20 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-03-13 07:50:07 +00:00
										 |  |  | 	PyModule_AddObject( mod, "data", BPY_rna_module() ); | 
					
						
							|  |  |  | 	/* PyModule_AddObject( mod, "doc", BPY_rna_doc() ); */ | 
					
						
							|  |  |  | 	PyModule_AddObject( mod, "types", BPY_rna_types() ); | 
					
						
							|  |  |  | 	PyModule_AddObject( mod, "ops", BPY_operator_module(C) ); | 
					
						
							|  |  |  | 	PyModule_AddObject( mod, "ui", BPY_ui_module() ); // XXX very experemental, consider this a test, especially PyCObject is not meant to be perminant
 | 
					
						
							| 
									
										
										
										
											2009-02-16 16:17:20 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	// XXX - evil, need to access context
 | 
					
						
							|  |  |  | 	item = PyCObject_FromVoidPtr( C, NULL ); | 
					
						
							|  |  |  | 	PyDict_SetItemString( dict, "__bpy_context__", item ); | 
					
						
							|  |  |  | 	Py_DECREF(item); | 
					
						
							| 
									
										
										
										
											2008-11-29 13:36:08 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-03-16 15:54:43 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	// XXX - put somewhere more logical
 | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		PyMethodDef *ml; | 
					
						
							|  |  |  | 		static PyMethodDef bpy_prop_meths[] = { | 
					
						
							| 
									
										
										
										
											2009-03-21 16:03:26 +00:00
										 |  |  | 			{"FloatProperty", (PyCFunction)BPy_FloatProperty, METH_VARARGS|METH_KEYWORDS, ""}, | 
					
						
							|  |  |  | 			{"IntProperty", (PyCFunction)BPy_IntProperty, METH_VARARGS|METH_KEYWORDS, ""}, | 
					
						
							|  |  |  | 			{"BoolProperty", (PyCFunction)BPy_BoolProperty, METH_VARARGS|METH_KEYWORDS, ""}, | 
					
						
							| 
									
										
										
										
											2009-03-16 15:54:43 +00:00
										 |  |  | 			{NULL, NULL, 0, NULL} | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 		 | 
					
						
							| 
									
										
										
										
											2009-03-21 16:03:26 +00:00
										 |  |  | 		for(ml = bpy_prop_meths; ml->ml_name; ml++) { | 
					
						
							| 
									
										
										
										
											2009-03-16 15:54:43 +00:00
										 |  |  | 			PyDict_SetItemString( dict, ml->ml_name, PyCFunction_New(ml, NULL)); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-11-29 13:36:08 +00:00
										 |  |  | 	return dict; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-27 04:55:45 +00:00
										 |  |  | void BPY_start_python( void ) | 
					
						
							| 
									
										
										
										
											2008-11-29 13:36:08 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	PyThreadState *py_tstate = NULL; | 
					
						
							| 
									
										
										
										
											2008-12-27 04:55:45 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-11-29 13:36:08 +00:00
										 |  |  | 	Py_Initialize(  ); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	//PySys_SetArgv( argc_copy, argv_copy );
 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* Initialize thread support (also acquires lock) */ | 
					
						
							|  |  |  | 	PyEval_InitThreads(); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	// todo - sys paths - our own imports
 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	py_tstate = PyGILState_GetThisThreadState(); | 
					
						
							|  |  |  | 	PyEval_ReleaseThread(py_tstate); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-27 04:55:45 +00:00
										 |  |  | void BPY_end_python( void ) | 
					
						
							| 
									
										
										
										
											2008-11-29 13:36:08 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	PyGILState_Ensure(); /* finalizing, no need to grab the state */ | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	// free other python data.
 | 
					
						
							| 
									
										
										
										
											2009-03-11 17:28:37 +00:00
										 |  |  | 	//BPY_rna_free_types();
 | 
					
						
							| 
									
										
										
										
											2008-11-29 13:36:08 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	Py_Finalize(  ); | 
					
						
							| 
									
										
										
										
											2009-03-11 17:28:37 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-11-29 13:36:08 +00:00
										 |  |  | 	return; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-03-04 13:26:33 +00:00
										 |  |  | /* Can run a file or text block */ | 
					
						
							|  |  |  | int BPY_run_python_script( bContext *C, const char *fn, struct Text *text ) | 
					
						
							| 
									
										
										
										
											2008-11-29 13:36:08 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	PyObject *py_dict, *py_result; | 
					
						
							|  |  |  | 	PyGILState_STATE gilstate; | 
					
						
							| 
									
										
										
										
											2009-03-04 13:26:33 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	if (fn==NULL && text==NULL) { | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-11-29 13:36:08 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-12-27 04:55:45 +00:00
										 |  |  | 	//BPY_start_python();
 | 
					
						
							| 
									
										
										
										
											2008-11-29 13:36:08 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	gilstate = PyGILState_Ensure(); | 
					
						
							| 
									
										
										
										
											2009-03-04 13:26:33 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-21 08:53:36 +00:00
										 |  |  | 	py_dict = CreateGlobalDictionary(C); | 
					
						
							| 
									
										
										
										
											2009-03-04 13:26:33 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (text) { | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		if( !text->compiled ) {	/* if it wasn't already compiled, do it now */ | 
					
						
							|  |  |  | 			char *buf = txt_to_buf( text ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			text->compiled = | 
					
						
							|  |  |  | 				Py_CompileString( buf, text->id.name+2, Py_file_input ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			MEM_freeN( buf ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if( PyErr_Occurred(  ) ) { | 
					
						
							| 
									
										
										
										
											2009-03-23 14:39:37 +00:00
										 |  |  | 				PyErr_Print(); | 
					
						
							| 
									
										
										
										
											2009-03-04 13:26:33 +00:00
										 |  |  | 				BPY_free_compiled_text( text ); | 
					
						
							| 
									
										
										
										
											2009-03-23 14:39:37 +00:00
										 |  |  | 				PyGILState_Release(gilstate); | 
					
						
							| 
									
										
										
										
											2009-03-11 17:28:37 +00:00
										 |  |  | 				return 0; | 
					
						
							| 
									
										
										
										
											2009-03-04 13:26:33 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		py_result =  PyEval_EvalCode( text->compiled, py_dict, py_dict ); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		char pystring[512]; | 
					
						
							|  |  |  | 		/* TODO - look into a better way to run a file */ | 
					
						
							|  |  |  | 		sprintf(pystring, "exec(open(r'%s').read())", fn);	 | 
					
						
							|  |  |  | 		py_result = PyRun_String( pystring, Py_file_input, py_dict, py_dict );			 | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-11-29 13:36:08 +00:00
										 |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-03-04 13:26:33 +00:00
										 |  |  | 	if (!py_result) { | 
					
						
							| 
									
										
										
										
											2008-11-29 13:36:08 +00:00
										 |  |  | 		PyErr_Print(); | 
					
						
							| 
									
										
										
										
											2009-03-04 13:26:33 +00:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2008-11-29 13:36:08 +00:00
										 |  |  | 		Py_DECREF( py_result ); | 
					
						
							| 
									
										
										
										
											2009-03-04 13:26:33 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2008-11-29 13:36:08 +00:00
										 |  |  | 	PyGILState_Release(gilstate); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2008-12-27 04:55:45 +00:00
										 |  |  | 	//BPY_end_python();
 | 
					
						
							| 
									
										
										
										
											2009-03-04 13:26:33 +00:00
										 |  |  | 	return py_result ? 1:0; | 
					
						
							| 
									
										
										
										
											2008-11-29 13:36:08 +00:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-02-28 13:27:45 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* TODO - move into bpy_space.c ? */ | 
					
						
							|  |  |  | /* GUI interface routines */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Copied from Draw.c */ | 
					
						
							|  |  |  | static void exit_pydraw( SpaceScript * sc, short err ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Script *script = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( !sc || !sc->script ) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	script = sc->script; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( err ) { | 
					
						
							|  |  |  | 		PyErr_Print(  ); | 
					
						
							|  |  |  | 		script->flags = 0;	/* mark script struct for deletion */ | 
					
						
							|  |  |  | 		SCRIPT_SET_NULL(script); | 
					
						
							|  |  |  | 		script->scriptname[0] = '\0'; | 
					
						
							|  |  |  | 		script->scriptarg[0] = '\0'; | 
					
						
							|  |  |  | // XXX 2.5		error_pyscript();
 | 
					
						
							|  |  |  | // XXX 2.5		scrarea_queue_redraw( sc->area );
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if 0 // XXX 2.5
 | 
					
						
							|  |  |  | 	BPy_Set_DrawButtonsList(sc->but_refs); | 
					
						
							|  |  |  | 	BPy_Free_DrawButtonsList(); /*clear all temp button references*/ | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sc->but_refs = NULL; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	Py_XDECREF( ( PyObject * ) script->py_draw ); | 
					
						
							|  |  |  | 	Py_XDECREF( ( PyObject * ) script->py_event ); | 
					
						
							|  |  |  | 	Py_XDECREF( ( PyObject * ) script->py_button ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	script->py_draw = script->py_event = script->py_button = NULL; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static int bpy_run_script_init(bContext *C, SpaceScript * sc) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (sc->script==NULL)  | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (sc->script->py_draw==NULL && sc->script->scriptname[0] != '\0') | 
					
						
							| 
									
										
										
										
											2009-03-04 13:26:33 +00:00
										 |  |  | 		BPY_run_python_script(C, sc->script->scriptname, NULL); | 
					
						
							| 
									
										
										
										
											2009-02-28 13:27:45 +00:00
										 |  |  | 		 | 
					
						
							|  |  |  | 	if (sc->script->py_draw==NULL) | 
					
						
							|  |  |  | 		return 0; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int BPY_run_script_space_draw(bContext *C, SpaceScript * sc) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (bpy_run_script_init(C, sc)) { | 
					
						
							|  |  |  | 		PyGILState_STATE gilstate = PyGILState_Ensure(); | 
					
						
							|  |  |  | 		PyObject *result = PyObject_CallObject( sc->script->py_draw, NULL ); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		if (result==NULL) | 
					
						
							|  |  |  | 			exit_pydraw(sc, 1); | 
					
						
							| 
									
										
										
										
											2009-03-02 20:18:29 +00:00
										 |  |  | 			 | 
					
						
							|  |  |  | 		PyGILState_Release(gilstate); | 
					
						
							| 
									
										
										
										
											2009-02-28 13:27:45 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // XXX - not used yet, listeners dont get a context
 | 
					
						
							|  |  |  | int BPY_run_script_space_listener(bContext *C, SpaceScript * sc) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (bpy_run_script_init(C, sc)) { | 
					
						
							|  |  |  | 		PyGILState_STATE gilstate = PyGILState_Ensure(); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		PyObject *result = PyObject_CallObject( sc->script->py_draw, NULL ); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		if (result==NULL) | 
					
						
							|  |  |  | 			exit_pydraw(sc, 1); | 
					
						
							| 
									
										
										
										
											2009-03-02 20:18:29 +00:00
										 |  |  | 			 | 
					
						
							|  |  |  | 		PyGILState_Release(gilstate); | 
					
						
							| 
									
										
										
										
											2009-02-28 13:27:45 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-04-01 12:43:07 +00:00
										 |  |  | void BPY_DECREF(void *pyob_ptr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Py_DECREF((PyObject *)pyob_ptr); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-28 13:27:45 +00:00
										 |  |  | #if 0
 | 
					
						
							|  |  |  | /* called from the the scripts window, assume context is ok */ | 
					
						
							|  |  |  | int BPY_run_python_script_space(const char *modulename, const char *func) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	PyObject *py_dict, *py_result= NULL; | 
					
						
							|  |  |  | 	char pystring[512]; | 
					
						
							|  |  |  | 	PyGILState_STATE gilstate; | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	/* for calling the module function */ | 
					
						
							|  |  |  | 	PyObject *py_func,  | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	gilstate = PyGILState_Ensure(); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	py_dict = CreateGlobalDictionary(C); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	PyObject *module = PyImport_ImportModule(scpt->script.filename); | 
					
						
							|  |  |  | 	if (module==NULL) { | 
					
						
							|  |  |  | 		PyErr_SetFormat(PyExc_SystemError, "could not import '%s'", scpt->script.filename); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else { | 
					
						
							|  |  |  | 		py_func = PyObject_GetAttrString(modulename, func); | 
					
						
							|  |  |  | 		if (py_func==NULL) { | 
					
						
							|  |  |  | 			PyErr_SetFormat(PyExc_SystemError, "module has no function '%s.%s'\n", scpt->script.filename, func); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else { | 
					
						
							| 
									
										
										
										
											2009-03-18 22:22:58 +00:00
										 |  |  | 			Py_DECREF(py_func); | 
					
						
							| 
									
										
										
										
											2009-02-28 13:27:45 +00:00
										 |  |  | 			if (!PyCallable_Check(py_func)) { | 
					
						
							|  |  |  | 				PyErr_SetFormat(PyExc_SystemError, "module item is not callable '%s.%s'\n", scpt->script.filename, func); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			else { | 
					
						
							|  |  |  | 				py_result= PyObject_CallObject(py_func, NULL); // XXX will need args eventually
 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if (!py_result) | 
					
						
							|  |  |  | 		PyErr_Print(); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		Py_DECREF( py_result ); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	Py_XDECREF(module); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	PyGILState_Release(gilstate); | 
					
						
							|  |  |  | 	return 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | #endif
 |