Skip to content
Snippets Groups Projects
BPY_interface.c 36.4 KiB
Newer Older
  • Learn to ignore specific revisions
  •  *
     * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
     *
     * This program is free software; you can redistribute it and/or
     * modify it under the terms of the GNU General Public License
     * as published by the Free Software Foundation; either version 2
     * of the License, or (at your option) any later version. The Blender
     * Foundation also sells licenses for use in proprietary software under
     * the Blender License.  See http://www.blender.org/BL/ for information
     * about this.
     *
     * This program is distributed in the hope that it will be useful,
     * but WITHOUT ANY WARRANTY; without even the implied warranty of
     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     * GNU General Public License for more details.
     *
     * You should have received a copy of the GNU General Public License
     * along with this program; if not, write to the Free Software Foundation,
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
     * Inc., 59 Temple Place - Suite 330, Boston, MA	02111-1307, USA.
    
     *
     * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
     * All rights reserved.
     *
     * This is a new part of Blender.
     *
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
     * Contributor(s): Michel Selten, Willian P. Germano, Stephen Swaney,
     * Chris Keith
    
     *
     * ***** END GPL/BL DUAL LICENSE BLOCK *****
    */
    #ifdef HAVE_CONFIG_H
    #include <config.h>
    #endif
    
    #include "compile.h"		/* for the PyCodeObject */
    #include "eval.h"		/* for PyEval_EvalCode */
    
    #include <BLI_blenlib.h>	/* for BLI_last_slash() */
    
    Willian Padovani Germano's avatar
     
    Willian Padovani Germano committed
    
    
    #include <BIF_interface.h>	/* for pupmenu() */
    
    #include <BIF_space.h>
    #include <BIF_screen.h>
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    #include <BIF_toolbox.h>
    
    #include <BKE_object.h>		/* during_scriptlink() */
    
    #include <BKE_utildefines.h>
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    #include <BPI_script.h>
    
    
    #include <DNA_lamp_types.h>
    #include <DNA_material_types.h>
    #include <DNA_object_types.h>
    #include <DNA_scene_types.h>
    
    #include <DNA_space_types.h>
    #include <DNA_text_types.h>
    
    #include <DNA_userdef_types.h>	/* for U.pythondir */
    
    Willian Padovani Germano's avatar
     
    Willian Padovani Germano committed
    
    
    #include "BPY_menus.h"
    
    #include "api2_2x/EXPP_interface.h"
    
    #include "api2_2x/modules.h"
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    /* bpy_registryDict is declared in api2_2x/Registry.h and defined
    
     * in api2_2x/Registry.c
     * This Python dictionary will be used to store data that scripts
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
     * choose to preserve after they are executed, so user changes can be
    
     * restored next time the script is used.  Check the Blender.Registry module. 
     */
    #include "api2_2x/Registry.h"
    
    /*************************************************************************
    * Structure definitions	
    **************************************************************************/
    
    #define FILENAME_LENGTH 24
    typedef struct _ScriptError {
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    	char filename[FILENAME_LENGTH];
    	int lineno;
    
    /****************************************************************************
    * Global variables 
    ****************************************************************************/
    
    /***************************************************************************
    * Function prototypes 
    ***************************************************************************/
    PyObject *RunPython( Text * text, PyObject * globaldict );
    char *GetName( Text * text );
    PyObject *CreateGlobalDictionary( void );
    void ReleaseGlobalDictionary( PyObject * dict );
    void DoAllScriptsFromList( ListBase * list, short event );
    PyObject *importText( char *name );
    void init_ourImport( void );
    PyObject *blender_import( PyObject * self, PyObject * args );
    
    /****************************************************************************
    * Description: This function will initialise Python and all the implemented 
    *	          api variations.
    * Notes:	Currently only the api for 2.2x will be initialised. 
    ****************************************************************************/
    void BPY_start_python( void )
    
    	bpy_registryDict = PyDict_New(  );	/* check comment at start of this file */
    
    	if( !bpy_registryDict )
    		printf( "Error: Couldn't create the Registry Python Dictionary!" );
    
    /* TODO: Shouldn't "blender" be replaced by PACKAGE ?? (config.h) */
    
    	Py_SetProgramName( "blender" );
    
    	/* 
    	 * Py_Initialize() will attempt to import the site module and
    	 * print an error if not found.  See init_syspath() for the
    	 * rest of our init msgs.
    	 */
    
    
    	printf( "Checking for Python install...\n" );
    
    	fflush( stdout );
    
    	Py_Initialize(  );
    
    	init_ourImport(  );
    
    Willian Padovani Germano's avatar
     
    Willian Padovani Germano committed
    
    
    	initBlenderApi2_2x(  );
    
    	init_syspath(  );
    
    Willian Padovani Germano's avatar
     
    Willian Padovani Germano committed
    
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    	return;
    
    /*****************************************************************************/
    
    /* Description: This function will terminate the Python interpreter	     */
    
    /*****************************************************************************/
    
    void BPY_end_python( void )
    
    	if( bpy_registryDict ) {
    		Py_DECREF( bpy_registryDict );
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    		bpy_registryDict = NULL;
    	}
    
    	Py_Finalize(  );
    
    	BPyMenu_RemoveAllEntries(  );	/* freeing bpymenu mem */
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    	/* a script might've opened a .blend file but didn't close it, so: */
    
    	EXPP_Library_Close(  );
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    
    	return;
    
    void syspath_append( char *dirname )
    
    Willian Padovani Germano's avatar
     
    Willian Padovani Germano committed
    {
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    	PyObject *mod_sys, *dict, *path, *dir;
    
    Willian Padovani Germano's avatar
     
    Willian Padovani Germano committed
    
    
    	PyErr_Clear(  );
    
    Willian Padovani Germano's avatar
     
    Willian Padovani Germano committed
    
    
    	dir = Py_BuildValue( "s", dirname );
    
    	mod_sys = PyImport_ImportModule( "sys" );	/* new ref */
    	dict = PyModule_GetDict( mod_sys );	/* borrowed ref */
    	path = PyDict_GetItemString( dict, "path" );	/* borrowed ref */
    
    Willian Padovani Germano's avatar
     
    Willian Padovani Germano committed
    
    
    	if( !PyList_Check( path ) )
    		return;
    
    Willian Padovani Germano's avatar
     
    Willian Padovani Germano committed
    
    
    	PyList_Append( path, dir );
    
    Willian Padovani Germano's avatar
     
    Willian Padovani Germano committed
    
    
    	if( PyErr_Occurred(  ) )
    		Py_FatalError( "could not build sys.path" );
    
    Willian Padovani Germano's avatar
     
    Willian Padovani Germano committed
    
    
    	Py_DECREF( mod_sys );
    
    Willian Padovani Germano's avatar
     
    Willian Padovani Germano committed
    }
    
    
    void init_syspath( void )
    
    Willian Padovani Germano's avatar
     
    Willian Padovani Germano committed
    {
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    	PyObject *path;
    	PyObject *mod, *d;
    	PyObject *p;
    	char *c, *progname;
    
    	char execdir[FILE_MAXDIR + FILE_MAXFILE];	/*defines from DNA_space_types.h */
    
    Willian Padovani Germano's avatar
     
    Willian Padovani Germano committed
    
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    	int n;
    
    Willian Padovani Germano's avatar
     
    Willian Padovani Germano committed
    
    
    	path = Py_BuildValue( "s", bprogname );
    
    Willian Padovani Germano's avatar
     
    Willian Padovani Germano committed
    
    
    	mod = PyImport_ImportModule( "Blender.sys" );
    
    Willian Padovani Germano's avatar
     
    Willian Padovani Germano committed
    
    
    	if( mod ) {
    		d = PyModule_GetDict( mod );
    		PyDict_SetItemString( d, "progname", path );
    		Py_DECREF( mod );
    	} else
    		printf( "Warning: could not set Blender.sys.progname\n" );
    
    Willian Padovani Germano's avatar
     
    Willian Padovani Germano committed
    
    
    	progname = BLI_last_slash( bprogname );	/* looks for the last dir separator */
    
    Willian Padovani Germano's avatar
     
    Willian Padovani Germano committed
    
    
    	c = Py_GetPath(  );	/* get python system path */
    	PySys_SetPath( c );	/* initialize */
    
    Willian Padovani Germano's avatar
     
    Willian Padovani Germano committed
    
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    	n = progname - bprogname;
    
    	if( n > 0 ) {
    		strncpy( execdir, bprogname, n );
    		if( execdir[n - 1] == '.' )
    			n--;	/*fix for when run as ./blender */
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    		execdir[n] = '\0';
    
    Willian Padovani Germano's avatar
     
    Willian Padovani Germano committed
    
    
    		syspath_append( execdir );	/* append to module search path */
    
    Willian Padovani Germano's avatar
     
    Willian Padovani Germano committed
    
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    		/* set Blender.sys.progname */
    
    	} else
    		printf( "Warning: could not determine argv[0] path\n" );
    
    Willian Padovani Germano's avatar
     
    Willian Padovani Germano committed
    
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    	/* 
    	 * bring in the site module so we can add 
    	 * site-package dirs to sys.path 
    	 */
    
    Stephen Swaney's avatar
     
    Stephen Swaney committed
    
    
    	mod = PyImport_ImportModule( "site" );	/* new ref */
    
    	if( mod ) {
    		PyObject *item;
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    		int size = 0;
    		int index;
    
    		printf( "Installed Python found!\n" );
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    		/* get the value of 'sitedirs' from the module */
    
    Stephen Swaney's avatar
     
    Stephen Swaney committed
    
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    		/* the ref man says GetDict() never fails!!! */
    
    		d = PyModule_GetDict( mod );	/* borrowed ref */
    		p = PyDict_GetItemString( d, "sitedirs" );	/* borrowed ref */
    
    		if( p ) {	/* we got our string */
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    			/* append each item in sitedirs list to path */
    
    			size = PyList_Size( p );
    
    			for( index = 0; index < size; index++ ) {
    				item = PySequence_GetItem( p, index );	/* new ref */
    				if( item )
    					syspath_append( PyString_AsString
    							( item ) );
    
    		Py_DECREF( mod );
    	} else {		/* import 'site' failed */
    		PyErr_Clear(  );
    		printf( "No installed Python found.\n" );
    		printf( "Only built-in modules are available.  Some scripts may not run.\n" );
    		printf( "Continuing happily.\n" );
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    	}
    
    	/* 
    	 * initialize the sys module
    	 * set sys.executable to the Blender exe 
    	 * set argv[0] to the Blender exe
    	 */
    
    
    	mod = PyImport_ImportModule( "sys" );	/* new ref */
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    
    
    	if( mod ) {
    		d = PyModule_GetDict( mod );	/* borrowed ref */
    		PyDict_SetItemString( d, "executable",
    				      Py_BuildValue( "s", bprogname ) );
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    		/* in the future this can be extended to have more argv's if needed: */
    
    		PyDict_SetItemString( d, "argv",
    				      Py_BuildValue( "[s]", bprogname ) );
    		Py_DECREF( mod );
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    	}
    
    Willian Padovani Germano's avatar
     
    Willian Padovani Germano committed
    }
    
    
    /****************************************************************************
    * Description: This function finishes Python initialization in Blender.	 
    
    Because U.pythondir (user defined dir for scripts) isn't	 
    initialized when BPY_start_Python needs to be executed, we	 
    postpone adding U.pythondir to sys.path and also BPyMenus	  
    (mechanism to register scripts in Blender menus) for when  
    that dir info is available.   
    ****************************************************************************/
    void BPY_post_start_python( void )
    
    Willian Padovani Germano's avatar
     
    Willian Padovani Germano committed
    {
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    	PyObject *result, *dict;
    
    
    	if( U.pythondir && U.pythondir[0] != '\0' )
    		syspath_append( U.pythondir );	/* append to module search path */
    
    	BPyMenu_Init( 0 );	/* get dynamic menus (registered scripts) data */
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    
    
    	dict = PyDict_New(  );
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    
    	/* here we check if the user has (some of) the expected modules */
    
    	if( dict ) {
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    		char *s = "import chunk, gzip, math, os, struct, string";
    
    		result = PyRun_String( s, Py_eval_input, dict, dict );
    		if( !result ) {
    			PyErr_Clear(  );
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    			/*XXX print msg about this, point to readme.html */
    
    		} else
    			Py_DECREF( result );
    		Py_DECREF( dict );
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    	}
    
    Willian Padovani Germano's avatar
     
    Willian Padovani Germano committed
    }
    
    
    /****************************************************************************
    * Description: This function will return the linenumber on which an error  
    *       	has occurred in the Python script.			
    ****************************************************************************/
    int BPY_Err_getLinenumber( void )
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    	return g_script_error.lineno;
    
    /*****************************************************************************/
    /* Description: This function will return the filename of the python script. */
    /*****************************************************************************/
    
    const char *BPY_Err_getFilename( void )
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    	return g_script_error.filename;
    
    }
    
    /*****************************************************************************/
    
    /* Description: Return PyString filename from a traceback object	    */
    
    /*****************************************************************************/
    
    PyObject *traceback_getFilename( PyObject * tb )
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    	PyObject *v;
    
    
    /* co_filename is in f_code, which is in tb_frame, which is in tb */
    
    
    	v = PyObject_GetAttrString( tb, "tb_frame" );
    	Py_XDECREF( v );
    	v = PyObject_GetAttrString( v, "f_code" );
    	Py_XDECREF( v );
    	v = PyObject_GetAttrString( v, "co_filename" );
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    	return v;
    
    /****************************************************************************
    * Description: Blender Python error handler. This catches the error and	
    * stores filename and line number in a global  
    *****************************************************************************/
    void BPY_Err_Handle( char *script_name )
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    	PyObject *exception, *err, *tb, *v;
    
    	if( !script_name ) {
    		printf( "Error: script has NULL name\n" );
    
    	PyErr_Fetch( &exception, &err, &tb );
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    
    
    	if( !exception && !tb ) {
    		printf( "FATAL: spurious exception\n" );
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    		return;
    	}
    
    
    	strcpy( g_script_error.filename, script_name );
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    
    
    	if( exception
    	    && PyErr_GivenExceptionMatches( exception, PyExc_SyntaxError ) ) {
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    		/* no traceback available when SyntaxError */
    
    		PyErr_Restore( exception, err, tb );	/* takes away reference! */
    		PyErr_Print(  );
    		v = PyObject_GetAttrString( err, "lineno" );
    		if( v ) {
    			g_script_error.lineno = PyInt_AsLong( v );
    			Py_DECREF( v );
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    		/* this avoids an abort in Python 2.3's garbage collecting: */
    
    		PyErr_Clear(  );
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    		return;
    	} else {
    
    		PyErr_NormalizeException( &exception, &err, &tb );
    		PyErr_Restore( exception, err, tb );	/* takes away reference! */
    		PyErr_Print(  );
    		tb = PySys_GetObject( "last_traceback" );
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    
    
    		if( !tb ) {
    			printf( "\nCan't get traceback\n" );
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    			return;
    		}
    
    
    		Py_INCREF( tb );
    
    
    /* From old bpython BPY_main.c:
     * 'check traceback objects and look for last traceback in the
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
     *	same text file. This is used to jump to the line of where the
     *	error occured. "If the error occured in another text file or module,
    
     *	the last frame in the current file is adressed."' 
     */
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    
    
    		while( 1 ) {
    			v = PyObject_GetAttrString( tb, "tb_next" );
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    
    
    			if( v == Py_None
    			    ||
    			    strcmp( PyString_AsString
    				    ( traceback_getFilename( v ) ),
    				    script_name ) ) {
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    				break;
    			}
    
    
    			Py_DECREF( tb );
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    			tb = v;
    		}
    
    
    		v = PyObject_GetAttrString( tb, "tb_lineno" );
    		g_script_error.lineno = PyInt_AsLong( v );
    		Py_XDECREF( v );
    		v = traceback_getFilename( tb );
    		strncpy( g_script_error.filename, PyString_AsString( v ),
    			 FILENAME_LENGTH );
    		Py_XDECREF( v );
    		Py_DECREF( tb );
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    	}
    
    	return;
    
    /****************************************************************************
    * Description: This function executes the script passed by st.		
    * Notes:	It is called by blender/src/drawtext.c when a Blender user  
    *		presses ALT+PKEY in the script's text window. 
    *****************************************************************************/
    int BPY_txt_do_python_Text( struct Text *text )
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    	PyObject *py_dict, *py_result;
    
    	BPy_constant *info;
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    	char textname[24];
    
    	if( !text )
    		return 0;
    
    
    	/* check if this text is already running */
    
    	while( script ) {
    		if( !strcmp( script->id.name + 2, text->id.name + 2 ) ) {
    			/* if this text is already a running script, 
    			 * just move to it: */
    
    			newspace( curarea, SPACE_SCRIPT );
    
    			sc = curarea->spacedata.first;
    			sc->script = script;
    
    			return 1;
    		}
    		script = script->id.next;
    	}
    
    	/* Create a new script structure and initialize it: */
    
    	script = alloc_libblock( &G.main->script, ID_SCRIPT, GetName( text ) );
    
    	if( !script ) {
    		printf( "couldn't allocate memory for Script struct!" );
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    	/* if in the script Blender.Load(blendfile) is not the last command,
    	 * an error after it will call BPY_Err_Handle below, but the text struct
    
    	 * will have been deallocated already, so we need to copy its name here.
    	 */
    	BLI_strncpy( textname, GetName( text ),
    		     strlen( GetName( text ) ) + 1 );
    
    	script->id.us = 1;
    	script->flags = SCRIPT_RUNNING;
    	script->py_draw = NULL;
    	script->py_event = NULL;
    	script->py_button = NULL;
    
    
    	py_dict = CreateGlobalDictionary(  );
    
    	info = ( BPy_constant * ) M_constant_New(  );
    	if( info ) {
    		constant_insert( info, "name",
    				 PyString_FromString( script->id.name + 2 ) );
    		Py_INCREF( Py_None );
    		constant_insert( info, "arg", Py_None );
    		PyDict_SetItemString( py_dict, "__script__",
    				      ( PyObject * ) info );
    
    	py_result = RunPython( text, py_dict );	/* Run the script */
    
    	if( !py_result ) {	/* Failed execution of the script */
    
    		BPY_Err_Handle( textname );
    		ReleaseGlobalDictionary( py_dict );
    
    		if( G.main->script.first )
    			free_libblock( &G.main->script, script );
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    		return 0;
    
    	} else {
    		Py_DECREF( py_result );
    		script->flags &= ~SCRIPT_RUNNING;
    		if( !script->flags ) {
    			ReleaseGlobalDictionary( py_dict );
    
    			script->py_globaldict = NULL;
    
    			free_libblock( &G.main->script, script );
    
    	return 1;		/* normal return */
    
    /****************************************************************************
    * Description: The original function of this name has been refactored	   
    * into BPY_txt_do_python_Text.  That version is needed for the command	
    * line support for Python.  This is here to keep the interface the 
    * same and reduce code changes elsewhere. 
    ****************************************************************************/
    int BPY_txt_do_python( struct SpaceText *st )
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    {
    
    	return BPY_txt_do_python_Text( st->text );
    
    /****************************************************************************
    * Description: Called from command line to run a Python script
    * automatically. 
    ****************************************************************************/
    void BPY_run_python_script( char *fn )
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    {
    
    	Text *text = NULL;
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    	int is_blenText = 0;
    
    
    	if( !BLI_exists( fn ) ) {	/* if there's no such filename ... */
    		text = G.main->text.first;	/* try an already existing Blender Text */
    		while( text ) {
    			if( !strcmp( fn, text->id.name + 2 ) )
    				break;
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    			text = text->id.next;
    		}
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    
    
    		if( !text ) {
    			printf( "\nError: no such file or Blender text -- %s.\n", fn );
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    			return;
    
    		} else
    			is_blenText = 1;	/* fn is already a Blender Text */
    
    	if( !is_blenText )
    		text = add_text( fn );
    	if( text == NULL ) {
    		printf( "Error in BPY_run_python_script: couldn't create Blender text " "from %s\n", fn );
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    		// Chris: On Windows if I continue I just get a segmentation
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    		// violation.  To get a baseline file I exit here.
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    	}
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    
    
    	if( BPY_txt_do_python_Text( text ) != 1 ) {
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    		printf( "\nError executing Python script from command-line:\n"
    
    			"%s (at line %d).\n", fn, BPY_Err_getLinenumber(  ) );
    
    	if( !is_blenText )
    		free_libblock( &G.main->text, text );
    
    /****************************************************************************
    * Description: This function executes the script chosen from a menu.
    * Notes:	It is called by the ui code in src/header_???.c when a user  
    *		clicks on a menu entry that refers to a script.
    *		Scripts are searched in the BPyMenuTable, using the given
    *		menutype and event values to know which one was chosen.	
    *****************************************************************************/
    int BPY_menu_do_python( short menutype, int event )
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    	PyObject *py_dict, *py_res, *pyarg = NULL;
    
    	BPy_constant *info;
    	BPyMenu *pym;
    	BPySubMenu *pysm;
    	FILE *fp = NULL;
    
    	char *buffer, *s;
    
    	char filestr[FILE_MAXDIR + FILE_MAXFILE];
    
    	char dirname[FILE_MAXDIR];
    
    	Script *script = G.main->script.first;
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    	int len;
    
    	pym = BPyMenu_GetEntry( menutype, ( short ) event );
    
    	if( !pym )
    		return 0;
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    
    
    	if( pym->version > G.version )
    		notice( "Version mismatch: script was written for Blender %d. "
    			"It may fail with yours: %d.", pym->version,
    			G.version );
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    
    
    /* if there are submenus, let the user choose one from a pupmenu that we
     * create here.*/
    	pysm = pym->submenus;
    
    	if( pysm ) {
    		char *pupstr;
    
    		pupstr = BPyMenu_CreatePupmenuStr( pym, menutype );
    
    		if( pupstr ) {
    			arg = pupmenu( pupstr );
    			MEM_freeN( pupstr );
    
    			if( arg >= 0 ) {
    				while( arg-- )
    					pysm = pysm->next;
    				pyarg = PyString_FromString( pysm->arg );
    			} else
    				return 0;
    
    	if( !pyarg ) {		/* no submenus */
    		Py_INCREF( Py_None );
    
    		pyarg = Py_None;
    	}
    
    
    	if( pym->dir )		/* script is in U.pythondir */
    		BLI_make_file_string( "/", filestr, U.pythondir,
    				      pym->filename );
    	else {			/* script is in ~/.blender/scripts/ */
    		BLI_make_file_string( "/", dirname, bpy_gethome(  ),
    				      "scripts" );
    		BLI_make_file_string( "/", filestr, dirname, pym->filename );
    
    	fp = fopen( filestr, "rb" );
    	if( !fp ) {
    		printf( "Error loading script: couldn't open file %s\n",
    			filestr );
    
    		return 0;
    	}
    
    	/* Create a new script structure and initialize it: */
    
    	script = alloc_libblock( &G.main->script, ID_SCRIPT, pym->name );
    
    	if( !script ) {
    		printf( "couldn't allocate memory for Script struct!" );
    		fclose( fp );
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    	/* let's find a proper area for an eventual script gui:
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    	 * (still experimenting here, need definition on which win
    	 * each group will be put to code this properly) */
    
    	switch ( menutype ) {
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    
    
    	case PYMENU_IMPORT:	/* first 3 were handled in header_info.c */
    	case PYMENU_EXPORT:
    	case PYMENU_HELP:
    	case PYMENU_WIZARDS:
    		break;
    
    	default:
    		if( curarea->spacetype != SPACE_SCRIPT ) {
    			ScrArea *sa = NULL;
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    
    
    			sa = find_biggest_area_of_type( SPACE_BUTS );
    			if( sa ) {
    				if( ( 1.5 * sa->winx ) < sa->winy )
    					sa = NULL;	/* too narrow? */
    			}
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    
    
    			if( !sa )
    				sa = find_biggest_area_of_type( SPACE_SCRIPT );
    			if( !sa )
    				sa = find_biggest_area_of_type( SPACE_TEXT );
    			if( !sa )
    				sa = find_biggest_area_of_type( SPACE_IMAGE );	/* group UV */
    			if( !sa )
    				sa = find_biggest_area_of_type( SPACE_VIEW3D );
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    
    
    			if( !sa )
    				sa = find_biggest_area(  );
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    
    
    			areawinset( sa->win );
    		}
    		break;
    
    	script->id.us = 1;
    	script->flags = SCRIPT_RUNNING;
    	script->py_draw = NULL;
    	script->py_event = NULL;
    	script->py_button = NULL;
    
    
    	py_dict = CreateGlobalDictionary(  );
    
    
    	script->py_globaldict = py_dict;
    
    
    	info = ( BPy_constant * ) M_constant_New(  );
    	if( info ) {
    		constant_insert( info, "name",
    				 PyString_FromString( script->id.name + 2 ) );
    		constant_insert( info, "arg", pyarg );
    		PyDict_SetItemString( py_dict, "__script__",
    				      ( PyObject * ) info );
    
    	/* Previously we used PyRun_File to run directly the code on a FILE 
    	 * object, but as written in the Python/C API Ref Manual, chapter 2,
    	 * 'FILE structs for different C libraries can be different and 
    	 * incompatible'.
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    	 * So now we load the script file data to a buffer */
    
    
    	fseek( fp, 0L, SEEK_END );
    	len = ftell( fp );
    	fseek( fp, 0L, SEEK_SET );
    
    	buffer = MEM_mallocN( len + 2, "pyfilebuf" );	/* len+2 to add '\n\0' */
    	len = fread( buffer, 1, len, fp );
    
    	buffer[len] = '\n';	/* fix syntax error in files w/o eol */
    	buffer[len + 1] = '\0';
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    	/* fast clean-up of dos cr/lf line endings: change '\r' to space */
    
    	/* we also have to check for line splitters: '\\' */
    	/* to avoid possible syntax errors on dos files on win */
    
    	 /**/
    		/* but first make sure we won't disturb memory below &buffer[0]: */
    		if( *buffer == '\r' )
    		*buffer = ' ';
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    
    	/* now handle the whole buffer */
    
    	for( s = buffer + 1; *s != '\0'; s++ ) {
    		if( *s == '\r' ) {
    			if( *( s - 1 ) == '\\' ) {	/* special case: long lines split with '\': */
    				*( s - 1 ) = ' ';	/* we write ' \', because '\ ' is a syntax error */
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    				*s = '\\';
    
    			} else
    				*s = ' ';	/* not a split line, just replace '\r' with ' ' */
    
    	fclose( fp );
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    	/* run the string buffer */
    
    
    	py_res = PyRun_String( buffer, Py_file_input, py_dict, py_dict );
    
    	MEM_freeN( buffer );
    
    	if( !py_res ) {		/* Failed execution of the script */
    
    		BPY_Err_Handle( script->id.name + 2 );
    		PyErr_Print(  );
    		ReleaseGlobalDictionary( py_dict );
    		if( G.main->script.first )
    			free_libblock( &G.main->script, script );
    		error( "Python script error: check console" );
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    		return 0;
    
    	} else {
    		Py_DECREF( py_res );
    		script->flags &= ~SCRIPT_RUNNING;
    
    		if( !script->flags ) {
    			ReleaseGlobalDictionary( py_dict );
    
    			free_libblock( &G.main->script, script );
    
    
    			/* special case: called from the menu in the Scripts window
    			 * we have to change sc->script pointer, since it'll be freed here.*/
    
    			if( curarea->spacetype == SPACE_SCRIPT ) {
    
    				SpaceScript *sc = curarea->spacedata.first;
    
    				sc->script = G.main->script.first;	/* can be null, which is ok ... */
    
    				/* ... meaning no other script is running right now. */
    			}
    
    	return 1;		/* normal return */
    
    /*****************************************************************************
    * Description:	
    * Notes:
    *****************************************************************************/
    void BPY_free_compiled_text( struct Text *text )
    
    	if( !text->compiled )
    		return;
    	Py_DECREF( ( PyObject * ) text->compiled );
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    	text->compiled = NULL;
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    	return;
    
    /*****************************************************************************
    * Description: This function frees a finished (flags == 0) script.
    *****************************************************************************/
    void BPY_free_finished_script( Script * script )
    
    	if( !script )
    		return;
    
    	if( PyErr_Occurred(  ) ) {	/* if script ended after filesel */
    		PyErr_Print(  );	/* eventual errors are handled now */
    		error( "Python script error: check console" );
    
    	free_libblock( &G.main->script, script );
    
    void unlink_script( Script * script )
    {	/* copied from unlink_text in drawtext.c */
    
    	bScreen *scr;
    	ScrArea *area;
    	SpaceLink *sl;
    
    
    	for( scr = G.main->screen.first; scr; scr = scr->id.next ) {
    		for( area = scr->areabase.first; area; area = area->next ) {
    			for( sl = area->spacedata.first; sl; sl = sl->next ) {
    				if( sl->spacetype == SPACE_SCRIPT ) {
    					SpaceScript *sc = ( SpaceScript * ) sl;
    
    					if( sc->script == script ) {
    						sc->script = NULL;
    
    						if( sc ==
    						    area->spacedata.first ) {
    							scrarea_queue_redraw
    								( area );
    
    void BPY_clear_script( Script * script )
    
    	if( !script )
    		return;
    
    	Py_XDECREF( ( PyObject * ) script->py_draw );
    	Py_XDECREF( ( PyObject * ) script->py_event );
    	Py_XDECREF( ( PyObject * ) script->py_button );
    
    	if( dict ) {
    		PyDict_Clear( dict );
    		Py_DECREF( dict );	/* Release dictionary. */
    
    	unlink_script( script );
    
    /*****************************************************************************/
    
    /* ScriptLinks                                                        */
    
    /*****************************************************************************/
    
    
    /*****************************************************************************/
    
    /* Description:								 */
    /* Notes:				Not implemented yet	 */
    
    /*****************************************************************************/
    
    void BPY_clear_bad_scriptlinks( struct Text *byebye )
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    	BPY_clear_bad_scriptlist(getObjectList(), byebye);
    	BPY_clear_bad_scriptlist(getLampList(), byebye);
    	BPY_clear_bad_scriptlist(getCameraList(), byebye);
    	BPY_clear_bad_scriptlist(getMaterialList(), byebye);
    	BPY_clear_bad_scriptlist(getWorldList(),	byebye);
    	BPY_clear_bad_scriptlink(&scene_getCurrent()->id, byebye);
    
    	allqueue(REDRAWBUTSSCRIPT, 0);
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    	return;
    
    /*****************************************************************************
    * Description: Loop through all scripts of a list of object types, and 
    *	execute these scripts.	
    *	For the scene, only the current active scene the scripts are 
    *	executed (if any).
    *****************************************************************************/
    void BPY_do_all_scripts( short event )
    
    	DoAllScriptsFromList( &( G.main->object ), event );
    	DoAllScriptsFromList( &( G.main->lamp ), event );
    	DoAllScriptsFromList( &( G.main->camera ), event );
    	DoAllScriptsFromList( &( G.main->mat ), event );
    	DoAllScriptsFromList( &( G.main->world ), event );
    
    	BPY_do_pyscript( &( G.scene->id ), event );
    
    Willian Padovani Germano's avatar
    Willian Padovani Germano committed
    	return;
    
    /*****************************************************************************
    * Description: Execute a Python script when an event occurs. The following  
    *		events are possible: frame changed, load script and redraw.  
    *		Only events happening to one of the following object types   
    *		are handled: Object, Lamp, Camera, Material, World and	    
    *		Scene.			
    *****************************************************************************/
    
    static ScriptLink *ID_getScriptlink( ID * id )
    
    	switch ( MAKE_ID2( id->name[0], id->name[1] ) ) {
    
    		return &( ( Object * ) id )->scriptlink;
    
    		return &( ( Lamp * ) id )->scriptlink;
    
    		return &( ( Camera * ) id )->scriptlink;
    
    		return &( ( Material * ) id )->scriptlink;
    
    		return &( ( World * ) id )->scriptlink;
    
    		return &( ( Scene * ) id )->scriptlink;
    
    static PyObject *ID_asPyObject( ID * id )
    
    	switch ( MAKE_ID2( id->name[0], id->name[1] ) ) {
    
    		return Object_CreatePyObject( ( Object * ) id );
    
    		return Lamp_CreatePyObject( ( Lamp * ) id );
    
    		return Camera_CreatePyObject( ( Camera * ) id );
    
    		return Material_CreatePyObject( ( Material * ) id );
    
    		return World_CreatePyObject( ( World * ) id );
    
    		return Scene_CreatePyObject( ( Scene * ) id );
    
    		Py_INCREF( Py_None );
    
    		return Py_None;
    
    int BPY_has_onload_script( void )
    
    	if( !slink || !slink->totscript )
    		return 0;
    
    	for( i = 0; i < slink->totscript; i++ ) {
    		if( ( slink->flag[i] == SCRIPT_ONLOAD )
    		    && ( slink->scripts[i] != NULL ) )
    			return 1;
    
    void BPY_do_pyscript( ID * id, short event )
    
    	ScriptLink *scriptlink = ID_getScriptlink( id );
    
    	if( scriptlink && scriptlink->totscript ) {
    
    		int index, during_slink = during_scriptlink(  );
    
    
    		/* invalid scriptlinks (new .blend was just loaded), return */
    
    		if( during_slink < 0 )
    			return;
    
    		/* tell we're running a scriptlink.  The sum also tells if this script
    		 * is running nested inside another.  Blender.Load needs this info to
    		 * avoid trouble with invalid slink pointers. */