Page MenuHome

blender-command-port-patch.2008-07-12.2.46.r15538.txt

File Metadata

Author
Dietrich Bollmann (diresu)
Created
Nov 13 2013, 1:25 PM

blender-command-port-patch.2008-07-12.2.46.r15538.txt

This file is larger than 256 KB, so syntax highlighting was skipped.
Index: tools/Blender.py
===================================================================
--- tools/Blender.py (revision 15538)
+++ tools/Blender.py (working copy)
@@ -9,6 +9,9 @@
* custom printout
* wrapper functions
+Contributor(s):
+- Dietrich Bollmann - added command port build code.
+
TODO: clean up and sanitise code - crosscheck with btools and SConstruct
to kill any code duplication
@@ -163,6 +166,8 @@
syslibs += Split(lenv['BF_OPENGL_LIB'])
if lenv['OURPLATFORM'] in ('win32-vc', 'win32-mingw','linuxcross'):
syslibs += Split(lenv['BF_PTHREADS_LIB'])
+ if lenv['WITH_COMMAND_PORT'] or lenv['WITH_BLASH']: # (dietrich)
+ syslibs += Split(lenv['READLINE_LIB'])
syslibs += Split(lenv['LLIBS'])
@@ -417,6 +422,8 @@
print bc.WARNING+'Not building '+bc.ENDC+bc.OKGREEN+libname+bc.ENDC+' for '+bc.OKBLUE+'BF_QUICK'+bc.ENDC
# note: libs is a global
add_lib_to_dict(self, libs, libtype, libname, priority)
+ if lenv['WITH_COMMAND_PORT']: # (dietrich)
+ lenv.Append(CPPDEFINES=['WITH_COMMAND_PORT'])
def BlenderProg(self=None, builddir=None, progname=None, sources=None, includes=None, libs=None, libpath=None, binarykind=''):
print bc.HEADER+'Configuring program '+bc.ENDC+bc.OKGREEN+progname+bc.ENDC
Index: tools/btools.py
===================================================================
--- tools/btools.py (revision 15538)
+++ tools/btools.py (working copy)
@@ -59,6 +59,7 @@
'BF_PROFILE_FLAGS', 'LCGDIR', 'WITH_BF_VERSE',
'BF_VERSE_INCLUDE',
'VERSE_BUILD_BINARY', 'VERSE_BUILD_DIR', 'VERSE_REGEN_PROTO',
+ 'WITH_COMMAND_PORT', 'WITH_BLASH', 'READLINE_LIB',
'BF_TWEAK_MODE', 'BF_SPLIT_SRC',
'WITHOUT_BF_INSTALL',
'WITH_BF_OPENMP',
@@ -96,7 +97,8 @@
def validate_targets(targs, bc):
valid_list = ['.', 'blender', 'blenderstatic', 'blenderplayer', 'webplugin',
'blendernogame', 'blenderstaticnogame', 'release',
- 'everything', 'clean', 'install-bin', 'install', 'nsis']
+ 'everything', 'clean', 'install-bin', 'install', 'nsis',
+ 'blash'] # (dietrich)
oklist = []
for t in targs:
if t in valid_list:
@@ -323,6 +325,10 @@
(BoolOption('BF_BUILDINFO', 'Buildtime in splash if true', 'true')),
+ (BoolOption('WITH_COMMAND_PORT', 'Build Blender with command port if true', 'false')),
+ (BoolOption('WITH_BLASH', 'Build blash - the blender python shell - if true', 'false')),
+ ('READLINE_LIB', 'readline libraries', ''),
+
(BoolOption('BF_TWEAK_MODE', 'Enable tweak mode if true', 'false')),
(BoolOption('BF_SPLIT_SRC', 'Split src lib into several chunks if true', 'false')),
(BoolOption('WITHOUT_BF_INSTALL', 'dont install if true', 'false')),
Index: source/creator/creator.c
===================================================================
--- source/creator/creator.c (revision 15538)
+++ source/creator/creator.c (working copy)
@@ -22,7 +22,7 @@
*
* The Original Code is: all of this file.
*
- * Contributor(s): none yet.
+ * Contributor(s): Dietrich Bollmann.
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -83,6 +83,10 @@
#include "nla.h"
#include "datatoc.h"
+#ifdef WITH_COMMAND_PORT
+#include "commandport.h" /* Blender command port (dietrich) */
+#endif
+
/* for passing information between creator and gameengine */
#include "SYS_System.h"
@@ -108,6 +112,9 @@
/* Local Function prototypes */
static void print_help();
+#ifdef WITH_COMMAND_PORT
+static void print_debug_command_port_help(); /* (dietrich) */
+#endif
static void print_version();
@@ -224,6 +231,13 @@
#ifdef WIN32
printf (" -R\t\tRegister .blend extension\n");
#endif
+#ifdef WITH_COMMAND_PORT
+ printf (" -c <port number> | --command-port <port number>\n" /* (dietrich) */
+ " \t\tStart the Command Port using port <port number>\n");
+ printf (" --debug-command-port <debug level>\tTurn debug mode on for the command port.\n"); /* (dietrich) */
+ printf (" \t\tFour different debug levels are defined: 1, 2, 3 and 4.\n");
+ printf (" \t\tFor more information try --debug-command-port help.\n");
+#endif
printf (" -v\t\tPrint Blender version and exit\n");
printf (" --\t\tEnds option processing. Following arguments are \n");
printf (" \t\t passed unchanged. Access via Python's sys.argv\n");
@@ -252,7 +266,37 @@
printf (" \"blender -b test.blend -o /tmp -f 1\" works as expected.\n\n");
}
+#ifdef WITH_COMMAND_PORT
+/**
+ help message for the command port debug mode
+ (dietrich)
+*/
+static void print_debug_command_port_help()
+{
+ printf("\n"
+ "* Command Port Debug Mode\n"
+ "\n"
+ "Usage:\n"
+ "\n"
+ " blender --command-port <port number> --debug-command-port <debug level> [more options]\n"
+ "\n"
+ "Print messages for debugging the command port functionality.\n"
+ "This mode is very useful when developing new command port client applications.\n"
+ "\n"
+ "Four different debug levels are defined:\n"
+ "\n"
+ " 1 - Print general command port debug messages.\n"
+ " 2 - Print more detailed information about the evaluation of received commands,\n"
+ " the command packages received from a Blender client and the result packages\n"
+ " sent back to the client after evaluating the commands.\n"
+ " 3 - Hexdump the received packages before processing them.\n"
+ " 4 - Hexdump the received packages without processing them.\n"
+ "\n"
+ );
+}
+#endif
+
double PIL_check_seconds_timer(void);
extern void winlay_get_screensize(int *width_r, int *height_r);
@@ -269,6 +313,10 @@
{
int a, i, stax=0, stay=0, sizx, sizy, scr_init = 0;
SYS_SystemHandle syshandle;
+#ifdef WITH_COMMAND_PORT
+ unsigned short port; /* command port */
+ int command_port_debug_level; /* command port debug level */
+#endif
#if defined(WIN32) || defined (__linux__)
int audio = 1;
@@ -554,6 +602,61 @@
for(a=1; a<argc; a++) {
if (G.afbreek==1) break;
+#ifdef WITH_COMMAND_PORT
+
+ /* handle command port option */
+ if (!strcmp(argv[a], "-c") ||
+ !strcmp(argv[a], "--command-port")) {
+
+ /* get port number */
+ if ((argc - a) < 2) {
+ printf("\nERROR: A port number has to be specified "
+ "after the command port option!\n");
+ exit(1);
+ }
+ a++;
+ port = (unsigned short) atoi(argv[a]);
+
+ /* init the command port */
+ commandport_init(port);
+
+ /* continue with next option */
+ continue;
+
+ } else
+
+ /* handle command port debug level option */
+ if (!strcmp(argv[a], "--debug-command-port")) {
+
+ /* debug level */
+ if ((argc - a) < 2) {
+ printf("\nERROR: A debug level has to be specified "
+ "as value of the command port debug level option!\n");
+ exit(1);
+ }
+ a++;
+
+ /* check if help was requested */
+ if (!strcmp(argv[a], "help")) {
+
+ /* print command port debug help and exit */
+ print_debug_command_port_help();
+ exit(0);
+ }
+
+ /* get the debug level */
+ command_port_debug_level = (unsigned short) atoi(argv[a]);
+
+ /* init the command port debug level */
+ commandport_set_debug_level(command_port_debug_level);
+
+ /* continue with next option */
+ continue;
+
+ } else
+
+#endif
+
if(argv[a][0] == '-') {
switch(argv[a][1]) {
case '-': /* -- ends argument processing */
Index: source/creator/SConscript
===================================================================
--- source/creator/SConscript (revision 15538)
+++ source/creator/SConscript (working copy)
@@ -15,6 +15,10 @@
incs += ' ' + env['BF_QUICKTIME_INC']
defs.append('WITH_QUICKTIME')
+# command port (dietrich)
+if env['WITH_COMMAND_PORT']==1:
+ incs += ' ../blender/commandport/include'
+
if env['WITH_BF_BINRELOC']==1:
incs += ' ../../extern/binreloc/include'
defs.append('WITH_BINRELOC')
Index: source/blender/python/BPY_extern.h
===================================================================
--- source/blender/python/BPY_extern.h (revision 15538)
+++ source/blender/python/BPY_extern.h (working copy)
@@ -52,6 +52,8 @@
extern "C" {
#endif
+ int BPY_setup_armature_weakrefs();
+
/*These two next functions are important for making sure the Draw module
works correctly. Before calling any gui callback using the Draw module,
the following code must be executed:
Index: source/blender/python/BPY_interface.c
===================================================================
--- source/blender/python/BPY_interface.c (revision 15538)
+++ source/blender/python/BPY_interface.c (working copy)
@@ -100,7 +100,7 @@
* creates list in __main__ module dict
*/
-int setup_armature_weakrefs()
+int BPY_setup_armature_weakrefs()
{
PyObject *maindict;
PyObject *main_module;
@@ -123,7 +123,7 @@
if (PyDict_SetItemString(maindict,
list_name,
PyList_New(0)) == -1){
- printf("Oops - setup_armature_weakrefs()\n");
+ printf("Oops - BPY_setup_armature_weakrefs()\n");
return 0;
}
@@ -674,7 +674,7 @@
py_dict = CreateGlobalDictionary( );
- if( !setup_armature_weakrefs()){
+ if( !BPY_setup_armature_weakrefs()){
printf("Oops - weakref dict\n");
PyGILState_Release(gilstate);
return 0;
@@ -857,7 +857,7 @@
script->py_globaldict = py_dict;
- if( !setup_armature_weakrefs()){
+ if( !BPY_setup_armature_weakrefs()){
printf("Oops - weakref dict\n");
free_libblock( &G.main->script, script );
ReleaseGlobalDictionary( py_dict );
@@ -1539,7 +1539,7 @@
PyList_SET_ITEM(tarmats, index, tarmat);
}
- if (!setup_armature_weakrefs()) {
+ if (!BPY_setup_armature_weakrefs()) {
fprintf(stderr, "Oops - weakref dict setup\n");
PyGILState_Release(gilstate);
@@ -1707,7 +1707,7 @@
tarmat = newMatrixObject((float *)ct->matrix, 4, 4, Py_NEW);
idprop = BPy_Wrap_IDProperty( NULL, con->prop, NULL);
- if (!setup_armature_weakrefs()) {
+ if (!BPY_setup_armature_weakrefs()) {
fprintf(stderr, "Oops - weakref dict setup\n");
PyGILState_Release(gilstate);
return;
@@ -2021,7 +2021,7 @@
setitem_retval = EXPP_dict_set_item_str(bpy_pydriver_Dict, "self", bpy_ob);
- if( !setup_armature_weakrefs()){
+ if( !BPY_setup_armature_weakrefs()){
fprintf( stderr, "Oops - weakref dict setup\n");
PyGILState_Release(gilstate);
return result;
@@ -2108,7 +2108,7 @@
}
- if( !setup_armature_weakrefs()){
+ if( !BPY_setup_armature_weakrefs()){
fprintf(stderr, "Oops - weakref dict\n");
PyGILState_Release(gilstate);
return -1;
@@ -2262,7 +2262,7 @@
gilstate = PyGILState_Ensure();
- if( !setup_armature_weakrefs()){
+ if( !BPY_setup_armature_weakrefs()){
printf("Oops - weakref dict, this is a bug\n");
PyGILState_Release(gilstate);
return;
@@ -2504,7 +2504,7 @@
gilstate = PyGILState_Ensure();
- if( !setup_armature_weakrefs()){
+ if( !BPY_setup_armature_weakrefs()){
printf("Oops - weakref dict, this is a bug\n");
PyGILState_Release(gilstate);
return 0;
Index: source/blender/commandport/include/commandport.h
===================================================================
--- source/blender/commandport/include/commandport.h (revision 0)
+++ source/blender/commandport/include/commandport.h (revision 0)
@@ -0,0 +1,103 @@
+/*
+ * $Id: commandport.h, v 1.0 2007/05/02, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Main Blender Command Port header file.
+ *
+ * All command port functionality in files outside of the
+ * directory `source/blender/commandport/' is implemented
+ * by calling the functions imported from this file:
+ *
+ * - `commandport_init()' initializes the command port and
+ * is called from function `main()'
+ * in file `source/creator/creator.c'
+ * when Blender is started with the `-c' / `--bcp' option;
+ *
+ * - `commandport_start()' starts the command port and
+ * is called from function `screenmain()'
+ * in file `source/blender/src/editscreen.c'
+ * when Blender is started with the `-c' / `--bcp' option;
+ *
+ * - When the command port thread receives a command sequence from
+ * a client, a `COMMAND_PORT_INPUT' event token is appended
+ * to the end of the Blender main event loop queue.
+ * When the Blender main event handler finds such a token,
+ * the function `commandport_handle_input_allocate()' is
+ * called to handle the event.
+ * See the Blender main event loop in function `screenmain()',
+ * file `source/blender/src/editscreen.c'.
+ *
+ * - When Blender was started with the `-c' / `--bcp' option
+ * the function `commandport_destroy()' cleans up the command port code
+ * when Blender exists.
+ * It is called from function `exit_usiblender()'
+ * in file `source/blender/src/usiblender.c'.
+ *
+ * source file: ../blender/src/commandport.c
+ *
+ */
+
+#ifndef COMMANDPORT_H
+#define COMMANDPORT_H
+
+/**
+ Called from function `main()'
+ in file `source/creator/creator.c'
+*/
+void commandport_init(unsigned short port);
+
+/**
+ Called from function `main()'
+ in file `source/creator/creator.c'
+
+ Activate the printing of debug messages for the command port
+ and set their verbosity level.
+*/
+void commandport_set_debug_level(int debug_level);
+
+/**
+ Called from function `screenmain()'
+ in file `source/blender/src/editscreen.c'
+*/
+void commandport_start();
+
+/**
+ Called from function `screenmain()'
+ in file `source/blender/src/editscreen.c'
+*/
+void commandport_handle_input_allocate(void* args);
+
+/**
+ Called from function `exit_usiblender()'
+ in file `source/blender/src/usiblender.c'
+*/
+void commandport_destroy();
+
+#endif /* COMMANDPORT_H */
+
+/* fin */
Index: source/blender/commandport/SConscript
===================================================================
--- source/blender/commandport/SConscript (revision 0)
+++ source/blender/commandport/SConscript (revision 0)
@@ -0,0 +1,49 @@
+# -*- mode: python -*-
+#
+# $Id: SConscript, v 1.0 2007/05/01, dietrich, tokyo $
+#
+# ***** BEGIN GPL 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.
+#
+# 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,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 by the Blender Foundation.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Author: Dietrich Bollmann
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Command port main build file.
+#
+
+Import('env')
+
+sconscripts = []
+
+if env['WITH_COMMAND_PORT'] == 1:
+ sconscripts.append('blender/SConscript')
+
+if env['WITH_BLASH'] == 1:
+ sconscripts.append('blash/SConscript')
+
+if env['WITH_COMMAND_PORT'] == 1 or env['WITH_BLASH'] == 1:
+ sconscripts.append('utilities/SConscript')
+
+SConscript(sconscripts)
+
+# fin.
Index: source/blender/commandport/blash/include/blash_usage.h
===================================================================
--- source/blender/commandport/blash/include/blash_usage.h (revision 0)
+++ source/blender/commandport/blash/include/blash_usage.h (revision 0)
@@ -0,0 +1,51 @@
+/*
+ * $Id: blash_usage.h, v 1.0 2007/07/09, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * blash usage and help functions.
+ *
+ * source file: ../src/blash_usage.c
+ *
+ */
+
+#ifndef BLASH_USAGE_H
+
+/**
+ Print `blash' usage information / help text.
+*/
+void print_blash_usage();
+
+/**
+ Print `blash' shell command usage help text.
+ */
+void print_blash_help();
+
+#define BLASH_USAGE_H
+#endif /* BLASH_USAGE_H */
+
+/* fin */
Index: source/blender/commandport/blash/SConscript
===================================================================
--- source/blender/commandport/blash/SConscript (revision 0)
+++ source/blender/commandport/blash/SConscript (revision 0)
@@ -0,0 +1,38 @@
+# -*- mode: python -*-
+#
+# $Id: SConscript, v 1.0 2007/05/01, dietrich, tokyo $
+#
+# ***** BEGIN GPL 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.
+#
+# 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,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 by the Blender Foundation.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Author: Dietrich Bollmann
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# blash main build file.
+#
+
+SConscript([
+ 'src/SConscript',
+ ])
+
+# fin.
Index: source/blender/commandport/blash/src/SConscript
===================================================================
--- source/blender/commandport/blash/src/SConscript (revision 0)
+++ source/blender/commandport/blash/src/SConscript (revision 0)
@@ -0,0 +1,44 @@
+# -*- mode: python -*-
+#
+# $Id: SConscript, v 1.0 2007/05/01, dietrich, tokyo $
+#
+# ***** BEGIN GPL 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.
+#
+# 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,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 by the Blender Foundation.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Author: Dietrich Bollmann
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# blash source build file.
+
+Import ('env')
+
+incs = '''
+ ../include
+ ../../utilities/include
+'''
+
+sources = env.Glob('*.c')
+
+env.BlenderLib ('blash', sources, Split(incs), [], libtype=['blash'], priority=[0])
+
+# fin.
Index: source/blender/commandport/blash/src/blash.c
===================================================================
--- source/blender/commandport/blash/src/blash.c (revision 0)
+++ source/blender/commandport/blash/src/blash.c (revision 0)
@@ -0,0 +1,142 @@
+/*
+ * $Id: blash.c, v 1.0 2007/05/01, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * blash main file.
+ *
+ */
+
+#include <stdio.h> /* for printf() and fprintf() */
+#include <stdlib.h> /* for atoi() and exit() */
+#include <getopt.h> /* for getopt() */
+
+#include "bcp_debug.h" /* for bcp_debug() */
+#include "blash_usage.h" /* for print_blash_usage() */
+#include "bcp_shell.h" /* for bcp_shell() */
+#include "bcp_defaults.h" /* default values: default IP address, default port, ... */
+#include "message_client.h" /* message client to read and send messages */
+#include "string_buffer.h" /* string buffer */
+
+/**
+ Parameters:
+ Using 'getopt' to parse the parameters.
+*/
+extern char* optarg; /* needed to access option arguments */
+
+/* Parameter definitions */
+static struct option longopts[] = {
+ { "debug", optional_argument, NULL, 'd' },
+ { "help", no_argument, NULL, 'h' },
+ { "IP-address", required_argument, NULL, 'i' },
+ { "port", required_argument, NULL, 'p' },
+ { "shell-mode", no_argument, NULL, 's' },
+ { "eval-mode", no_argument, NULL, 'e' },
+ { "file-mode", no_argument, NULL, 'f' },
+ { "retries", required_argument, NULL, 'r' },
+ { "retry-sleeptime", required_argument, NULL, 't' },
+ { "init", required_argument, NULL, 'I' },
+ { NULL, 0, NULL, 0 }
+};
+
+/**
+ blash main function.
+ */
+int main(int argc, char *argv[])
+{
+ char* server_IP_address; /* server IP address (dotted quad) */
+ unsigned short server_port; /* server port */
+ int mode; /* shell-mode / text-mode */
+ int retries; /* number of times to try to connect to server */
+ double retry_sleeptime; /* time to sleep before retrying to connect to server
+ * in seconds used only if `retries' is not 0 */
+ char* init_command; /* if not NULL the `init_command' command is send
+ * to Blender immediately after (re)connecting */
+
+ int c;
+
+ init_command = NULL; /* NULL - no init command */
+
+ /* defaults */
+ server_IP_address = BCP_DEFAULT_IP;
+ server_port = BCP_DEFAULT_PORT;
+ mode = BCP_SINGLE_MODE;
+ retries = 0;
+ retry_sleeptime = 0.5;
+
+ /* parsing the command line parameters */
+ while ((c = getopt_long(argc, argv, "hd::i:p:sefr:t:", longopts, NULL)) != -1) {
+
+ switch(c) {
+
+ /* help */
+ case 'h': print_blash_usage(); exit(0); break;
+
+ /* set debug message level */
+ case 'd': bcp_set_debug_level((optarg == NULL) ? 1 : atoi(optarg)); break;
+
+ /* server address and port */
+ case 'i': server_IP_address = optarg; break;
+ case 'p': server_port = atoi(optarg); break;
+
+ /* shell modes */
+ case 's': mode = BCP_SINGLE_MODE; break;
+ case 'e': mode = BCP_EVAL_MODE; break;
+ case 'f': mode = BCP_FILE_MODE; break;
+
+ /* retries to connect to Blender server */
+ case 'r': retries = atoi(optarg); break;
+ case 't': retry_sleeptime = atof(optarg); break;
+
+ /* command send to Blender for evaluation
+ immediately after (re)connecting */
+ case 'I': init_command = optarg; break;
+
+ default:
+ printf("ERROR: Unrecognized option `-%c'\n", c);
+ printf("\n");
+ print_blash_usage();
+ exit(1);
+ }
+ }
+
+ /* start the shell */
+ printf("This is Blash - the GNU BLender-Again SHell :)\n");
+ if (bcp_debug()) printf("Connecting to Blender server at IP-address %s, port %d...\n",
+ server_IP_address, server_port);
+
+ /* starting the shell */
+ bcp_shell_wait(server_IP_address, server_port, mode, retries, retry_sleeptime, init_command);
+
+ /* done */
+ printf("\n");
+ printf("bye...\n");
+ printf("\n");
+ exit(0);
+}
+
+/* fin */
Index: source/blender/commandport/blash/src/blash_usage.c
===================================================================
--- source/blender/commandport/blash/src/blash_usage.c (revision 0)
+++ source/blender/commandport/blash/src/blash_usage.c (revision 0)
@@ -0,0 +1,121 @@
+/*
+ * $Id: blash_usage.c, v 1.0 2007/07/09, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * blash usage and help functions.
+ *
+ */
+
+/* fin */
+/* shell_client.c - Dietrich Bollmann */
+
+#include <stdio.h> /* for printf() and fprintf() */
+
+#include "bcp_defaults.h" /* default values: default IP address, default port, ... */
+
+#include "blash_usage.h"
+
+/**
+ Print `blash' usage information / help text.
+ */
+void print_blash_usage()
+{
+ /* "01234567890123456789012345678901234567890123456789012345678901234567890123456789\n" */
+ printf(" \n"
+ " This is Blash - the GNU BLender-Again SHell.\n"
+ " \n"
+ " Blash is used to connect to a running Blender instance\n"
+ " started in server mode and to \"remote control\" it\n"
+ " via the Blender Python scripting API.\n"
+ " \n"
+ " Usage: blash [OPTION]*...\n"
+ " \n"
+ " Options:\n"
+ " \n"
+ " -h, --help Print this help message.\n"
+ " -d[<level>], --debug[=<level>] Print debug messages. The higher the \n"
+ " verbosity level, the more detailed are \n"
+ " the debug messages. Currently 3 levels \n"
+ " are implemented (level 0, 1, 2).\n"
+ " Default: debug level 0; --debug / -d has\n"
+ " the same effect as --debug=1 / -d1. \n"
+ " -i, --IP-address <IP address> IP address of Blender server.\n"
+ " default: %s\n"
+ " -p, --port <port> Port of Blender server.\n"
+ " Default: %d\n"
+ " -s, --shell-mode start in shell (single) mode (default).\n"
+ " -e, --eval-mode start in eval mode.\n"
+ " -f, --file-mode start in file mode.\n"
+ " -r, --retries <no of retries> Number of times blash should retry to \n"
+ " connect to the Blender server.\n"
+ " -t, --retry-sleeptime <seconds> Time to sleep before next try to connect.\n"
+ " Te be used together with `--retries'.\n"
+ " -I, --init <python init command> Initialization code for the Blender server.\n"
+ " <python init command> is evaluated immediately\n"
+ " after (re)connecting to the Blender server.\n"
+ " \n"
+ " Examples:\n"
+ " \n"
+ " blash\n"
+ " blash --IP-address %s --port %d --shell-mode\n"
+ " blash --retries 20 --retry-sleeptime 0.1\n"
+ " \n"
+ " Copyright (c) published under the GNU General Public License.\n"
+ " Written by Dietrich Bollmann.\n",
+ BCP_DEFAULT_IP,
+ BCP_DEFAULT_PORT,
+ BCP_DEFAULT_IP, BCP_DEFAULT_PORT /* example 2 */
+ );
+}
+
+/**
+ Print `blash' shell command usage help text.
+ */
+void print_blash_help()
+{
+ /* "01234567890123456789012345678901234567890123456789012345678901234567890123456789\n" */
+ printf(" \n"
+ " * Blash Commands:\n"
+ " \n"
+ " help - Print the current help text.\n"
+ " \n"
+ " . - Switch temporarily to text input mode. Text input\n"
+ " mode has to be terminated with another dot.\n"
+ " .shell, .single, .s - Switch to shell/single input mode.\n"
+ " .eval, .e - Switch to eval input mode.\n"
+ " .file, .f - Switch to file input mode.\n"
+ " \n"
+ " reconnect [<port>] - Reconnect to the Blender server; use <port> if given.\n"
+ " bye, quit, exit - Exit Blash.\n"
+ " \n"
+ " ...all other inputs are interpreted as Blender python commands.\n"
+ " \n"
+ );
+}
+
+/* fin */
Index: source/blender/commandport/blash/README
===================================================================
--- source/blender/commandport/blash/README (revision 0)
+++ source/blender/commandport/blash/README (revision 0)
@@ -0,0 +1,72 @@
+#
+# $Id: README, v 1.0 2007/05/01, dietrich, tokyo $
+#
+# ***** BEGIN GPL 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.
+#
+# 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,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 by the Blender Foundation.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Author: Dietrich Bollmann
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# blash readme file.
+
+
+* blash - the BLender-Again SHell
+
+Blash is a Blender-Python shell which can be used together
+with Blender when started in server mode.
+
+See also the BCP (Blender Command Port) README (../README).
+
+Example:
+
+ # starting the Blender server:
+
+ $ blender -w -p 10 10 800 600 --command-port 6789 &
+
+ # using blash to send Python commands to the Blender server:
+
+ $ blash --port 6789
+
+ This is Blash - the GNU BLender-Again SHell :)
+ Connection to Blender Server established. (IP address: 127.0.0.1, port: 6789)
+
+ >>> from Blender import *
+ >>>
+ >>> vertices = [[1, 1, 0], [-1, 1, 0], [-1, -1, 0], [1, -1, 0], [0, 0, 1.27]]
+ >>> faces = [[3, 2, 1, 0], [0, 1, 4], [1, 2, 4], [2, 3, 4], [3, 0, 4]]
+ >>>
+ >>> mesh = Mesh.New('mesh')
+ >>> mesh.verts.extend(vertices)
+ >>> mesh.faces.extend(faces)
+ >>>
+ >>> scene = Scene.GetCurrent()
+ >>> object = scene.objects.new(mesh, 'object')
+ >>> Redraw()
+ >>>
+ >>> bye
+
+ bye...
+
+For more information see http://formgames.org/blender/command-port
+
+# fin.
Index: source/blender/commandport/blender/include/bcp_server.h
===================================================================
--- source/blender/commandport/blender/include/bcp_server.h (revision 0)
+++ source/blender/commandport/blender/include/bcp_server.h (revision 0)
@@ -0,0 +1,43 @@
+/*
+ * $Id: bcp_server.h, v 1.0 2007/05/02, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Blender command port server.
+ *
+ * source file: ../src/bcp_server.c]]
+ *
+ */
+
+#ifndef BCP_SERVER_H
+#define BCP_SERVER_H
+
+void bcp_server(unsigned short port);
+
+#endif /* BCP_SERVER_H */
+
+/* fin */
Index: source/blender/commandport/blender/include/bcp_thread.h
===================================================================
--- source/blender/commandport/blender/include/bcp_thread.h (revision 0)
+++ source/blender/commandport/blender/include/bcp_thread.h (revision 0)
@@ -0,0 +1,48 @@
+/*
+ * $Id: bcp_thread.h, v 1.0 2007/05/02, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * the command port server is running in its own thread.
+ * The communication with the main Blender thread is done
+ * via the Blender queue.
+ *
+ * source file: ../src/bcp_thread.c
+ *
+ */
+
+#ifndef BCP_THREAD_H
+#define BCP_THREAD_H
+
+/**
+ Start the command port server thread.
+*/
+void bcp_thread_start(unsigned short port);
+
+#endif /* BCP_THREAD_H */
+
+/* fin */
Index: source/blender/commandport/blender/include/py_stdouterr_buffer.h
===================================================================
--- source/blender/commandport/blender/include/py_stdouterr_buffer.h (revision 0)
+++ source/blender/commandport/blender/include/py_stdouterr_buffer.h (revision 0)
@@ -0,0 +1,121 @@
+/*
+ * $Id: py_stdouterr_buffer.h, v 1.0 2007/05/01, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * A buffer for saving Pythons stdout / stderr
+ * and accessing it after in form of a c string buffer.
+ *
+ * source file: ../src/py_stdouterr_buffer.c
+ *
+ */
+
+#ifndef PY_STDOUTERR_BUFFER_H
+#define PY_STDOUTERR_BUFFER_H
+
+typedef struct py_stdouterr_buffer_struct *py_stdouterr_buffer;
+
+/**
+ Make a new text buffer.
+*/
+py_stdouterr_buffer py_stdouterr_buffer_new();
+
+/**
+ Delete a text buffer.
+*/
+void py_stdouterr_buffer_delete(py_stdouterr_buffer buffer);
+
+/**
+ Redirect stdout to the string buffer.
+*/
+void py_stdouterr_buffer_redirect_stdout(py_stdouterr_buffer buffer);
+
+/**
+ Redirect stderr to the string buffer.
+*/
+void py_stdouterr_buffer_redirect_stderr(py_stdouterr_buffer buffer);
+
+/**
+ Redirect stdout/stderr to the string buffer.
+*/
+void py_stdouterr_buffer_redirect(py_stdouterr_buffer buffer);
+
+/**
+ Restore stdout.
+*/
+void py_stdouterr_buffer_restore_stdout(py_stdouterr_buffer buffer);
+
+/**
+ Restore stdout/stderr.
+*/
+void py_stdouterr_buffer_restore_stderr(py_stdouterr_buffer buffer);
+
+/**
+ Restore stdout/stderr.
+*/
+void py_stdouterr_buffer_restore(py_stdouterr_buffer buffer);
+
+/**
+ Retrive the content of the stdout string buffer.
+
+ NOTE:
+ The retrived string is allocated starage and has to be freed!
+*/
+char* py_stdouterr_buffer_get_stdout_allocate(py_stdouterr_buffer buffer);
+
+/**
+ Retrive the content of the stderr string buffer.
+
+ NOTE:
+ The retrived string is allocated starage and has to be freed!
+*/
+char* py_stdouterr_buffer_get_stderr_allocate(py_stdouterr_buffer buffer);
+
+/**
+ Print the stdout buffer to STDOUT.
+*/
+void py_stdouterr_buffer_print_stdout(py_stdouterr_buffer buffer);
+
+/**
+ Print the stderr buffer to STDERR.
+*/
+void py_stdouterr_buffer_print_stderr(py_stdouterr_buffer buffer);
+
+/**
+ Print first the stdout buffer to STDOUT
+ and after the stderr buffer to STDERR.
+*/
+void py_stdouterr_buffer_print(py_stdouterr_buffer buffer);
+
+/**
+ Clear stdout/stderr buffers.
+*/
+void py_stdouterr_buffer_clear_buffers(py_stdouterr_buffer buffer);
+
+#endif /* PY_STDOUTERR_BUFFER_H */
+
+/* fin */
Index: source/blender/commandport/blender/include/bcp_handle_client.h
===================================================================
--- source/blender/commandport/blender/include/bcp_handle_client.h (revision 0)
+++ source/blender/commandport/blender/include/bcp_handle_client.h (revision 0)
@@ -0,0 +1,43 @@
+/*
+ * $Id: bcp_handle_client.h, v 1.0 2007/05/02, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Handle command port client
+ *
+ * source file: ../src/bcp_handle_client.c
+ *
+ */
+
+#ifndef BCP_HANDLE_CLIENT_H
+#define BCP_HANDLE_CLIENT_H
+
+void bcp_handle_client(int client_socket); /* TCP client handling function */
+
+#endif /* BCP_HANDLE_CLIENT_H */
+
+/* fin */
Index: source/blender/commandport/blender/include/bcp_blender.h
===================================================================
--- source/blender/commandport/blender/include/bcp_blender.h (revision 0)
+++ source/blender/commandport/blender/include/bcp_blender.h (revision 0)
@@ -0,0 +1,71 @@
+/*
+ * $Id: bcp_blender.h, v 1.0 2007/05/18, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Blender command port handler functionality.
+ *
+ * source file: ../src/bcp_blender.c
+ *
+ */
+
+#ifndef BCP_BLENDER_H
+#define BCP_BLENDER_H
+
+typedef struct bcp_blender_handler_struct* bcp_blender_handler;
+
+/**
+ Make a new BCP Blender handler to execute the command port input.
+*/
+bcp_blender_handler bcp_blender_handler_new();
+
+/**
+ Delete the BCP Blender handler.
+*/
+void bcp_blender_handler_delete(bcp_blender_handler handler);
+
+/**
+ Make a Blender command port event,
+ add it to the blender main queue,
+ wait for the result and return it.
+
+ Note:
+ The result is returned as newly allocated character array
+ and has to be freed by the caller!
+*/
+char* bcp_blender_handle_input_allocate(bcp_blender_handler handler, char* command);
+
+/*
+ Handler used internal by the Blender main event queue event handler.
+ Note: This function is wrapped into `commandport_handle_input_allocate()'
+ in order to use `commandport.h' as only interface between Blender and the command port.
+*/
+void bcp_blender_queue_handle_input_allocate(void* args);
+
+#endif /* BCP_BLENDER_H */
+
+/* fin */
Index: source/blender/commandport/blender/include/bcp_python_utilities.h
===================================================================
--- source/blender/commandport/blender/include/bcp_python_utilities.h (revision 0)
+++ source/blender/commandport/blender/include/bcp_python_utilities.h (revision 0)
@@ -0,0 +1,165 @@
+/*
+ * $Id: bcp_python_utilities.h, v 1.0 2007/05/18, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * todo: Short description of this file
+ *
+ * source file: ../src/bcp_python_utilities.c
+ *
+ */
+
+#ifndef BCP_PYTHON_UTILITIES_H
+#define BCP_PYTHON_UTILITIES_H
+
+#define PYTHON_SUCCESS 0
+#define PYTHON_INCOMPLETE_INPUT 1
+#define PYTHON_ERROR 2
+
+/*
+ BCP Input Mode
+
+ The variable 'handler->input_mode' holds the current
+ input mode of the command port.
+
+ Different types of input can be treated:
+
+ - 'EVAL_INPUT_MODE' - for isolated Python expressions.
+ This mode corresponds to the 'Py_eval_input' Python grammar symbol.
+ Compare the documentation to the 'Py_eval_input' token
+ in http://docs.python.org/api/veryhigh.html#l2h-76
+
+ - 'FILE_INPUT_MODE' - for sequences of Python statements as read from a file or other source.
+ This is the symbol to use when compiling arbitrarily long Python source code.
+ This mode corresponds to the 'Py_file_input' Python grammar symbol.
+ Compare the documentation to the 'Py_file_input' token
+ in http://docs.python.org/api/veryhigh.html#l2h-77
+
+ - 'SINGLE_INPUT_MODE' - for single Python statements.
+ This is the symbol used for the interactive interpreter loop.
+ This mode corresponds to the 'Py_single_input' Python grammar symbol.
+ Compare the documentation to the 'Py_single_input' token
+ in http://docs.python.org/api/veryhigh.html#l2h-78
+
+ The input mode can be one of
+ 'SINGLE_INPUT_MODE', 'EVAL_INPUT_MODE' and 'FILE_INPUT_MODE'
+ and describes the input type expected.
+
+ The default input mode is 'FILE_INPUT_MODE'
+ but can be changed at every time with a BCP Meta Command.
+*/
+#define SINGLE_INPUT_MODE 0 /* shell / single command input modus */
+#define EVAL_INPUT_MODE 1 /* eval command input modus */
+#define FILE_INPUT_MODE 2 /* file command input modus (default) */
+
+/*
+ BCP Result Print Mode
+
+ The Result Print Mode determines the method used to
+ convert the result of a python run into a string representation.
+
+ - 'BCP_REPR_PRINT_MODE' - for isolated Python expressions.
+ todo: add the Phython doc description
+ todo: add examples:
+ Strings for example are printed differently depending on the print mode:
+ RESULT (STR): THE MEANING OF PYTHON...
+ RESULT (REPR): 'THE MEANING OF PYTHON...'
+
+Compare the documentation ...
+ in http://docs.python.org/api/???
+
+ - 'BCP_STR_PRINT_MODE' -
+
+ The default input mode is 'todo'
+ but can be changed at every time with a BCP Meta Command.
+*/
+#define BCP_REPR_PRINT_MODE 0
+#define BCP_STR_PRINT_MODE 1
+
+struct py_stdouterr_buffer_struct;
+
+/**
+ Run a c string in single input mode.
+ Note: For eval or file mode use 'py_input_run_allocate()'!
+
+ This is the mode used for the interactive interpreter loop.
+ It corresponds to the 'Py_single_input' Python grammar symbol.
+ Compare the documentation to the 'Py_single_input' token
+ in http://docs.python.org/api/veryhigh.html#l2h-78
+ */
+int py_single_input_run(const char* code, PyObject* namespace,
+ struct py_stdouterr_buffer_struct* stdouterr_buffer);
+
+/**
+ Run a c string in eval or file mode.
+ Note: For single input mode use 'py_single_input_run()'!
+
+ Eval mode should be used for isolated Python expressions.
+ This mode corresponds to the 'Py_eval_input' Python grammar symbol.
+ Compare the documentation to the 'Py_eval_input' token
+ in http://docs.python.org/api/veryhigh.html#l2h-76
+
+ File mode should be used for sequences of Python statements
+ as read from a file or other source. This is the symbol to use when
+ compiling arbitrarily long Python source code.
+ This mode corresponds to the 'Py_file_input' Python grammar symbol.
+ Compare the documentation to the 'Py_file_input' token
+ in http://docs.python.org/api/veryhigh.html#l2h-77
+ */
+int py_input_run_allocate(const char* code,
+ const int input_mode,
+ const int result_print_mode,
+ char** result,
+ PyObject* namespace,
+ struct py_stdouterr_buffer_struct* stdouterr_buffer);
+
+/**
+ Test if 'code' can be parsed and compiled with the
+ python grammar using 'start' as start token.
+
+ Returns a python object with the compiled code if
+ the parsing and compilation was successful
+ and NULL if not.
+
+ Possible start token are:
+ Py_eval_input, Py_file_input, or Py_single_input.
+
+ Compare python API documentation ( http://docs.python.org/api ) for
+ 'Py_CompileStringFlags()' ( http://docs.python.org/api/veryhigh.html#l2h-74 ),
+ 'Py_eval_input' ( http://docs.python.org/api/veryhigh.html#l2h-76 ),
+ 'Py_file_input' ( http://docs.python.org/api/veryhigh.html#l2h-77 ) and
+ 'Py_single_input' ( http://docs.python.org/api/veryhigh.html#l2h-78 ).
+
+ This code was written using an example from the "Extending/Embedding FAQ" - see:
+ http://www.python.org/doc/faq/extending/#how-do-i-tell-incomplete-input-from-invalid-input
+ which in turn was inspired by code from Alex Farber :)
+*/
+/* int python_compile(const char *code, int start_token, PyObject** compiled_code); */
+
+#endif /* BCP_PYTHON_UTILITIES_H */
+
+/* fin */
Index: source/blender/commandport/blender/include/py_codeop.h
===================================================================
--- source/blender/commandport/blender/include/py_codeop.h (revision 0)
+++ source/blender/commandport/blender/include/py_codeop.h (revision 0)
@@ -0,0 +1,89 @@
+/*
+ * $Id: py_codeop.h, v 1.0 2008/04/24, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * A C wrapper for the function 'compile_command()'
+ * from the Python 'codeop' module.
+ *
+ * The documentation for the Python 'codeop' module can be found
+ * here: http://docs.python.org/lib/module-codeop.html
+ *
+ * The function 'compile_command()' is used rather than
+ * 'Py_CompileString()' to implement the interactive read-eval-print
+ * loop as it is able to make the difference between incomplete input
+ * and erroneous input.
+ *
+ * source file: ../src/py_codeop.c
+ *
+ */
+
+#ifndef PY_CODEOP_H
+#define PY_CODEOP_H
+
+/**
+ A C wrapper for the Python command 'compile_command()'
+ from the Python modules 'code' and 'codeop'.
+
+ The function 'compile_command()' is used rather than
+ 'Py_CompileString()' to implement the interactive read-eval-print
+ loop as 'compile_command()' contrary to 'Py_CompileString()'
+ is able to make the difference between incomplete input
+ and erroneous input.
+
+ The function returns
+
+ - a code object if the command is complete and valid;
+ - NULL (and not 'None' as the wrapped Python function)
+ if the command is incomplete;
+ - raises a SyntaxError if the command is complete and contains a
+ syntax error, or raises an OverflowError or ValueError if the
+ command contains an invalid literal.
+
+ Excerpt from the documentation of 'compile_command()'
+ of the 'code' module:
+
+ This function is useful for programs that want to emulate
+ Python's interpreter main loop (a.k.a. the read-eval-print loop).
+ The tricky part is to determine when the user has entered an
+ incomplete command that can be completed by entering more text
+ (as opposed to a complete command or a syntax error).
+ This function almost always makes the same decision as the real
+ interpreter main loop.
+
+ The original documentation of 'compile_command()' can be found here:
+
+ - 27.1 code -- Interpreter base classes
+ http://docs.python.org/lib/module-code.html
+ - 27.2 codeop -- Compile Python code
+ http://docs.python.org/lib/module-codeop.html :
+*/
+PyObject *compile_command(const char *source);
+
+#endif /* PY_CODEOP_H */
+
+/* fin */
Index: source/blender/commandport/blender/include/bcp_python.h
===================================================================
--- source/blender/commandport/blender/include/bcp_python.h (revision 0)
+++ source/blender/commandport/blender/include/bcp_python.h (revision 0)
@@ -0,0 +1,52 @@
+/*
+ * $Id: bcp_python.h, v 1.0 2007/05/18, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Functionality to run a python script in the Blender server.
+ *
+ * source file: ../src/bcp_python.c
+ *
+ */
+
+#ifndef BCP_PYTHON_H
+#define BCP_PYTHON_H
+
+struct py_stdouterr_buffer_struct;
+
+char* bcp_run_python_script_allocate(int* input_mode,
+ int* result_print_mode,
+ struct py_stdouterr_buffer_struct* stdouterr_buffer,
+ PyObject** namespace,
+ char* script,
+ char** shell_input_buffer,
+ int* shell_input_buffer_length,
+ int* shell_input_line_count);
+
+#endif /* BCP_PYTHON_H */
+
+/* fin */
Index: source/blender/commandport/blender/SConscript
===================================================================
--- source/blender/commandport/blender/SConscript (revision 0)
+++ source/blender/commandport/blender/SConscript (revision 0)
@@ -0,0 +1,37 @@
+# -*- mode: python -*-
+#
+# $Id: SConscript, v 1.0 2007/05/18, dietrich, tokyo $
+#
+# ***** BEGIN GPL 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.
+#
+# 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,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 by the Blender Foundation.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Author: Dietrich Bollmann
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# SCons build file for ..../commandport/blender/SConscript/src
+
+SConscript([
+ 'src/SConscript',
+ ])
+
+# fin.
Index: source/blender/commandport/blender/src/bcp_blender.c
===================================================================
--- source/blender/commandport/blender/src/bcp_blender.c (revision 0)
+++ source/blender/commandport/blender/src/bcp_blender.c (revision 0)
@@ -0,0 +1,300 @@
+/*
+ * $Id: bcp_blender.c, v 1.0 2007/05/18, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Blender command port handler functionality.
+ *
+ * header file: ../include/bcp_blender.h
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+
+#include <Python.h>
+
+#include "BIF_mainqueue.h"
+#include "BPY_extern.h"
+
+#include "mydevice.h" /* for COMMAND_PORT_INPUT */
+
+#include "error_codes.h"
+#include "bcp_python_utilities.h"
+#include "bcp_python.h"
+#include "py_stdouterr_buffer.h"
+#include "bcp_defaults.h"
+
+#include "bcp_blender.h"
+
+/* a structure to pass arguments between
+ command port and blender thread
+ and to synchronize them.
+*/
+typedef struct bcp_blender_handler_struct {
+
+ /* BCP input mode - see bcp_python.h.
+ The input mode can be one of
+ 'SINGLE_INPUT_MODE', 'EVAL_INPUT_MODE' and 'FILE_INPUT_MODE'
+ The default is 'FILE_INPUT_MODE'.
+ */
+ int input_mode;
+
+ /* Print mode:
+ The result can be formated using two different print functions:
+ - BCP_REPR_PRINT_MODE, uses 'PyObject_Repr()' to print the result,
+ Example: Stings are printed with "'": 'THE MEANING OF PYTHON...'
+ - BCP_STR_PRINT_MODE, uses 'PyObject_Str()' to print the result,
+ Example: Stings are printed without "'": THE MEANING OF PYTHON...
+ The default is BCP_REPR_PRINT_MODE
+ */
+ int result_print_mode;
+
+ /* a buffer to store pythons stdout/stderr
+ and send it to the client */
+ py_stdouterr_buffer stdouterr_buffer;
+
+ /* Python name space of the command port instance */
+ PyObject* namespace;
+
+ /* the command to be run by the Blender thread */
+ char* command;
+
+ /* shell mode: buffer holding the (possibly incomplete)
+ code entered until the current moment */
+ char* shell_input_buffer;
+
+ /* shell mode: length of the 'shell_input_buffer' */
+ int shell_input_buffer_length;
+
+ /* shell mode: line index of the current shell input */
+ int shell_input_line_count;
+
+ /* the result delivered by the Blender thread */
+ char* result;
+
+ /* mutex to protect struct against
+ simultaneous access by BCP and Blender threads */
+ pthread_mutex_t mutex;
+
+ /* thread condition variable to implement a master/servant model:
+ - The BCP thread waits on the condition for the result of his request
+ - The Blender thread fills in the result slot
+ and signals the BCP that his run request has been finished
+ and the result can be read.
+ */
+ pthread_cond_t condition;
+
+} bcp_blender_handler_struct;
+
+/**/
+bcp_blender_handler bcp_blender_handler_new()
+{
+ /* allocate memory for the handler data struct */
+ bcp_blender_handler handler;
+ handler = (bcp_blender_handler) malloc(sizeof(bcp_blender_handler_struct));
+
+ if (handler == NULL) {
+ fprintf(stderr, "Couldn't allocate memory for new bcp_blender_handler!\n");
+ exit(ERROR_MEMORY);
+ }
+
+ /* init the handler data slots */
+ handler->input_mode = FILE_INPUT_MODE;
+ handler->result_print_mode = BCP_REPR_PRINT_MODE;
+ handler->stdouterr_buffer = py_stdouterr_buffer_new();
+ handler->namespace = NULL;
+ handler->command = NULL;
+ handler->shell_input_buffer = NULL;
+ handler->shell_input_buffer_length = 0;
+ handler->shell_input_line_count = 0;
+ handler->result = NULL;
+ pthread_mutex_init( &handler->mutex, NULL );
+ pthread_cond_init( &handler->condition, NULL );
+
+ return handler;
+}
+
+/**/
+void bcp_blender_handler_delete(bcp_blender_handler handler)
+{
+ PyGILState_STATE gstate;
+
+ /* free the members */
+ py_stdouterr_buffer_delete(handler->stdouterr_buffer);
+
+ /* aquire python thread */
+ gstate = PyGILState_Ensure();
+
+ if (handler->namespace != NULL ) { Py_XDECREF(handler->namespace); }
+
+ /* release python thread */
+ PyGILState_Release(gstate);
+
+ /* Note: handler->command
+ is initialized from a parameter of the function
+ 'bcp_blender_handle_input_allocate(blender_handler, command)'
+ and should be freed in the calling context of this function and not here!
+ */
+ if (handler->shell_input_buffer != NULL ) { free(handler->shell_input_buffer); }
+ if (handler->result != NULL ) { free(handler->result); }
+
+ pthread_mutex_destroy( &handler->mutex );
+ pthread_cond_destroy( &handler->condition );
+
+ /* free the bcp_blender_handler_struct */
+ free(handler);
+}
+
+/**/
+char* bcp_blender_handle_input_allocate(bcp_blender_handler handler, char* command)
+{
+ /* pack arguments and
+ initialize result mutex
+ bcp_queue_handler_args args;
+ args.command = script;
+ args.result = NULL;
+ args.result_mutex = PTHREAD_MUTEX_INITIALIZER;
+ */
+
+ /* get the condition variable and the mutex
+ to synchronize command port and blender thread
+ */
+ pthread_mutex_t* mutex = &handler->mutex;
+ pthread_cond_t* condition = &handler->condition;
+
+ /* the command to be run by the Blender thread */
+ handler->command = command;
+
+ /* initialize the result */
+ handler->result = NULL;
+
+ /* enter the command request into the blender main queue */
+ void* args = (void*) handler;
+ mainqenter_args(COMMAND_PORT_INPUT, 1, 0, args); /* dtodo: why 1 ?? */
+
+ /* wait on the condition variable for the command being executed and
+ the result being returned
+ */
+ if (pthread_mutex_lock(mutex)) {
+ fprintf(stderr, "[BCP] ERROR: BCP thread couldn't lock the result mutex!\n");
+ exit(ERROR_SYNCHRONIZATION);
+ }
+
+ if (pthread_cond_wait(condition, mutex)) {
+ fprintf(stderr, "[BCP] ERROR: BCP thread couldn't wait on the result condition!\n");
+ exit(ERROR_SYNCHRONIZATION);
+ }
+
+ /* get the result */
+ char* result = handler->result;
+
+ if (pthread_mutex_unlock(mutex)) {
+ fprintf(stderr, "[BCP] ERROR: BCP thread couldn't unlock the result mutex!\n");
+ exit(ERROR_SYNCHRONIZATION);
+ }
+
+ /* when the condition variable is signalled, the result should be available */
+ if (handler->result == NULL) {
+ fprintf(stderr, "[BCP] ERROR: No result returned from blender thread!\n");
+ exit(ERROR_SYNCHRONIZATION);
+ }
+
+ /* after returning, the caller is responsible to free the result memory.
+ => resetting handlers result buffer slot.
+ if this is not done and the handler is deleted,
+ bcp_blender_handler_delete() will try to free the memory again...
+ */
+ handler->result = NULL;
+
+ /* return the result :) */
+ return result;
+}
+
+void bcp_blender_queue_handle_input_allocate(void* args)
+{
+ /* extract the arguments */
+ bcp_blender_handler handler_args = (bcp_blender_handler) args;
+ int* input_mode = &handler_args->input_mode;
+ int* result_print_mode = &handler_args->result_print_mode;
+ py_stdouterr_buffer stdouterr_buffer = handler_args->stdouterr_buffer;
+ PyObject** namespace = &handler_args->namespace;
+ char* command = handler_args->command;
+ char** shell_input_buffer = &handler_args->shell_input_buffer;
+ int* shell_input_buffer_length = &handler_args->shell_input_buffer_length;
+ int* shell_input_line_count = &handler_args->shell_input_line_count;
+
+ pthread_mutex_t* mutex = &handler_args->mutex;
+ pthread_cond_t* condition = &handler_args->condition;
+
+ /*
+ todo - compiler complains about:
+
+ bcp_blender.c: In function ‘bcp_blender_queue_handle_input_allocate’:
+ bcp_blender.c:115: warning: unused variable ‘condition’
+ bcp_blender.c:114: warning: unused variable ‘mutex’
+ */
+
+ /* execute command and get the result */
+ char* result;
+
+ /* todo todo todo todo : result = ??? */
+ result = bcp_run_python_script_allocate(input_mode,
+ result_print_mode,
+ stdouterr_buffer,
+ namespace,
+ command,
+ shell_input_buffer,
+ shell_input_buffer_length,
+ shell_input_line_count);
+
+ /* signal the BCP thread that the result is available */
+ if (pthread_mutex_lock(mutex)) {
+ fprintf(stderr, "[BCP] ERROR: Blender thread couldn't lock the result mutex!\n");
+ exit(ERROR_SYNCHRONIZATION);
+ }
+
+ /* set the result pointer */
+ handler_args->result = result;
+
+ /* the result has been calculated - awake the BCP thread to continue */
+ if (pthread_cond_signal(condition)) {
+ fprintf(stderr, "[BCP] ERROR: Blender thread couldn't signal the result condition!\n");
+ exit(ERROR_SYNCHRONIZATION);
+ }
+
+ if (pthread_mutex_unlock(mutex)) {
+ fprintf(stderr, "[BCP] ERROR: Blender thread couldn't unlock the result mutex!\n");
+ exit(ERROR_SYNCHRONIZATION);
+ }
+}
+
+// =========================================================
+// =========================================================
+
+/* fin */
Index: source/blender/commandport/blender/src/test.c
===================================================================
--- source/blender/commandport/blender/src/test.c (revision 0)
+++ source/blender/commandport/blender/src/test.c (revision 0)
@@ -0,0 +1,57 @@
+/*
+ * $Id: test.c, v 1.0 2007/05/18, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Main file for testing the string buffer.
+ *
+ * no header file.
+ *
+ */
+
+#include <stdio.h> /* for printf() and fprintf() */
+#include <sys/socket.h> /* for socket(), connect(), send(), and recv() */
+#include <arpa/inet.h> /* for sockaddr_in and inet_addr() */
+#include <stdlib.h> /* for atoi() and exit() */
+#include <string.h> /* for memset() */
+#include <unistd.h> /* for close() */
+
+#include "string_buffer.h"
+#include "string_buffer_test.h"
+
+int main(int argc, char *argv[])
+{
+ /* test (some of) my code */
+
+ /* testing the string_buffer */
+ string_buffer_test();
+
+ printf("bye...\n");
+ exit(0);
+}
+
+/* fin */
Index: source/blender/commandport/blender/src/bcp_python_utilities.c
===================================================================
--- source/blender/commandport/blender/src/bcp_python_utilities.c (revision 0)
+++ source/blender/commandport/blender/src/bcp_python_utilities.c (revision 0)
@@ -0,0 +1,388 @@
+/*
+ * $Id: bcp_python_utilities.c, v 1.0 2007/05/18, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Functions to execute python code in the blender server.
+ *
+ * header file: ../include/bcp_python_utilities.h
+ *
+ */
+
+#include <Python.h>
+
+#include "bcp_python_utilities.h"
+
+#include "py_stdouterr_buffer.h"
+#include "py_codeop.h"
+
+/* function declarations */
+int get_start_symbol(int input_mode);
+char* result_to_string_allocate(PyObject* result_obj, int result_print_mode);
+char* empty_string_allocate();
+
+/**
+ Run a c string in single input mode.
+ Note: For eval or file mode use 'py_input_run_allocate()'!
+
+ This is the mode used for the interactive interpreter loop.
+ It corresponds to the 'Py_single_input' Python grammar symbol.
+ Compare the documentation to the 'Py_single_input' token
+ in http://docs.python.org/api/veryhigh.html#l2h-78
+ */
+int py_single_input_run(const char* code, PyObject* namespace,
+ py_stdouterr_buffer stdouterr_buffer)
+{
+ PyGILState_STATE gstate;
+ int ret; /* the return code */
+ PyObject *compiled_code_obj, *result_obj, *exception, *error, *traceback;
+
+ /* aquire python thread */
+ gstate = PyGILState_Ensure();
+
+ /* redirect stdout/stderr to buffer */
+ py_stdouterr_buffer_redirect(stdouterr_buffer);
+
+ /* compile
+
+ Using 'compile_command()' rather than 'Py_CompileString()' as:
+
+ - 'compile_command()' contrary to 'Py_CompileString()' is able
+ to determine the difference between incomplete code and
+ erroneous code: In the first case NULL is returned; in the
+ second one an error is thrown. When the code is complete and
+ correct, the compiled code is returned in a Python object.
+
+ - the code is part of an official Python module - and hopefully
+ doesn't break with every new Python release :)
+ */
+ compiled_code_obj = compile_command(code);
+
+ /* check result of comilation */
+ if (compiled_code_obj == NULL) {
+
+ /* the code couldn't be compiled -
+ or it is incomplete, or there are syntax errors */
+
+ /* check for errors */
+ if (PyErr_Occurred()) {
+
+ /* some error occurred - print error message */
+
+ /* retrive error */
+ PyErr_Fetch(&exception, &error, &traceback);
+
+ /* restore the error for printing
+ Note: not owning exception, error, traceback anymore!
+ see documentation of PyErr_Restore(). */
+ PyErr_Restore(exception, error, traceback);
+
+ /* print it and set the corresponding return code */
+ PyErr_Print();
+ ret = PYTHON_ERROR;
+
+ } else {
+
+ /* the 'code' input is incomplete */
+
+ /* set the corresponding return code */
+ ret = PYTHON_INCOMPLETE_INPUT;
+ }
+
+ } else {
+
+ /* compilation was successfull */
+
+ /* evaluate code */
+ result_obj = PyEval_EvalCode((PyCodeObject*) compiled_code_obj,
+ namespace, namespace);
+
+ /* the result object is not needed:
+ the result is printed to the stdout buffer */
+ Py_XDECREF(result_obj);
+ Py_XDECREF(compiled_code_obj);
+
+ /* check result of evaluation for errors */
+ if (PyErr_Occurred()) {
+
+ /* an error occurred -
+ print it and set the corresponding return code */
+ PyErr_Print();
+ ret = PYTHON_ERROR;
+
+ } else {
+
+ /* the code was executed successfully */
+ ret = PYTHON_SUCCESS;
+ }
+ }
+
+ /* restore the original stdout/stderr */
+ py_stdouterr_buffer_restore(stdouterr_buffer);
+
+ /* release python thread */
+ PyGILState_Release(gstate);
+
+ /* return the result code */
+ return ret;
+}
+
+/**
+ Run a c string in eval or file mode.
+ Note: For single input mode use 'py_single_input_run()'!
+
+ Eval mode should be used for isolated Python expressions.
+ This mode corresponds to the 'Py_eval_input' Python grammar symbol.
+ Compare the documentation to the 'Py_eval_input' token
+ in http://docs.python.org/api/veryhigh.html#l2h-76
+
+ File mode should be used for sequences of Python statements
+ as read from a file or other source. This is the symbol to use when
+ compiling arbitrarily long Python source code.
+ This mode corresponds to the 'Py_file_input' Python grammar symbol.
+ Compare the documentation to the 'Py_file_input' token
+ in http://docs.python.org/api/veryhigh.html#l2h-77
+ */
+int py_input_run_allocate(const char* code,
+ const int input_mode,
+ const int result_print_mode,
+ char** result,
+ PyObject* namespace,
+ struct py_stdouterr_buffer_struct* stdouterr_buffer)
+{
+ int ret; /* the return code */
+ PyObject *compiled_code_obj, *result_obj;
+ PyGILState_STATE gstate;
+
+ /* aquire python thread */
+ gstate = PyGILState_Ensure();
+
+ /* redirect stdout/stderr to buffer */
+ py_stdouterr_buffer_redirect(stdouterr_buffer);
+
+ /* compile */
+ compiled_code_obj = Py_CompileString(code, "<stdin>", get_start_symbol(input_mode));
+
+ if (compiled_code_obj != NULL) {
+
+ /* compilation was successfull */
+
+ /* evaluate code */
+ result_obj = PyEval_EvalCode((PyCodeObject*) compiled_code_obj,
+ namespace, namespace);
+
+ if (PyErr_Occurred()) {
+
+ /* an error occurred -
+ print it and set the corresponding return code */
+ PyErr_Print();
+ ret = PYTHON_ERROR;
+
+ /* return a newly allocated emtpy string */
+ *result = empty_string_allocate();
+
+ } else {
+
+ /* the code was executed successfully */
+ ret = PYTHON_SUCCESS;
+
+ /* convert the result in a newly allocated string to return */
+ *result = result_to_string_allocate(result_obj, result_print_mode);
+
+ }
+
+ /* garbage collect the result object */
+ Py_XDECREF(result_obj);
+ Py_XDECREF(compiled_code_obj);
+
+ } else {
+
+ /* some non-syntax error
+ print it and set the corresponding return code */
+ PyErr_Print();
+ ret = PYTHON_ERROR;
+
+ /* return a newly allocated emtpy string */
+ *result = empty_string_allocate();
+
+ }
+
+ /* restore the original stdout/stderr */
+ py_stdouterr_buffer_restore(stdouterr_buffer);
+
+ /* release python thread */
+ PyGILState_Release(gstate);
+
+ /* return the result code */
+ return ret;
+}
+
+/**
+ Get the start symbol of the Python grammar corresponding to the
+ input mode given as parameter.
+*/
+int get_start_symbol(int input_mode)
+{
+ switch (input_mode) {
+ case SINGLE_INPUT_MODE : return Py_single_input; break;
+ case EVAL_INPUT_MODE : return Py_eval_input; break;
+ case FILE_INPUT_MODE : return Py_file_input; break;
+ default : return Py_file_input; break;
+ }
+}
+
+/**
+ Convert the Python result object returned by 'ObjectPyEval_EvalCode()'
+ to a string.
+
+ Depending on the parameter 'result_print_mode',
+ two different conversion functions can be used:
+
+ - BCP_REPR_PRINT_MODE 'PyObject_Repr()' is used to convert the result.
+
+ Example:
+
+ Strings are printed with "'":
+ 'THE MEANING OF PYTHON...'
+
+ - BCP_STR_PRINT_MODE 'PyObject_Str()' is used to convert the result.
+
+ Example:
+
+ Strings are printed without "'":
+ THE MEANING OF PYTHON...
+
+*/
+char* result_to_string_allocate(PyObject* result_obj, int result_print_mode)
+{
+ PyObject* result_str_obj;
+ PyGILState_STATE gstate;
+ char *result_str, *result_buffer;
+ int result_length;
+
+ /* check if a result object was given */
+ if (result_obj == NULL) {
+ fprintf(stderr, "[BCP] ERROR: Python didn't return any result!\n");
+ exit(1);
+ // todo: clean up
+ }
+
+ /* aquire python thread */
+ gstate = PyGILState_Ensure();
+
+ /* convert the result object to a string object */
+ if (result_print_mode == BCP_REPR_PRINT_MODE) {
+
+ /* compute a string representation of the result object
+ using 'PyObject_Repr()'
+
+ PyObject* PyObject_Repr(PyObject *o)
+ Return value: New reference.
+ Compute a string representation of object o.
+ Returns the string representation on success, NULL on failure.
+ This is the equivalent of the Python expression "repr(o)".
+ Called by the repr() built-in function and by reverse quotes.
+
+ (see http://docs.python.org/api/object.html)
+ */
+ result_str_obj = PyObject_Repr(result_obj);
+
+ } else if (result_print_mode == BCP_STR_PRINT_MODE) {
+
+ /* compute a string representation of the result object
+ using 'PyObject_Str();'
+
+ PyObject* PyObject_Str(PyObject *o)
+ Return value: New reference.
+ Compute a string representation of object o.
+ Returns the string representation on success, NULL on failure.
+ This is the equivalent of the Python expression "str(o)".
+ Called by the str() built-in function and by the print statement.
+
+ (see http://docs.python.org/api/object.html)
+ */
+ result_str_obj = PyObject_Str(result_obj);
+
+ } else {
+
+ /* this should never be the case - but... */
+ fprintf(stderr, "[BCP] ERROR: todo: unknown print result mode!\n" );
+
+ }
+
+ if (result_str_obj == NULL) {
+ fprintf(stderr, "[BCP] ERROR: Couldn't compute a string representation from the result object!\n");
+ fprintf(stderr, "todo: catch error and print / return error message!");
+ exit(1);
+ // todo: clean up
+ }
+
+ /* convert the python string object to a c string */
+ if (!PyArg_Parse(result_str_obj, "s", &result_str)) {
+ fprintf(stderr, "[BCP] ERROR: Couldn't convert the python result to a c string!\n");
+ exit(1); /* todo: catch error and print / return error message */
+ // todo: clean up
+ }
+
+ /* allocate a c string buffer to return the result */
+ result_length = strlen(result_str);
+ result_buffer = (char*) malloc((result_length + 1) * sizeof(char));
+
+ /* copy the result string into the buffer */
+ memcpy(result_buffer, result_str, result_length);
+ result_buffer[result_length]= '\0';
+
+ /* clean up */
+ Py_DECREF(result_str_obj);
+ // todo: there are other object references to count down!!!
+
+ /* release python thread */
+ PyGILState_Release(gstate);
+
+ /* return the allocated result buffer */
+ return result_buffer;
+}
+
+
+/**
+ return a newly allocated empty string.
+*/
+char* empty_string_allocate()
+{
+ /* allocate a c string buffer to return the result */
+ char* empty_string;
+ empty_string = (char*) malloc(1 * sizeof(char));
+
+ /* copy the result string into the buffer */
+ empty_string[0]= '\0';
+
+ /* return the allocated empty string */
+ return empty_string;
+}
+
+/* fin */
+
Index: source/blender/commandport/blender/src/py_codeop.c
===================================================================
--- source/blender/commandport/blender/src/py_codeop.c (revision 0)
+++ source/blender/commandport/blender/src/py_codeop.c (revision 0)
@@ -0,0 +1,85 @@
+/*
+ * $Id: py_stdouterr_buffer.c, v 1.0 2008/04/24, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * A C wrapper for the function 'compile_command()'
+ * from the Python 'codeop' module.
+ *
+ * The documentation for the Python 'codeop' module can be found
+ * here: http://docs.python.org/lib/module-codeop.html
+ *
+ * The function 'compile_command()' is used rather than
+ * 'Py_CompileString()' to implement the interactive read-eval-print
+ * loop as it is able to make the difference between incomplete input
+ * and erroneous input.
+ *
+ * header file: ../include/py_codeop.h
+ *
+ */
+
+#include <Python.h>
+
+#include "py_codeop.h"
+
+PyObject *compile_command(const char *source)
+{
+ PyGILState_STATE gstate;
+ PyObject *mod_codeop;
+ PyObject *func_compile_command, *obj_args, *obj_res;
+
+ /* aquire python thread */
+ gstate = PyGILState_Ensure();
+
+ /* get the 'compile_command()' function */
+ mod_codeop = PyImport_ImportModule("codeop");
+ func_compile_command = PyObject_GetAttrString(mod_codeop, "compile_command");
+ Py_DECREF(mod_codeop);
+
+ /* call it with the code from parameter 'source' */
+ obj_args = Py_BuildValue("(s)", source);
+ obj_res = PyEval_CallObject(func_compile_command, obj_args);
+ Py_DECREF(func_compile_command);
+ Py_DECREF(obj_args);
+
+ /* - Return a code object if the command is complete and valid
+ - Return NULL if the command is incomplete
+ */
+ if (obj_res == Py_None) {
+
+ Py_DECREF(obj_res);
+ obj_res = NULL;
+ }
+
+ /* release python thread */
+ PyGILState_Release(gstate);
+
+ /* return the code object or NULL for an incomplete python input */
+ return obj_res;
+}
+
+/* fin */
Index: source/blender/commandport/blender/src/commandport.c
===================================================================
--- source/blender/commandport/blender/src/commandport.c (revision 0)
+++ source/blender/commandport/blender/src/commandport.c (revision 0)
@@ -0,0 +1,121 @@
+/*
+ * $Id: commandport.c, v 1.0 2007/05/02, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Main Blender Command Port source file.
+ *
+ * All command port functionality in files outside of the
+ * directory `source/blender/commandport/' is implemented
+ * by calling the functions imported from this file:
+ *
+ * - `commandport_init()' initializes the command port and
+ * is called from function `main()'
+ * in file `source/creator/creator.c'
+ * when Blender is started with the `-c' / `--bcp' option;
+ *
+ * - `commandport_start()' starts the command port and
+ * is called from function `screenmain()'
+ * in file `source/blender/src/editscreen.c'
+ * when Blender is started with the `-c' / `--bcp' option;
+ *
+ * - When the command port thread receives a command sequence from
+ * a client, a `COMMAND_PORT_INPUT' event token is appended
+ * to the end of the Blender main event loop queue.
+ * When the Blender main event handler finds such a token,
+ * the function `commandport_handle_input_allocate()' is
+ * called to handle the event.
+ * See the Blender main event loop in function `screenmain()',
+ * file `source/blender/src/editscreen.c'.
+ *
+ * - When Blender was started with the `-c' / `--bcp' option
+ * the function `commandport_destroy()' cleans up the command port code
+ * when Blender exists.
+ * It is called from function `exit_usiblender()'
+ * in file `source/blender/src/usiblender.c'.
+ *
+ * header file: ../../include/commandport.h
+ *
+ */
+
+#include <stdio.h>
+
+#include "bcp_thread.h"
+#include "bcp_blender.h"
+#include "bcp_debug.h"
+
+#include "commandport.h"
+
+/* command port data */
+unsigned short g_bcp_port = 0;
+
+/**
+*/
+void commandport_init(unsigned short port)
+{
+ /* init the commandport data */
+ g_bcp_port = port;
+}
+
+/**
+*/
+void commandport_set_debug_level(int debug_level)
+{
+ /* init the BCP debug message level */
+ bcp_set_debug_level(debug_level);
+}
+
+/**
+*/
+void commandport_start()
+{
+ /* check if the command port was initialized */
+ if (g_bcp_port == 0) return;
+
+ /* if the command port was initialized, start it */
+ printf("Starting the Blender command port - listening on port %d.\n", g_bcp_port);
+ bcp_thread_start(g_bcp_port);
+}
+
+/**
+*/
+void commandport_handle_input_allocate(void* args)
+{
+ /* this is just a wrapper for the function defined in bcp_blender.h
+ in order ot be able to import everything from only one header: commandport.h
+ */
+ bcp_blender_queue_handle_input_allocate(args);
+}
+
+/**
+*/
+void commandport_destroy()
+{
+ /* nothing to do */
+}
+
+/* fin */
Index: source/blender/commandport/blender/src/bcp_python.c
===================================================================
--- source/blender/commandport/blender/src/bcp_python.c (revision 0)
+++ source/blender/commandport/blender/src/bcp_python.c (revision 0)
@@ -0,0 +1,912 @@
+/*
+ * $Id: bcp_python.c, v 1.0 2007/05/18, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Functionality ro run a BCP package in Blender.
+ *
+ * header file: ../include/bcp_python.h
+ *
+ */
+
+#include <Python.h>
+
+#include <compile.h> /* for the PyCodeObject needed by eval.h */
+#include <eval.h> /* for PyEval_EvalCode */
+
+#include "BPY_extern.h" /* for BPY_setup_armature_weakrefs() */
+
+#include "bcp_debug.h" /* bcp_debug() */
+#include "bcp_defaults.h"
+#include "bcp_meta_commands.h"
+#include "bcp_package.h"
+#include "bcp_python.h"
+#include "bcp_python_utilities.h"
+#include "error_codes.h"
+#include "py_stdouterr_buffer.h"
+
+void process_bcp_meta_command(char meta_command, int* input_mode, int* result_print_mode);
+PyObject* new_python_namespace();
+void delete_python_namespace(PyObject* namespace);
+void reinitialize_python_namespace(PyObject** namespace);
+char* compile_and_evaluate_allocate(int input_mode,
+ int result_print_mode,
+ py_stdouterr_buffer stdouterr_buffer,
+ PyObject** namespace,
+ char* script,
+ char** shell_input_buffer,
+ int* shell_input_buffer_length,
+ int* shell_input_line_count);
+char* process_python_single_input_allocate(py_stdouterr_buffer stdouterr_buffer,
+ PyObject** namespace,
+ char* line,
+ char** shell_input_buffer,
+ int* shell_input_buffer_length,
+ int* shell_input_line_count);
+
+char* process_python_input_allocate(int input_mode,
+ int result_print_mode,
+ py_stdouterr_buffer stdouterr_buffer,
+ PyObject** namespace,
+ char* code);
+/* tools */
+void print_input_mode(int input_mode);
+void dump_string(char* string);
+
+/**
+ Runs a python script
+ packed together with zero or more BCP meta commands
+ into a bcp package.
+
+ BCP Protocol:
+ - The package might start with zero or more BCP meta commands.
+ - There should be exacly ONE command string in every package.
+ - The command string should be the last element in the package.
+*/
+char* bcp_run_python_script_allocate(int* input_mode,
+ int* result_print_mode,
+ py_stdouterr_buffer stdouterr_buffer,
+ PyObject** namespace,
+ char* script,
+ char** shell_input_buffer,
+ int* shell_input_buffer_length,
+ int* shell_input_line_count)
+{
+ /* get debug level */
+ int debug = bcp_debug();
+ /* unused: int debug1 = (debug == 1); */
+ int debug2 = (debug >= 2);
+
+ bcp_package command_package;
+ bcp_package_enumerator enumerator;
+ void* elem;
+ char type;
+ char meta_command;
+ char* command = NULL;
+ char* result = NULL;
+
+ /* DEBUG */
+ if (debug2) {
+
+ /* print packed package */
+ printf(">>> the packed command package:\n");
+ printf(">>>%s<<<\n", script);
+ printf("\n");
+ }
+
+ /* unpack the client command package */
+ command_package = bcp_package_unpack(script);
+
+ /* DEBUG - short
+
+ printf("[DEBUG] dumping the client command package:\n");
+ dump_package(command_package);
+ printf("\n");
+ */
+
+ /* DEBUG - more detailed
+
+ dump_packed_package(package);
+ printf("\n");
+ */
+
+ /* make new package enumerator */
+ enumerator = bcp_package_enumerator_new(command_package);
+
+ /* print element */
+ while (1) {
+
+ /* get next element */
+ elem = bcp_package_enumerator_get_next_element(enumerator, &type);
+
+ /* if there are no more elements - exit */
+ if (type == BCP_PACKAGE_TYPE_EMPTY) break;
+
+ /* print value */
+ switch (type) {
+
+ case BCP_PACKAGE_TYPE_UNDEFINED:
+
+ /* ERROR - undefined package type */
+ fprintf(stderr, "ERROR in BCP protocol: Client send a bcp_package element with an unknown type!\n");
+ exit(ERROR_IN_BCP_PROTOCOL);
+ break;
+
+ case BCP_PACKAGE_TYPE_INT:
+
+ /* ERROR - client should only send
+ - command type elements and
+ - string type element
+ */
+ fprintf(stderr, "ERROR in BCP protocol: "
+ "Client send a bcp_package int element which is not defined by the BCP protocol!\n");
+ exit(ERROR_IN_BCP_PROTOCOL);
+ break;
+
+ case BCP_PACKAGE_TYPE_STRING:
+
+ /* every string send by the client is interpreted as command string */
+ command = (char*) elem;
+
+ /* DEBUG
+ printf("python command string: \"%s\"\n", command);
+ */
+
+ /* init the BCP Python namespace if not already done */
+ if (*namespace == NULL) {
+ *namespace = new_python_namespace();
+ }
+
+ /* execute the script and return the result
+ - in the current state of the BCP namespace (see 'handler->namespace')
+ - using the currently active BCP Input Mode (see 'handler->input_mode')
+ */
+ result = compile_and_evaluate_allocate(*input_mode,
+ *result_print_mode,
+ stdouterr_buffer,
+ namespace,
+ command,
+ shell_input_buffer,
+ shell_input_buffer_length,
+ shell_input_line_count);
+
+ /* never reached */
+ break;
+
+ case BCP_PACKAGE_TYPE_COMMAND:
+
+ /* the element is a BCP Meta Command */
+ meta_command = *((char*) elem);
+
+ /* DEBUG
+ printf("BCP meta command: %c\n", meta_command);
+ */
+
+ /* process the BCP Meta Command */
+ process_bcp_meta_command(meta_command, input_mode, result_print_mode);
+
+ break;
+
+ default:
+
+ /* ERROR - element with unknown type */
+ fprintf(stderr, "ERROR in BCP protocol: "
+ "Client send a bcp_package element with an unknown type!\n");
+ exit(ERROR_IN_BCP_PROTOCOL);
+ }
+ }
+
+ /* delete the package enumerator */
+ bcp_package_enumerator_delete(enumerator);
+
+ /* delete package */
+ bcp_package_delete(command_package);
+
+ /* return result */
+ return result;
+}
+
+/**
+ Process a BCP Meta Command.
+*/
+void process_bcp_meta_command(char meta_command, int* input_mode, int* result_print_mode)
+{
+ /* get debug level */
+ int debug = bcp_debug();
+
+ switch (meta_command) {
+
+ case BCP_SINGLE_MODE_COMMAND:
+
+ if (debug) printf("[BCP] Setting Input Mode to 'Single Input Mode'.\n");
+ *input_mode = SINGLE_INPUT_MODE;
+ break;
+
+ case BCP_EVAL_MODE_COMMAND:
+
+ if (debug) printf("[BCP] Setting Input Mode to 'Eval Input Mode'.\n");
+ *input_mode = EVAL_INPUT_MODE;
+ break;
+
+ case BCP_FILE_MODE_COMMAND:
+
+ if (debug) printf("[BCP] Setting Input Mode to 'File Input Mode'.\n");
+ *input_mode = FILE_INPUT_MODE;
+ break;
+
+ case BCP_REPR_PRINT_MODE_COMMAND:
+
+ if (debug) printf("[BCP] Setting Result Print Mode: Printing Result Representation.\n");
+ *result_print_mode = BCP_REPR_PRINT_MODE;
+ break;
+
+ case BCP_STR_PRINT_MODE_COMMAND:
+
+ if (debug) printf("[BCP] Setting Result Print Mode: Printing Result String.\n");
+ *result_print_mode = BCP_STR_PRINT_MODE;
+ break;
+
+ case BCP_RESET_COMMAND:
+
+ /* if (debug) */
+ printf("[BCP] Resetting the Command Port.\n");
+ printf("... todo ...\n");
+ break;
+
+ default:
+
+ /* the given meta command is not defined -
+ print a warning message and ignore the command
+ */
+ printf("[BCP] WARNING: '"
+ "' is not a valid BCP Meta Command and will be ignored!\n");
+ break;
+
+ } /* end of switch */
+}
+
+/**
+ Create a new Python namespace to evaluate Python scripts in.
+*/
+PyObject* new_python_namespace()
+{
+ PyObject* main_string_obj;
+ PyObject *namespace;
+ PyGILState_STATE gstate;
+
+ /* aquire python thread */
+ gstate = PyGILState_Ensure();
+
+ /* make new namespace dictionary */
+ namespace = PyDict_New();
+ if (namespace == NULL) {
+ printf( "[BCP] ERROR: Problems while trying to create a new python dictonary!\n" );
+ exit(1); /* todo: catch error and print / return error message */
+ }
+
+ /* initialize the namespace with the Python buildins */
+ if (PyDict_SetItemString(namespace, "__builtins__", PyEval_GetBuiltins())) {
+ printf( "[BCP] ERROR: Couldn't get the Python buildins!\n" );
+ exit(1); /* todo: catch error and print / return error message */
+ }
+
+ /* name the BCP namespace __main__ - like top-level Python program */
+ main_string_obj = PyString_FromString("__main__");
+ if (PyDict_SetItemString(namespace, "__name__", main_string_obj)) {
+ printf( "[BCP] ERROR: Couldn't name the BCP namespase as '__main__'!\n" );
+ exit(1); /* todo: catch error and print / return error message */
+ }
+ /* delete added string object:
+ When some object is just created to be added to the dictionary,
+ its reference count needs to be decremented so it can be reclaimed.
+ (Compare `EXPP_dict_set_item_str(dict, key, value)'
+ in blender/source/blender/python/api2_2x/gen_utils.c)
+ */
+ Py_DECREF(main_string_obj);
+
+ /* Without setting up the armature weakrefs the error
+ "RuntimeError: internal error - update_armature_weakrefs"
+ is thrown when executing the python function
+ `Blender.Window.EditMode(1)' via the command port.
+ */
+ if (!BPY_setup_armature_weakrefs()) {
+ fprintf(stderr, "[command port error] couldn't setup weakref dictionary!\n");
+ PyGILState_Release(gstate);
+ return NULL;
+ }
+
+ /* release python thread */
+ PyGILState_Release(gstate);
+
+ /* return the new namespace */
+ return namespace;
+}
+
+/**
+ Delete a new Python namespace created with 'new_python_namespace()'.
+*/
+void delete_python_namespace(PyObject* namespace)
+{
+ PyGILState_STATE gstate;
+
+ /* count down the reference counter of the namespace
+ to allow the Python garbage collector to
+ garbage collect the namespace object.
+
+ Note:
+ This works only if there is only one reference to the namespace object!
+ */
+ if (namespace != NULL ) {
+
+ /* aquire python thread */
+ gstate = PyGILState_Ensure();
+
+ Py_XDECREF(namespace);
+
+ /* release python thread */
+ PyGILState_Release(gstate);
+ }
+}
+
+/**
+ Sustitute the given namespace with a newly created one.
+*/
+void reinitialize_python_namespace(PyObject** namespace)
+{
+ /* delete the current namespace object */
+ delete_python_namespace(*namespace);
+
+ /* ...and substitute it with a new one */
+ *namespace = new_python_namespace();
+}
+
+/**
+ Compile and evaluate a Python script given as a c string.
+ The result is returned as a newly allocated c string
+ and has to be freed after usage.
+
+ The second parameter start specifies the start token that should be used
+ to parse the source code and should be one of
+ 'Py_eval_input', 'Py_file_input' and 'Py_single_input'.
+
+ Compare the documentation for
+ 'PyRun_StringFlags()' ( http://docs.python.org/api/veryhigh.html#l2h-69 ) and
+ 'Py_CompileStringFlags()' ( http://docs.python.org/api/veryhigh.html#l2h-74 ).
+
+
+ * Shell Evaluation Modes
+
+ Three different modes can be used from the interactive bash shell.
+ Each "shell evaluation mode" corresponds to a Python grammar start symbol which will be used to parse
+ the entered string and to a strategy which determines the usage of the parsed information.
+
+ The following macros specify the shell evaluation mode:
+
+ ------------------------------------------------------------
+ macro - corresponding Python grammar start symbol
+ ------------------------------------------------------------
+ BCP_SINGLE_MODE - Py_single_input
+ BCP_EVAL_MODE - Py_eval_input
+ BCP_FILE_MODE - Py_file_input
+ ------------------------------------------------------------
+
+ Description:
+
+ - Py_single_input
+
+ The start symbol from the Python grammar for a single statement; for use with Py_CompileString(). This is the symbol used for the interactive interpreter loop.
+
+ See Python documentation: http://docs.python.org/api/veryhigh.html#l2h-78
+
+ - Py_eval_input
+
+ The start symbol from the Python grammar for isolated expressions; for use with Py_CompileString().
+
+ See Python documentation: http://docs.python.org/api/veryhigh.html#l2h-76
+
+
+ - Py_file_input
+
+ The start symbol from the Python grammar for sequences of statements as read from a file or other source; for use with Py_CompileString(). This is the symbol to use when compiling arbitrarily long Python source code.
+
+ See Python documentation: http://docs.python.org/api/veryhigh.html#l2h-77
+
+
+*/
+
+char* compile_and_evaluate_allocate(int input_mode,
+ int result_print_mode,
+ py_stdouterr_buffer stdouterr_buffer,
+ PyObject** namespace,
+ char* script,
+ char** shell_input_buffer,
+ int* shell_input_buffer_length,
+ int* shell_input_line_count)
+{
+ switch (input_mode) {
+
+ case SINGLE_INPUT_MODE :
+
+ return process_python_single_input_allocate(stdouterr_buffer,
+ namespace,
+ script,
+ shell_input_buffer,
+ shell_input_buffer_length,
+ shell_input_line_count);
+
+ case EVAL_INPUT_MODE :
+ case FILE_INPUT_MODE :
+
+ return process_python_input_allocate(input_mode,
+ result_print_mode,
+ stdouterr_buffer,
+ namespace,
+ script);
+
+
+
+ default :
+ fprintf(stderr, "[BCP] ERROR: Unknown input mode: %d\n", input_mode);
+ exit(1);
+ }
+}
+
+/**
+ Note: The following function was written using code from the
+ Extending/Embedding FAQ - see:
+ http://www.python.org/doc/faq/extending/#how-do-i-tell-incomplete-input-from-invalid-input
+ which in turn was inspired by code from Alex Farber :)
+
+ Returns NULL if the imput is still incomplete or
+ an error occurred.
+*/
+char* process_python_single_input_allocate(py_stdouterr_buffer stdouterr_buffer,
+ PyObject** namespace,
+ char* line,
+ char** shell_input_buffer,
+ int* shell_input_buffer_length,
+ int* shell_input_line_count)
+{
+ /* get debug level */
+ int debug, debug1, debug2;
+ int ret, result_code;
+ char *stdout_string, *stderr_string, *packed_result, **code;
+ int *clen, *lcount, llen;
+ bcp_package result_package;
+
+ /* making aliases for readability */
+ code = shell_input_buffer;
+ clen = shell_input_buffer_length;
+ lcount = shell_input_line_count;
+ llen = 0; /* lengths of line, code */
+
+ /* get debug level */
+ debug = bcp_debug();
+ debug1 = (debug == 1);
+ debug2 = (debug >= 2);
+
+ /* make a package for sending back the result of the current python execution */
+ result_package = bcp_package_new();
+
+ llen = strlen(line); /* newly entered line */
+
+ if (*code == NULL) { /* nothing in the code buffer yet */
+ *clen = 0;
+ *lcount = 0; /* line counter is 0 */
+ } else {
+ *clen = strlen(*code); /* there are already some code lines
+ in the code buffer and the current
+ newly entered line will be added
+ to them
+ */
+ }
+
+ *code = realloc(*code, *clen + llen + 2);
+ if (NULL == *code) { /* out of memory */
+
+ /* ERROR: out of memory */
+ fprintf(stderr, "[BCP] ERROR: Out of memory!");
+ exit (1);
+ }
+
+ if (0 == *clen) { /* the code buffer was empty */
+ (*code)[0] = '\0'; /* to keep strncat happy */
+ }
+
+ strncat(*code, line, llen); /* append line to the code buffer
+ Note: the line (command) is freed by the
+ `bcp_handle_client()' loop! */
+ (*code)[*clen + llen ] = '\n'; /* append '\n' to the code buffer */
+ (*code)[*clen + llen + 1] = '\0'; /* terminate code buffer with NULL caracter */
+ (*lcount)++; /* increment line counter */
+
+ /* DEBUG */
+ /* print the content of stdout/stderr buffer */
+ if (debug1) {
+
+ /* short: */
+ printf(">>> ========================================================\n");
+ printf(">>> - new input line: '%s'\n", line);
+ printf(">>> - current input: '%s'\n", *code);
+
+ } else if (debug2) {
+
+ /* longer: */
+ printf(">>> ========================================================\n");
+ printf(">>> - debug message level: %d\n", debug);
+ printf(">>> \n");
+ printf(">>> - new input line:\n");
+ printf(">>> \n");
+ printf(">>> - length: %d\n", llen);
+ printf(">>> - content: '%s'\n", line);
+ printf(">>> - dump: "); dump_string(line); printf("\n");
+ printf(">>> \n");
+ printf(">>> - current input:\n");
+ printf(">>> \n");
+ printf(">>> - length: %d\n", *clen);
+ printf(">>> - lines: %d\n", *lcount);
+ printf(">>> - content: '%s'\n", *code);
+ printf(">>> - dump: "); dump_string(*code); printf("\n");
+ printf(">>> \n");
+ }
+
+ /* try to execute the code
+ received until now from the shell */
+ ret = py_single_input_run(*code, *namespace, stdouterr_buffer);
+
+ result_code = BCP_RESULT_CODE_UNDEFINED;
+ if (ret == PYTHON_SUCCESS) {
+
+ /* compiled -
+
+ As in the python shell
+ an input is accepted as complete and executed if
+ - it can be interpreted / parsed as a complete input
+ and it is one line long
+ - it can be interpreted / parsed as a complete input
+ and it is more than one line long
+ and it is terminated with an empty line
+ */
+ if (*lcount == 1 || /* first input line, prompt '>>> ' */
+ (*lcount > 1 && (llen == 0)) /* not first input line and
+ input line is empty, prompt '... ' */
+ ) {
+
+ /* The python evaluation was successful */
+ result_code = BCP_RESULT_CODE_SUCCESS;
+
+ free(*code);
+ *code = NULL; /* nothing in the code buffer yet */
+ *clen = 0;
+ *lcount = 0; /* line counter is 0 */
+
+ } else {
+
+
+ /* The entered python code is incomplete
+
+ The code could be successfully executed
+ but the input is not complete as
+ - it is more than one line long
+ (the current line is not the first line) and
+ - it was NOT terminated with an empty line
+ (as the current line is not empty).
+
+ Send a message back to the client indicating
+ that the blender server waits for the next line:
+ */
+ result_code = BCP_RESULT_CODE_INCOMPLETE_INPUT;
+
+ }
+
+ } else if (ret == PYTHON_INCOMPLETE_INPUT) {
+
+ /* The entered python code is incomplete
+ and the blender server waits for more
+ input lines to complete the input */
+ result_code = BCP_RESULT_CODE_INCOMPLETE_INPUT;
+
+ /* don't do anything
+ - the code in (*code) will be prepended to the next input */
+
+ } else if (ret == PYTHON_ERROR) {
+
+ /* An error occured during the
+ evaluation ot the python code */
+ result_code = BCP_RESULT_CODE_ERROR;
+
+ /* free the memory of the newly entered current line */
+ free(*code);
+ *code = NULL;
+
+ } else {
+
+ /*
+ ERROR - This line should never be reached
+ as the last cases should deal with all possible results
+ */
+ result_code = BCP_RESULT_CODE_UNDEFINED;
+
+ /* free the memory of the newly entered current line */
+ free(*code);
+ *code = NULL;
+
+ }
+
+ /* DEBUG */
+ if (debug) {
+
+ /* print result code (see bcp_meta_commands.h) */
+ printf(">>> - result code: %d (", result_code);
+ switch (result_code) {
+ case BCP_RESULT_CODE_SUCCESS : printf("BCP_RESULT_CODE_SUCCESS"); break;
+ case BCP_RESULT_CODE_INCOMPLETE_INPUT : printf("BCP_RESULT_CODE_INCOMPLETE_INPUT"); break;
+ case BCP_RESULT_CODE_ERROR : printf("BCP_RESULT_CODE_ERROR"); break;
+ case BCP_RESULT_CODE_UNDEFINED : printf("BCP_RESULT_CODE_UNDEFINED"); break;
+ case BCP_RESULT_CODE_EMPTY_INPUT : printf("BCP_RESULT_CODE_EMPTY_INPUT"); break;
+ default : printf("ERROR: unknown result code!"); break;
+ }
+ printf(")\n");
+
+ /* short: */
+ /* print the contenet of stdout/stderr buffer */
+ fprintf(stderr, ">>> - stderr: '");
+ py_stdouterr_buffer_print_stderr(stdouterr_buffer);
+ fprintf(stderr, "'\n");
+ fflush(stderr);
+ fprintf(stdout, ">>> - stdout: '");
+ py_stdouterr_buffer_print_stdout(stdouterr_buffer);
+ fprintf(stdout, "'\n");
+ fflush(stdout);
+ }
+
+ /* add the result code */
+ bcp_package_add_int(result_package, result_code);
+
+ /* in python single input mode the result is directly printed to stdout
+ and there is no other result returned.
+ But as the BCP protocol in order to be simple always sends a
+ result string as second element, an empty dummy result string is added.
+ */
+ bcp_package_add_string(result_package, "");
+
+ /* add the blender/python stdout string */
+ stdout_string = NULL;
+ stdout_string = py_stdouterr_buffer_get_stdout_allocate(stdouterr_buffer);
+ bcp_package_add_string(result_package, stdout_string);
+
+ /* add the blender/python stderr string */
+ stderr_string = py_stdouterr_buffer_get_stderr_allocate(stdouterr_buffer);
+ bcp_package_add_string(result_package, stderr_string);
+
+ /* pack the buffer into a newly allocated string */
+ packed_result = bcp_package_pack_allocate(result_package);
+
+ /* free the strout / stderr buffers */
+ free(stdout_string);
+ stdout_string = NULL;
+ free(stderr_string);
+ stderr_string = NULL;
+
+ /* DEBUG */
+ if (debug2) {
+
+ /* print packed package */
+ printf(">>> - the packed package: `\n");
+ printf("%s'\n", packed_result);
+ }
+
+ if (debug) printf(">>> ========================================================\n");
+
+ /* delete package */
+ bcp_package_delete(result_package);
+
+ /*
+ clear stdout/stderr buffers
+
+ Note:
+ The buffer can be cleared only after the result package
+ was packed into a newly allocated packed buffer string representation
+ becausee the unpacked package just holds the pointers to the added strings
+ and not a copy of the string itself.
+ */
+ py_stdouterr_buffer_clear_buffers(stdouterr_buffer);
+
+ /* return the allocated result buffer */
+ return packed_result;
+}
+
+/**
+ todo.................
+
+Process a complete python input (eval or file input but not single input)
+
+
+ Note: The following function was written using code from the
+ Extending/Embedding FAQ - see:
+ http://www.python.org/doc/faq/extending/#how-do-i-tell-incomplete-input-from-invalid-input
+ which in turn was inspired by code from Alex Farber :)
+
+ Returns NULL if the imput is still incomplete or
+ an error occurred.
+*/
+char* process_python_input_allocate(int input_mode,
+ int result_print_mode,
+ py_stdouterr_buffer stdouterr_buffer,
+ PyObject** namespace,
+ char* code)
+{
+ int debug, debug2;
+ bcp_package result_package;
+ int ret, result_code;
+ char *result, *stdout_string, *stderr_string, *packed_result;
+
+ /* get debug level */
+ debug = bcp_debug();
+ debug2 = (debug >= 2);
+
+ /* make a package for sending back the result of the current python execution */
+ result_package = bcp_package_new();
+
+ /* DEBUG */
+ if (debug) {
+
+ /* print the content of stdout/stderr buffer */
+
+ /* short: */
+ printf(">>> ========================================================\n");
+ printf(">>> debug: %d\n", debug);
+ printf(">>> - input mode: "); print_input_mode(input_mode); printf("\n");
+ printf(">>> - input: '%s'\n", code);
+ }
+
+ /* try to execute the code
+ received until now from the shell */
+ result = NULL;
+ ret = py_input_run_allocate(code, input_mode, result_print_mode, &result,
+ *namespace, stdouterr_buffer);
+
+ /* convert the result into the BCP result code */
+ result_code = BCP_RESULT_CODE_UNDEFINED;
+ switch (ret) {
+ case PYTHON_SUCCESS : result_code = BCP_RESULT_CODE_SUCCESS; break;
+ case PYTHON_ERROR : result_code = BCP_RESULT_CODE_ERROR; break;
+ default : result_code = BCP_RESULT_CODE_UNDEFINED; break;
+ }
+
+ /* DEBUG */
+ if (debug) {
+
+ /* print result code (see bcp_meta_commands.h) */
+ printf(">>> - result code: %d (", result_code);
+
+ switch (result_code) {
+ case BCP_RESULT_CODE_SUCCESS : printf("BCP_RESULT_CODE_SUCCESS"); break;
+ case BCP_RESULT_CODE_ERROR : printf("BCP_RESULT_CODE_ERROR"); break;
+ case BCP_RESULT_CODE_UNDEFINED : printf("BCP_RESULT_CODE_UNDEFINED"); break;
+ default : printf("ERROR: unknown result code!"); break;
+ }
+ printf(")\n");
+
+ /* print the result */
+ printf(">>> - result: '%s'\n", result);
+
+ /* print the contenet of stdout/stderr buffer */
+ fprintf(stderr, ">>> - stderr: '");
+ py_stdouterr_buffer_print_stderr(stdouterr_buffer);
+ fprintf(stderr, "'\n");
+ fflush(stderr);
+ fprintf(stdout, ">>> - stdout: '");
+ py_stdouterr_buffer_print_stdout(stdouterr_buffer);
+ fprintf(stdout, "'\n");
+ fflush(stdout);
+ printf(">>> ========================================================\n");
+ }
+
+ /* add the result code */
+ bcp_package_add_int(result_package, result_code);
+
+ /* add the result coded as string */
+ bcp_package_add_string(result_package, result);
+
+ /* add the blender/python stdout string */
+ stdout_string = py_stdouterr_buffer_get_stdout_allocate(stdouterr_buffer);
+ bcp_package_add_string(result_package, stdout_string);
+
+ /* add the blender/python stderr string */
+ stderr_string = py_stdouterr_buffer_get_stderr_allocate(stdouterr_buffer);
+ bcp_package_add_string(result_package, stderr_string);
+
+ /* pack the buffer into a newly allocated string */
+ packed_result = bcp_package_pack_allocate(result_package);
+
+ /* free the result / strout / stderr buffers */
+ free(result);
+ result = NULL;
+ free(stdout_string);
+ stdout_string = NULL;
+ free(stderr_string);
+ stderr_string = NULL;
+
+ /* DEBUG */
+ if (debug2) {
+
+ /* print packed package */
+ printf(">>> the packed package:\n");
+ printf(">>>%s<<<\n", packed_result);
+ printf("\n");
+ }
+
+ /* delete package */
+ bcp_package_delete(result_package);
+
+ /*
+ clear stdout/stderr buffers
+
+ Note:
+ The buffer can be cleared only after the result package
+ was packed into a newly allocated packed buffer string representation
+ becausee the unpacked package just holds the pointers to the added strings
+ and not a copy of the string itself.
+ */
+ py_stdouterr_buffer_clear_buffers(stdouterr_buffer);
+
+ /* return the allocated result buffer */
+ return packed_result;
+}
+
+/* tools */
+
+/**
+ Print given input mode.
+*/
+void print_input_mode(int input_mode)
+{
+ switch (input_mode) {
+ case SINGLE_INPUT_MODE : printf("SINGLE_INPUT_MODE"); break;
+ case EVAL_INPUT_MODE : printf("EVAL_INPUT_MODE"); break;
+ case FILE_INPUT_MODE : printf("FILE_INPUT_MODE"); break;
+ default : printf("ERROR: Undefined input mode!"); break;
+ }
+}
+
+/**
+ DEBUG - Dump a string to stdout.
+*/
+void dump_string(char* string)
+{
+ for( ; *string != '\0'; string++) {
+ printf("%X ", *string);
+ }
+ printf("%X", *string);
+}
+
+// =========================================================
+// =========================================================
+
+/* fin */
+
Index: source/blender/commandport/blender/src/SConscript
===================================================================
--- source/blender/commandport/blender/src/SConscript (revision 0)
+++ source/blender/commandport/blender/src/SConscript (revision 0)
@@ -0,0 +1,54 @@
+# -*- mode: python -*-
+#
+# $Id: SConscript, v 1.0 2007/05/02, dietrich, tokyo $
+#
+# ***** BEGIN GPL 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.
+#
+# 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,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 by the Blender Foundation.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Author: Dietrich Bollmann
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# blender command port source build file
+#
+
+Import ('env')
+
+sources = env.Glob('*.c')
+
+incs = '''
+ ../include
+ ../../include
+ ../../utilities/include
+ #/intern/guardedalloc
+ #/source/blender/blenkernel
+ #/source/blender/blenlib
+ #/source/blender/include
+ #/source/blender/makesdna
+ #/source/blender/python
+'''
+
+incs += ' ' + env['BF_PYTHON_INC']
+
+env.BlenderLib ( 'blender_commandport', sources, Split(incs), [], libtype=['blender'], priority=[0] )
+
+# fin.
Index: source/blender/commandport/blender/src/bcp_server.c
===================================================================
--- source/blender/commandport/blender/src/bcp_server.c (revision 0)
+++ source/blender/commandport/blender/src/bcp_server.c (revision 0)
@@ -0,0 +1,170 @@
+/*
+ * $Id: bcp_server.c, v 1.0 2007/05/02, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Blender command port server.
+ *
+ * header file: ../include/bcp_server.h]]
+ *
+ */
+
+#include <stdio.h> /* printf(), fprintf() */
+#include <sys/socket.h> /* socket(), bind(), connect() */
+#include <arpa/inet.h> /* sockaddr_in, inet_ntoa() */
+#include <pthread.h> /* pthread */
+#include <stdlib.h> /* atoi(), exit() */
+#include <string.h> /* memset() */
+#include <unistd.h> /* close() */
+
+#include "error_codes.h" /* error codes */
+#include "bcp_handle_client.h" /* bcp_handle_client() */
+#include "bcp_debug.h" /* bcp_debug() */
+
+#define MAXPENDING 5 /* Maximum outstanding connection requests */
+
+/** Structure with arguments to pass to client thread */
+struct bcp_client_thread_args
+{
+ int client_socket;
+};
+
+void bcp_client_thread_start(int client_socket);
+void* bcp_client_thread(void* args);
+
+/**
+ `port' is the BCP server port
+*/
+void bcp_server(unsigned short port)
+{
+ int server_socket; /* Socket descriptor for server */
+ int client_socket; /* Socket descriptor for client */
+ struct sockaddr_in server_address; /* Local address */
+ struct sockaddr_in client_address; /* Client address */
+ unsigned int length; /* Length of client address data structure */
+
+ /* Create socket for incoming connections */
+ if ((server_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
+ fprintf(stderr, "Couldn't create socket!\n");
+ exit(ERROR_SOCKET);
+ }
+
+ /* Construct local address structure */
+ memset(&server_address, 0, sizeof(server_address)); /* Zero out structure */
+ server_address.sin_family = AF_INET; /* Internet address family */
+ server_address.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
+ server_address.sin_port = htons(port); /* Local port */
+
+ /* Bind to the local address */
+ if (bind(server_socket, (struct sockaddr *) &server_address, sizeof(server_address)) < 0) {
+ fprintf(stderr, "Couldn't bind socket!\n");
+ exit(ERROR_SOCKET);
+ }
+
+ /* Mark the socket so it will listen for incoming connections */
+ if (listen(server_socket, MAXPENDING) < 0) {
+ fprintf(stderr, "Couldn't listen on socket!\n");
+ exit(ERROR_SOCKET);
+ }
+
+ while (1) /* Run forever */
+ {
+ /* Set the size of the in-out parameter */
+ length = sizeof(client_address);
+
+ /* Wait for a client to connect */
+ if ((client_socket = accept(server_socket,
+ (struct sockaddr *) &client_address,
+ &length)) < 0) {
+ fprintf(stderr, "Couldn't accept client!\n");
+ exit(ERROR_SOCKET);
+ }
+
+ /* client_socket is connected to a client! */
+ printf("Handling client %s\n", inet_ntoa(client_address.sin_addr));
+
+ /* start a thread to handle the client */
+ bcp_client_thread_start(client_socket);
+ }
+ /* NOT REACHED */
+}
+
+/**
+ Start a Blender Command Port client thread.
+ */
+void bcp_client_thread_start(int client_socket)
+{
+ int ret;
+ pthread_t client_thread;
+
+ /* allocate memory for the client thread args */
+ struct bcp_client_thread_args* args;
+ args = (struct bcp_client_thread_args *) malloc(sizeof(struct bcp_client_thread_args));
+
+ args->client_socket = client_socket;
+ ret = pthread_create(&client_thread, NULL, bcp_client_thread, (void*) args);
+
+ /* did the thread creation succeed? */
+ if (ret != 0) {
+ printf("ERROR: Couldn't create a Blender Command Port client thread!\n");
+ } else if (bcp_debug()) {
+ printf("Blender Command Port client thread %x started!\n",
+ (int) client_thread);
+ }
+}
+
+/**
+ Client thread.
+*/
+void* bcp_client_thread(void* args)
+{
+ struct bcp_client_thread_args *targs;
+ int client_socket;
+ pthread_t client_thread;
+
+ /* extract arguments */
+ targs = (struct bcp_client_thread_args *) args;
+ client_socket = targs->client_socket;
+ free(targs);
+ args = targs = NULL;
+
+ /* get my thread handle */
+ client_thread = pthread_self();
+ if (bcp_debug())
+ printf("Blender Command Port client thread %x running!\n", (int) client_thread);
+
+ /* Detache the Blender Command Port thread */
+ pthread_detach(client_thread);
+
+ /* handle client */
+ bcp_handle_client(client_socket);
+
+ /* exit */
+ pthread_exit( NULL );
+}
+
+/* fin */
Index: source/blender/commandport/blender/src/bcp_thread.c
===================================================================
--- source/blender/commandport/blender/src/bcp_thread.c (revision 0)
+++ source/blender/commandport/blender/src/bcp_thread.c (revision 0)
@@ -0,0 +1,124 @@
+/*
+ * $Id: bcp_thread.c, v 1.0 2007/05/02, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * the command port server is running in its own thread.
+ * The communication with the main Blender thread is done
+ * via the Blender queue.
+ *
+ * header file: ../include/bcp_thread.h
+ *
+ */
+
+#include <stdio.h>
+#include <string.h> /* memset() */
+#include <errno.h>
+#include <pthread.h>
+#include <sys/socket.h> /* socket(), bind(), and connect() */
+#include <arpa/inet.h> /* sockaddr_in and inet_ntoa() */
+#include <stdlib.h> /* atoi() and exit() */
+
+#include "bcp_debug.h" /* bcp_debug() */
+#include "bcp_server.h"
+
+#include "bcp_thread.h"
+
+/** Structure with arguments to pass to server thread */
+struct bcp_server_thread_args
+{
+ unsigned short server_port; /* BCP port */
+};
+
+void *blender_command_port_server_thread(void *args);
+
+/**
+ BCP Error handling function
+*/
+void bcp_error(char *err_msg)
+{
+ perror( err_msg );
+ exit( 1 );
+}
+
+/**
+ Start the Blender Command Port thread.
+ */
+void bcp_thread_start(unsigned short port)
+{
+ int ret;
+ pthread_t bcpthread;
+
+ /* allocate memory for command port thread args */
+ struct bcp_server_thread_args* args;
+ args = (struct bcp_server_thread_args *) malloc(sizeof(struct bcp_server_thread_args));
+
+ args->server_port = port;
+ ret = pthread_create(&bcpthread, NULL,
+ blender_command_port_server_thread,
+ (void*) args);
+
+ /* did the thread creation succeed? */
+ if (ret != 0) {
+ bcp_error("Can't create Blender Command Port server thread!\n");
+ } else if (bcp_debug()) {
+ printf("Blender Command Port server thread %x started "
+ "(port: %hu)!\n",
+ (int) bcpthread, port);
+ }
+}
+
+/**
+ */
+void *blender_command_port_server_thread(void* args)
+{
+ struct bcp_server_thread_args *targs;
+ unsigned short server_port;
+ pthread_t server_thread;
+
+ /* extract arguments */
+ targs = (struct bcp_server_thread_args *) args;
+ server_port = targs->server_port;
+ free(targs);
+ args = targs = NULL;
+
+ /* get my thread handle */
+ server_thread = pthread_self();
+ if (bcp_debug())
+ printf("Blender Command Port server thread %x running!\n", (int) server_thread);
+
+ /* Detache the Blender Command Port thread */
+ pthread_detach(server_thread);
+
+ /* starting the bcp_server */
+ bcp_server(server_port);
+
+ /* exit */
+ pthread_exit( NULL );
+}
+
+/* fin */
Index: source/blender/commandport/blender/src/py_stdouterr_buffer_test.c
===================================================================
--- source/blender/commandport/blender/src/py_stdouterr_buffer_test.c (revision 0)
+++ source/blender/commandport/blender/src/py_stdouterr_buffer_test.c (revision 0)
@@ -0,0 +1,139 @@
+/*
+ * $Id: py_stdouterr_buffer_test.c, v 1.0 2007/05/18, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Main test file for testing the
+ * functions to redirect the stdout / stderr into a string buffer.
+ *
+ * no header file.
+ *
+ */
+
+/* fetch and call objects in modules */
+
+#include <Python.h>
+
+#include "py_stdouterr_buffer.h"
+
+char buffer[100];
+
+void message_stdout(int i, int j) {
+ sprintf(buffer, "<stdout,%d,%d>\n", i, j);
+ PySys_WriteStdout(buffer);
+}
+
+void message_stderr(int i, int j) {
+ sprintf(buffer, "<stderr,%d,%d>\n", i, j);
+ PySys_WriteStderr(buffer);
+}
+
+main() {
+ /* initialize python */
+ Py_Initialize();
+
+ printf("\n");
+ printf(">>> ========================================================\n");
+ printf(">>> redirect stdin / stdout to write into a string :)\n");
+ printf(">>> --------------------------------------------------------\n");
+ printf("\n");
+
+ /* make a stdout/stderr string buffer */
+ py_stdouterr_buffer buffer;
+ buffer = py_stdouterr_buffer_new();
+
+ int i, j;
+ for (i = 0, j = 0; i < 3; i++, j = 0) {
+
+ printf(">>> ========================================================\n");
+ printf(">>> experiment %d\n", i);
+ printf(">>> --------------------------------------------------------\n");
+ printf("\n");
+
+ /* print something - this should go to stdout/stderr of the terminal :) */
+ message_stdout(i, j);
+ message_stderr(i, j);
+ j++;
+
+ /* redirect stdout/stderr to buffer */
+ py_stdouterr_buffer_redirect(buffer);
+
+ /* print something - this should go to the buffer :) */
+ message_stdout(i, j);
+ message_stderr(i, j);
+ j++;
+ message_stdout(i, j);
+ message_stderr(i, j);
+ j++;
+
+ /* restore the original stdout/stderr */
+ py_stdouterr_buffer_restore(buffer);
+
+ /* print something - this should go to stdout again :) */
+ message_stdout(i, j);
+ message_stderr(i, j);
+ j++;
+
+ /* retrive buffered stdout */
+ char* stdout_str;
+ stdout_str = py_stdouterr_buffer_get_stdout_allocate(buffer);
+ printf("\n");
+ printf("# here comes the buffered stdout:\n");
+ printf("\n");
+ printf(">>>%s<<<\n", stdout_str);
+ printf("\n");
+ free(stdout_str);
+ stdout_str = NULL;
+
+ /* retrive buffered stderr */
+ char* stderr_str;
+ stderr_str = py_stdouterr_buffer_get_stderr_allocate(buffer);
+ printf("# here comes the buffered stderr:\n");
+ printf("\n");
+ printf(">>>%s<<<\n", stderr_str);
+ printf("\n");
+ free(stderr_str);
+ stderr_str = NULL;
+
+ /* the buffers have to be cleared! */
+ py_stdouterr_buffer_clear_buffers(buffer);
+ }
+
+ printf(">>> ========================================================\n");
+ printf(">>> ========================================================\n");
+ printf("\n");
+
+ /* free the buffer */
+ py_stdouterr_buffer_delete(buffer);
+ buffer = NULL;
+
+ /* done :) */
+ printf("bye... :)\n");
+ printf("\n");
+}
+
+/* fin */
Index: source/blender/commandport/blender/src/py_stdouterr_buffer.c
===================================================================
--- source/blender/commandport/blender/src/py_stdouterr_buffer.c (revision 0)
+++ source/blender/commandport/blender/src/py_stdouterr_buffer.c (revision 0)
@@ -0,0 +1,354 @@
+/*
+ * $Id: py_stdouterr_buffer.c, v 1.0 2007/05/01, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * A buffer for saving Pythons stdout / stderr
+ * and accessing it after in form of a c string buffer.
+ *
+ * header file: ../include/py_stdouterr_buffer.h
+ *
+ */
+
+#include <Python.h>
+
+#include "error_codes.h"
+
+#include "py_stdouterr_buffer.h"
+
+
+typedef struct py_stdouterr_buffer_struct {
+
+ /* the needed modules */
+ PyObject *mod_sys;
+ PyObject *mod_cStringIO;
+
+ /* the initial stdout/stderr are stored here */
+ PyObject *stdout_obj;
+ PyObject *stderr_obj;
+
+ /* string buffer to store stdout/stderr */
+ PyObject *outbuf_obj;
+ PyObject *errbuf_obj;
+
+} py_stdouterr_buffer_struct;
+
+char* py_buffer_get_content_allocate(PyObject *buffer);
+
+/**
+ Make a new python io buffer.
+*/
+py_stdouterr_buffer py_stdouterr_buffer_new()
+{
+ py_stdouterr_buffer buffer;
+ PyGILState_STATE gstate;
+
+ buffer = (py_stdouterr_buffer) malloc(sizeof(py_stdouterr_buffer_struct));
+
+ if (buffer == NULL) {
+ fprintf(stderr, "Couldn't allocate memory for new py_stdouterr_buffer!\n");
+ exit(ERROR_MEMORY);
+ }
+
+ /* aquire python thread */
+ gstate = PyGILState_Ensure();
+
+ buffer->mod_sys = PyImport_ImportModule("sys");
+ buffer->mod_cStringIO = PyImport_ImportModule("cStringIO");
+
+ /* store stdout and stderr */
+ buffer->stdout_obj = PyObject_GetAttrString(buffer->mod_sys, "stdout");
+ buffer->stderr_obj = PyObject_GetAttrString(buffer->mod_sys, "stderr");
+
+ /* make new string buffer for stdout and stderr */
+ PyObject *func_StringIO, *args_StringIO;
+ func_StringIO = PyObject_GetAttrString(buffer->mod_cStringIO, "StringIO");
+ args_StringIO = Py_BuildValue("()");
+ buffer->outbuf_obj = PyEval_CallObject(func_StringIO, args_StringIO);
+ buffer->errbuf_obj = PyEval_CallObject(func_StringIO, args_StringIO);
+ Py_DECREF(args_StringIO);
+ Py_DECREF(func_StringIO);
+
+ /* release python thread */
+ PyGILState_Release(gstate);
+
+ return buffer;
+}
+
+
+/**
+ Delete a i/o buffer.
+*/
+void py_stdouterr_buffer_delete(py_stdouterr_buffer buffer)
+{
+ PyGILState_STATE gstate;
+
+ /* aquire python thread */
+ gstate = PyGILState_Ensure();
+
+ /* free the stdout/stderr buffer */
+ Py_DECREF(buffer->errbuf_obj);
+ Py_DECREF(buffer->outbuf_obj);
+
+ /* free the stdout/stderr objects */
+ Py_DECREF(buffer->stdout_obj);
+ Py_DECREF(buffer->stderr_obj);
+
+ /* free the imported modules */
+ Py_DECREF(buffer->mod_cStringIO);
+ Py_DECREF(buffer->mod_sys);
+
+ /* release python thread */
+ PyGILState_Release(gstate);
+
+ /* free string buffer structure */
+ free(buffer);
+}
+
+
+/**
+ Redirect stdout to the string buffer.
+*/
+void py_stdouterr_buffer_redirect_stdout(py_stdouterr_buffer buffer)
+{
+ PyGILState_STATE gstate;
+
+ /* aquire python thread */
+ gstate = PyGILState_Ensure();
+
+ PyObject_SetAttrString(buffer->mod_sys, "stdout", buffer->outbuf_obj);
+
+ /* release python thread */
+ PyGILState_Release(gstate);
+}
+
+
+/**
+ Redirect stderr to the string buffer.
+*/
+void py_stdouterr_buffer_redirect_stderr(py_stdouterr_buffer buffer)
+{
+ PyGILState_STATE gstate;
+
+ /* aquire python thread */
+ gstate = PyGILState_Ensure();
+
+ PyObject_SetAttrString(buffer->mod_sys, "stderr", buffer->errbuf_obj);
+
+ /* release python thread */
+ PyGILState_Release(gstate);
+}
+
+
+/**
+ Redirect stdout/stderr to the string buffer.
+*/
+void py_stdouterr_buffer_redirect(py_stdouterr_buffer buffer)
+{
+ py_stdouterr_buffer_redirect_stdout(buffer);
+ py_stdouterr_buffer_redirect_stderr(buffer);
+}
+
+
+/**
+ Restore stdout.
+*/
+void py_stdouterr_buffer_restore_stdout(py_stdouterr_buffer buffer)
+{
+ PyGILState_STATE gstate;
+
+ /* aquire python thread */
+ gstate = PyGILState_Ensure();
+
+ PyObject_SetAttrString(buffer->mod_sys, "stdout", buffer->stdout_obj);
+
+ /* release python thread */
+ PyGILState_Release(gstate);
+}
+
+
+/**
+ Restore stdout/stderr.
+*/
+void py_stdouterr_buffer_restore_stderr(py_stdouterr_buffer buffer)
+{
+ PyGILState_STATE gstate;
+
+ /* aquire python thread */
+ gstate = PyGILState_Ensure();
+
+ PyObject_SetAttrString(buffer->mod_sys, "stderr", buffer->stderr_obj);
+
+ /* release python thread */
+ PyGILState_Release(gstate);
+}
+
+
+/**
+ Restore stdout/stderr.
+*/
+void py_stdouterr_buffer_restore(py_stdouterr_buffer buffer)
+{
+ py_stdouterr_buffer_restore_stdout(buffer);
+ py_stdouterr_buffer_restore_stderr(buffer);
+}
+
+
+/**
+ Retrive the content of the stderr string buffer.
+
+ NOTE:
+ The retrived string is allocated storage and has to be freed!
+*/
+char* py_buffer_get_content_allocate(PyObject *buffer)
+{
+ PyGILState_STATE gstate;
+
+ /* aquire python thread */
+ gstate = PyGILState_Ensure();
+
+ /* access the stored stderr string buffer content as c string */
+ PyObject *func_getvalue, *args_getvalue, *buffer_obj;
+ func_getvalue = PyObject_GetAttrString(buffer, "getvalue");
+ args_getvalue = Py_BuildValue("()");
+ buffer_obj = PyEval_CallObject(func_getvalue, args_getvalue);
+ char* buf_pointer;
+ PyArg_Parse(buffer_obj, "s", &buf_pointer);
+
+ /* allocate a c string buffer to return the string */
+ int content_length = strlen(buf_pointer);
+ char* content;
+ content = (char*) malloc((content_length + 1) * sizeof(char));
+
+ /* copy the content string into the new buffer */
+ memcpy(content, buf_pointer, content_length);
+ content[content_length]= '\0';
+
+ /* give objects free for garbage collection */
+ Py_DECREF(buffer_obj);
+ Py_DECREF(args_getvalue);
+ Py_DECREF(func_getvalue);
+
+ /* release python thread */
+ PyGILState_Release(gstate);
+
+ return content;
+}
+
+
+/**
+ Retrive the content of the stdout string buffer.
+
+ NOTE:
+ The retrived string is allocated storage and has to be freed!
+*/
+char* py_stdouterr_buffer_get_stdout_allocate(py_stdouterr_buffer buffer)
+{
+ return py_buffer_get_content_allocate(buffer->outbuf_obj);
+}
+
+
+/**
+ Retrive the content of the stderr string buffer.
+
+ NOTE:
+ The retrived string is allocated storage and has to be freed!
+*/
+char* py_stdouterr_buffer_get_stderr_allocate(py_stdouterr_buffer buffer)
+{
+ return py_buffer_get_content_allocate(buffer->errbuf_obj);
+}
+
+
+/**
+ Print the stdout buffer to STDOUT.
+*/
+void py_stdouterr_buffer_print_stdout(py_stdouterr_buffer buffer)
+{
+ /* retrive buffered stdout */
+ char* stdout_str;
+ stdout_str = py_stdouterr_buffer_get_stdout_allocate(buffer);
+ fprintf(stdout, "%s", stdout_str);
+ free(stdout_str);
+ stdout_str = NULL;
+}
+
+
+/**
+ Print the stderr buffer to STDERR.
+*/
+void py_stdouterr_buffer_print_stderr(py_stdouterr_buffer buffer)
+{
+ /* retrive buffered stderr */
+ char* stderr_str;
+ stderr_str = py_stdouterr_buffer_get_stderr_allocate(buffer);
+ fprintf(stderr, "%s", stderr_str);
+ free(stderr_str);
+ stderr_str = NULL;
+}
+
+
+/**
+ Print first the stdout buffer to STDOUT
+ and after the stderr buffer to STDERR.
+*/
+void py_stdouterr_buffer_print(py_stdouterr_buffer buffer)
+{
+ py_stdouterr_buffer_print_stdout(buffer);
+ py_stdouterr_buffer_print_stderr(buffer);
+}
+
+
+/**
+ Clear stdout/stderr buffers.
+*/
+void py_stdouterr_buffer_clear_buffers(py_stdouterr_buffer buffer)
+{
+ PyGILState_STATE gstate;
+
+ /* aquire python thread */
+ gstate = PyGILState_Ensure();
+
+ /* free the stdout/stderr buffer */
+ Py_DECREF(buffer->errbuf_obj);
+ Py_DECREF(buffer->outbuf_obj);
+
+ /* make new string buffer for stdout and stderr */
+ PyObject *func_StringIO, *args_StringIO;
+ func_StringIO = PyObject_GetAttrString(buffer->mod_cStringIO, "StringIO");
+ args_StringIO = Py_BuildValue("()");
+ buffer->outbuf_obj = PyEval_CallObject(func_StringIO, args_StringIO);
+ buffer->errbuf_obj = PyEval_CallObject(func_StringIO, args_StringIO);
+ Py_DECREF(args_StringIO);
+ Py_DECREF(func_StringIO);
+
+ /* release python thread */
+ PyGILState_Release(gstate);
+}
+
+
+/* fin */
Index: source/blender/commandport/blender/src/bcp_handle_client.c
===================================================================
--- source/blender/commandport/blender/src/bcp_handle_client.c (revision 0)
+++ source/blender/commandport/blender/src/bcp_handle_client.c (revision 0)
@@ -0,0 +1,149 @@
+/*
+ * $Id: bcp_handle_client.c, v 1.0 2007/05/02, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Handle command port client
+ *
+ * header file: ../include/bcp_handle_client.h
+ *
+ */
+
+#include <stdio.h> /* for printf() */
+#include <stdlib.h> /* for free() */
+#include <string.h> /* strlen(), memcpy() */
+#include <unistd.h>
+
+#include "message_handler.h"
+#include "string_buffer.h"
+
+#include "bcp_debug.h" /* bcp_debug() */
+#include "bcp_blender.h"
+#include "bcp_handle_client.h"
+#include "hexdump_string.h" /* hexdump_string() */
+
+// void mainqenter_command_port_input_event(char* script);
+char* make_no_result_package_allocate();
+
+#define BCP_NO_RESULT "#i0\n#s4\nNone\n#s0\n\n#s0\n\n" /* a packed Blender `None' result -
+ used in DEBUG mode */
+
+void bcp_handle_client(int client_socket)
+{
+ int debug, debug3, debug4;
+ message_handler message_handler;
+ bcp_blender_handler blender_handler;
+ char *command, *result;
+ int package_number;
+
+ /* get debug level */
+ debug = bcp_debug();
+ debug3 = (debug >= 3); /* if debug >= 3 hexdump the received packages before processing them */
+ debug4 = (debug >= 4); /* if debug >= 4 only hexdump the received packages
+ without sending them to blender for processing. */
+
+ /* message handler */
+ message_handler = message_handler_new(client_socket);
+
+ /* Blender handler to handle the client command run requests */
+ blender_handler = bcp_blender_handler_new();
+
+ /* client socket loop */
+ package_number = 0; /* the number of the current package */
+ while ((command = message_handler_receive_message_allocate(message_handler)) != (char*) NULL) {
+
+ /* increment package counter */
+ package_number++;
+
+ /* DEBUG - dump command */
+ if (debug3) {
+ /* DEBUG > 3 mode -
+ print and dump received packages */
+ printf("[DEBUG] >>> Received package #%d:\n", package_number);
+ printf(" >>>%s<<<\n", command); /* print package */
+ hexdump_string(" ", command); /* dump package */
+ }
+
+ /* process the command */
+ if (debug4) {
+ /* DEBUG > 4 mode -
+ don't process package, just return `None' result package */
+ result = make_no_result_package_allocate();
+ } else {
+ /* put a package process request in blender queue
+ and wait for result */
+ result = bcp_blender_handle_input_allocate(blender_handler, command);
+ }
+
+ /* send the result back */
+ message_handler_send_message(message_handler, result);
+
+ /* free the result buffer */
+ if (debug) printf("[DEBUG] bcp_handle_client: free(result), result: %p\n", result);
+ free(result);
+ result = NULL;
+
+ /* free the command buffer */
+ if (debug) printf("[DEBUG] bcp_handle_client: free(command), command: %p\n", command);
+ free(command);
+ command = NULL;
+ }
+
+ printf("bye...\n");
+
+ /* cleanup */
+ bcp_blender_handler_delete(blender_handler);
+ if (debug) printf("[DEBUG] bcp_handle_client: bcp_blender_handler_delete(blender_handler);\n");
+ message_handler_delete(message_handler);
+ if (debug) printf("[DEBUG] bcp_handle_client: message_handler_delete(message_handler);\n");
+ close(client_socket);
+ if (debug) printf("[DEBUG] bcp_handle_client: close(client_socket);\n");
+}
+
+/**
+ For DEBUG mode only -
+ make a `None' result package and return it.
+*/
+char* make_no_result_package_allocate()
+{
+ char *none_result_package, *package;
+ int length;
+
+ /* allocate memory for message client structure */
+ none_result_package = BCP_NO_RESULT;
+
+ /* allocating memory for the package */
+ length = strlen(none_result_package);
+ package = (char*) malloc((length + 1) * sizeof(char));
+ memcpy(package, none_result_package, length);
+ package[length]= '\0';
+
+ /* return the newly allocated copy */
+ return package;
+}
+
+/* fin */
Index: source/blender/commandport/utilities/test/bcp_package_test.c
===================================================================
--- source/blender/commandport/utilities/test/bcp_package_test.c (revision 0)
+++ source/blender/commandport/utilities/test/bcp_package_test.c (revision 0)
@@ -0,0 +1,52 @@
+/*
+ * $Id: bcp_package_test.c, v 1.0 2007/06/13, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Main function for testing the
+ * Blender Commandport Package functionality
+ * using the tests defined in ../src/bcp_package.c
+ *
+ * usage:
+ *
+ * cd <path to blender source tree>/blender/source/blender/commandport/utilities/test/
+ * scons -f SConstruct.bcp_package.test
+ * ./test
+ *
+ */
+
+#include <stdio.h>
+
+#include "bcp_package.h"
+
+int main(int argc, char *argv[])
+{
+ /* test */
+ bcp_package_test();
+}
+
+/* fin */
Index: source/blender/commandport/utilities/test/SConstruct.bcp_package.test
===================================================================
--- source/blender/commandport/utilities/test/SConstruct.bcp_package.test (revision 0)
+++ source/blender/commandport/utilities/test/SConstruct.bcp_package.test (revision 0)
@@ -0,0 +1,52 @@
+# -*- mode: python -*-
+#
+# $Id: SConstruct.bcp_package.test, v 1.0 2007/06/13, dietrich, tokyo $
+#
+# ***** BEGIN GPL 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.
+#
+# 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,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 by the Blender Foundation.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Author: Dietrich Bollmann
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# A simple build file for testing the
+# Blender Commandport Package functionality
+# using the tests defined in bcp_package_test.c and ../src/bcp_package.c
+#
+# usage:
+#
+# cd <path to blender source tree>/blender/source/blender/commandport/utilities/test/
+# scons -f SConstruct.bcp_package.test
+# ./test
+
+env = Environment()
+
+env.Append(CPPPATH = ['../include'])
+
+test = env.Program('test', [
+ '../src/bcp_package.c',
+ 'bcp_package_test.c'
+ ])
+
+Default(test)
+
+# fin.
Index: source/blender/commandport/utilities/include/bcp_debug.h
===================================================================
--- source/blender/commandport/utilities/include/bcp_debug.h (revision 0)
+++ source/blender/commandport/utilities/include/bcp_debug.h (revision 0)
@@ -0,0 +1,72 @@
+/*
+ * $Id: bcp_debug.h, v 1.0 2007/05/30, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Module for initializing, storing and querying
+ * the Blender command port debug level.
+ *
+ * The command port can be made to print debug messages in different
+ * verbosity levels via the command line option `--debug bcp:<level>'.
+ * `<level>' can be one of 1, 2, 3, 4.
+ *
+ * For more information see the debug help text defined in function
+ * `print_help_debug()' in file `../../blender/src/bcp_handle_client.c'
+ * or call Blender with the option `-hd' / `--help=debug'.
+ *
+ * For the command port debug code search sources for `debug("bcp")'
+ * and `bcp_debug()'.
+ *
+ * source file: ../src/bcp_debug.c
+ *
+ */
+
+#ifndef BCP_DEBUG_H
+#define BCP_DEBUG_H
+
+/**
+ Set BCP debug level.
+
+ This option currently is used in
+ - blender/source/blender/commandport/blender/src/commandport.c and
+ - blender/source/blender/commandport/blash/src/blash.c
+ to init the debug level for the Blender command port server / client
+ respectively.
+*/
+void bcp_set_debug_level(int level);
+
+/**
+ Returns the debug level for the Blender command port.
+
+ Used in all functions printing debug messages
+ which depend on the debug level.
+*/
+int bcp_debug();
+
+#endif /* BCP_DEBUG_H */
+
+/* fin */
Index: source/blender/commandport/utilities/include/bcp_meta_commands.h
===================================================================
--- source/blender/commandport/utilities/include/bcp_meta_commands.h (revision 0)
+++ source/blender/commandport/utilities/include/bcp_meta_commands.h (revision 0)
@@ -0,0 +1,85 @@
+/*
+ * $Id: bcp_meta_commands.h, v 1.0 2007/06/13, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * The Meta Commands class defines codes used by the command port.
+ *
+ * Different classes of codes / meta commands exist:
+ *
+ * - codes to tell the Blender Python interpreter how to evaluate the
+ * messages send by a client
+ *
+ * - codes to change the Python print mode
+ *
+ * - codes to reset the command port
+ *
+ * - codes expressing the result of the evaluation of Python command string
+ *
+ * - codes to tell the client if the send command string is a complete or
+ * incomplete Python command sequence
+ *
+ * included by the following files:
+ *
+ * - ../../blender/src/bcp_python.c
+ * - ../src/bcp_shell.c
+ *
+ */
+
+#ifndef BCP_META_COMMANDS_H
+#define BCP_META_COMMANDS_H
+
+/* BCP input modes */
+#define BCP_SINGLE_MODE_COMMAND 'S' /* single command input mode */
+#define BCP_EVAL_MODE_COMMAND 'E' /* eval command input mode */
+#define BCP_FILE_MODE_COMMAND 'F' /* file command input mode (default) */
+
+/* result print modes */
+#define BCP_REPR_PRINT_MODE_COMMAND 'r' /* reset the command port (default) */
+#define BCP_STR_PRINT_MODE_COMMAND 's' /* reset the command port */
+
+/* reset the BCP namespace */
+#define BCP_RESET_COMMAND 'R' /* reset the command port */
+
+/**
+ Result codes -
+*/
+#define BCP_RESULT_CODE_SUCCESS 0 /* The python evaluation was successful */
+#define BCP_RESULT_CODE_INCOMPLETE_INPUT 1 /* The entered python code is incomplete
+ and the blender server waits for more
+ input lines to complete the input */
+#define BCP_RESULT_CODE_ERROR 2 /* An error occured during the
+ evaluation ot the python code */
+#define BCP_RESULT_CODE_UNDEFINED 3 /* This code should never be returned
+ and indicates that an unexpecte result
+ was returned by the Python interpreter */
+#define BCP_RESULT_CODE_EMPTY_INPUT 4 /* Returned if the shell input was emtpy */
+
+#endif /* BCP_META_COMMANDS_H */
+
+/* fin */
+
Index: source/blender/commandport/utilities/include/bcp_shell.h
===================================================================
--- source/blender/commandport/utilities/include/bcp_shell.h (revision 0)
+++ source/blender/commandport/utilities/include/bcp_shell.h (revision 0)
@@ -0,0 +1,90 @@
+/*
+ * $Id: bcp_shell.h, v 1.0 2007/05/31, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Defines the interactive shell called by blash's `main()' function.
+ *
+ * source file: ../src/bcp_shell.c
+ *
+ */
+
+#ifndef BCP_SHELL_H
+
+/**
+ Shell Evaluation Modes
+
+ Three different modes can be used from the interactive bash shell:
+
+ * BCP_SINGLE_MODE
+
+ This is the normal shell mode:
+ Python commands are entered line by line.
+ If a single line can be interpreted as complete python command,
+ it is evaluated and the result is printed;
+ if the first line doesn't correspond to a complete python command,
+ all lines following this first line are stored until an empty line
+ is entered. At this point all lines together are evaluated and the
+ result is printed to the shell.
+
+ * BCP_EVAL_MODE
+
+ The entered string is interpreted as a complete, isolated Python expression and
+ evaluated by the python interpreter. The result is printed to the shell.
+
+ * BCP_FILE_MODE
+
+ A sequences of Python statements can be entered and executed by the Python interpreter. No result is printed.
+ This mode is usefull when a full program is entered at once. It is also useful for
+ executing definitions which contain blank lines.
+
+ For more informatin concerning the shell evaluation modes compare the
+ documentation in `bcp_python.h' and `bcp_python.c'.
+
+*/
+#define BCP_SINGLE_MODE 0
+#define BCP_EVAL_MODE 1
+#define BCP_FILE_MODE 2
+
+/**
+ Open a new Blender command port shell.
+*/
+void bcp_shell(char* server_IP_address, unsigned short server_port, int mode);
+
+/**
+ Open a new Blender command port shell.
+
+ If the connection to the Blender server could not been established immediately,
+ retry up to `retries' times. Sleep `retry_sleeptime' seconds before trying again.
+*/
+void bcp_shell_wait(char* server_IP_address, unsigned short server_port, int mode,
+ int retries, float retry_sleeptime, char* init_command);
+
+#define BCP_SHELL_H
+#endif /* BCP_SHELL_H */
+
+/* fin */
Index: source/blender/commandport/utilities/include/bcp_defaults.h
===================================================================
--- source/blender/commandport/utilities/include/bcp_defaults.h (revision 0)
+++ source/blender/commandport/utilities/include/bcp_defaults.h (revision 0)
@@ -0,0 +1,47 @@
+/*
+ * $Id: bcp_defaults.h, v 1.0 2007/06/13, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Default definitions for the Blender Command Port.
+ *
+ */
+
+#ifndef BCP_DEFAULTS_H
+#define BCP_DEFAULTS_H
+
+/**
+ Defaults
+*/
+
+/* IP and port */
+#define BCP_DEFAULT_IP "127.0.0.1"
+#define BCP_DEFAULT_PORT 5555
+
+#endif /* BCP_DEFAULTS_H */
+
+/* fin */
Index: source/blender/commandport/utilities/include/string_buffer_test.h
===================================================================
--- source/blender/commandport/utilities/include/string_buffer_test.h (revision 0)
+++ source/blender/commandport/utilities/include/string_buffer_test.h (revision 0)
@@ -0,0 +1,48 @@
+/*
+ * $Id: string_buffer_test.h, v 1.0 2007/05/30, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Some functions to test the `string_buffer' functions.
+ *
+ * see: `../include/string_buffer.h' and `../src/string_buffer.c'
+ *
+ * source file: ../src/string_buffer_test.c
+ *
+ */
+
+#ifndef STRING_BUFFER_TEST_H
+#define STRING_BUFFER_TEST_H
+
+/**
+ main string_buffer testing function...
+*/
+void string_buffer_test();
+
+#endif /* STRING_BUFFER_TEST_H */
+
+/* fin */
Index: source/blender/commandport/utilities/include/fsleep.h
===================================================================
--- source/blender/commandport/utilities/include/fsleep.h (revision 0)
+++ source/blender/commandport/utilities/include/fsleep.h (revision 0)
@@ -0,0 +1,50 @@
+/*
+ * $Id: fsleep.h, v 1.0 2007/05/19, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * sleep for an amount of time - the time might be any fraction of seconds given as float.
+ *
+ * source file: ../src/fsleep.c
+ *
+ */
+
+#ifndef FSLEEP_H
+#define FSLEEP_H
+
+/**
+ sleep for an amount of time -
+
+ the time might be any fraction of seconds given as float.
+*/
+int fsleep(float seconds);
+
+#endif /* FSLEEP_H */
+
+/* fin */
+
+
Index: source/blender/commandport/utilities/include/bcp_package.h
===================================================================
--- source/blender/commandport/utilities/include/bcp_package.h (revision 0)
+++ source/blender/commandport/utilities/include/bcp_package.h (revision 0)
@@ -0,0 +1,162 @@
+/*
+ * $Id: bcp_package.h, v 1.0 2007/05/31, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Functions to pack and unpack integers, strings and commands into a
+ * single string for sending them over the command port socket.
+ *
+ * source file: ../src/bcp_package.c
+ *
+ */
+
+#ifndef BCP_PACKAGE_H
+#define BCP_PACKAGE_H
+
+/* types */
+#define BCP_PACKAGE_TYPE_EMPTY 'e'
+#define BCP_PACKAGE_TYPE_UNDEFINED 'u'
+#define BCP_PACKAGE_TYPE_INT 'i'
+#define BCP_PACKAGE_TYPE_STRING 's'
+#define BCP_PACKAGE_TYPE_COMMAND 'c'
+
+/**
+ bcp_package type definition
+*/
+typedef struct bcp_package_struct *bcp_package;
+
+/**
+ Make a new package.
+*/
+bcp_package bcp_package_new();
+
+/**
+ Delete a package.
+*/
+void bcp_package_delete(bcp_package package);
+
+/**
+ Empty a package.
+*/
+void bcp_package_make_empty(bcp_package package);
+
+/**
+ Add integer.
+*/
+void bcp_package_add_int(bcp_package package, int i);
+
+/**
+ Add string.
+*/
+void bcp_package_add_string(bcp_package package, char* s);
+
+/**
+ Add command.
+*/
+void bcp_package_add_command(bcp_package package, char command);
+
+/**
+ Convert the package to a string representation
+ which can be stored / send via the internet ....
+
+ Note:
+ The memory for the string returned by this function
+ has to be freed by the caller!
+*/
+char* bcp_package_pack_allocate(bcp_package package);
+
+/**
+ Unpack the elements in the string `packed'
+ and return the result package.
+
+ Note:
+ The string `is manipulated' and not printable as
+ one string after calling this function.
+ Note also that no new memory is allocated
+ for unpacked string elements.
+ `packed' therefore only can be freed after
+ the processing of the unpacked elements is finished.
+*/
+bcp_package bcp_package_unpack(char* packed);
+
+
+/* =========================================================
+ * BCP package enumerator functions
+ * ---------------------------------------------------------
+ */
+
+/**
+ bcp_package enumerator type definition
+*/
+typedef struct bcp_package_enumerator_struct *bcp_package_enumerator;
+
+/**
+ Make a new package enumerator.
+*/
+bcp_package_enumerator bcp_package_enumerator_new(bcp_package p);
+
+/**
+ Delete a package enumerator.
+*/
+void bcp_package_enumerator_delete(bcp_package_enumerator enumerator);
+
+/**
+ Reset enumerator.
+*/
+void bcp_package_enumerator_reset(bcp_package_enumerator e);
+
+/**
+ Get next element in package.
+*/
+void* bcp_package_enumerator_get_next_element(bcp_package_enumerator e, char* type);
+
+/**
+ Debugging function:
+ Dump an unpacked package
+*/
+void dump_package(bcp_package p);
+
+/* =========================================================
+ * Test functions
+ * ---------------------------------------------------------
+ */
+
+/* to build the test functions, uncomment the following define: */
+#define BCP_PACKAGE_TEST
+
+#ifdef BCP_PACKAGE_TEST
+
+/**
+ test
+*/
+void bcp_package_test();
+
+#endif /* BCP_PACKAGE_TEST */
+
+#endif /* BCP_PACKAGE_H */
+
+/* fin */
Index: source/blender/commandport/utilities/include/string_buffer.h
===================================================================
--- source/blender/commandport/utilities/include/string_buffer.h (revision 0)
+++ source/blender/commandport/utilities/include/string_buffer.h (revision 0)
@@ -0,0 +1,187 @@
+/*
+ * $Id: string_buffer.h, v 1.0 2007/05/30, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * A buffer to save c strings in chunks.
+ *
+ * Every string chunk (or slice) appended (or prepended) to the
+ * buffer is copied into newly allocated memory which is appended (or
+ * prepended) to a queue. Only when the whole string is needed (or
+ * some other operation is performed for which the whole string is
+ * needed), the slices are copied into a single newly allocated c
+ * buffer.
+ *
+ * source file: ../src/string_buffer.c
+ *
+ */
+
+#ifndef STRING_BUFFER_H
+#define STRING_BUFFER_H
+
+typedef struct string_buffer_struct *string_buffer;
+
+/**
+ Make a new text buffer.
+*/
+string_buffer string_buffer_new();
+
+/**
+ Delete a text buffer.
+*/
+void string_buffer_delete(string_buffer buffer);
+
+/**
+ Return true if the string buffer is empty and false if not.
+*/
+int string_buffer_is_empty(string_buffer buffer);
+
+/**
+ Empty a text buffer.
+*/
+void string_buffer_make_empty(string_buffer buffer);
+
+/**
+ Prepend a string to a string buffer.
+*/
+void string_buffer_prepend(string_buffer buffer, char* str);
+
+/**
+ Append a newline caracter to 'str' and
+ prepend the result to a string buffer.
+*/
+void string_buffer_prepend_newline(string_buffer buffer, char* str);
+
+/**
+ Append a line to a text buffer.
+*/
+void string_buffer_append(string_buffer buffer, char* str);
+
+/**
+ Append a string and a newline caracter to a string buffer.
+*/
+void string_buffer_append_newline(string_buffer buffer, char* str);
+
+/**
+ Get the length of a string buffer.
+*/
+int string_buffer_get_length(string_buffer buffer);
+
+/**
+ Cleanup a string buffer.
+ Returns the length of the string buffer.
+
+ Append the string slices constituting a string buffer
+ into one single string slice.
+*/
+int string_buffer_cleanup(string_buffer buffer);
+
+/**
+ Like strcmp - but for string buffers :)
+*/
+int string_buffer_compare_to_string(string_buffer buffer, char* str);
+
+/**
+ Check if the string buffer starts with the given prefix.
+ Return 1 if this is the case and 0 otherwise.
+*/
+int string_buffer_starts_with_prefix(string_buffer buffer, char* prefix);
+
+/**
+ Check if the string buffer is empty
+ or only contains white space.
+*/
+int string_buffer_is_empty_or_white_space_string(string_buffer buffer);
+
+/**
+ Transform a string buffer into a newly allocated character array.
+ A pointer to the allocated char array is returned.
+ The length of the string is returned as second parameter.
+*/
+char* string_buffer_to_char_array_allocate(string_buffer buffer, int* length);
+
+/**
+ Read a single line from stdin.
+ The function returns the accumulated length of lines in 'buffer'.
+*/
+int string_buffer_read_line_from_stdin(string_buffer buffer);
+
+/**
+ Get the line prompt.
+ The returned string is a copy of the original prompt in newly allocated memory.
+*/
+char* string_buffer_get_line_prompt_allocate(string_buffer buffer);
+
+/**
+ Get the text prompt.
+ The returned string is a copy of the original prompt in newly allocated memory.
+*/
+char* string_buffer_get_text_prompt_allocate(string_buffer buffer);
+
+/**
+ Get the text coninue prompt.
+ The returned string is a copy of the original prompt in newly allocated memory.
+*/
+char* string_buffer_get_text_coninue_prompt_allocate(string_buffer buffer);
+
+/**
+ Set the read line prompt.
+*/
+void string_buffer_set_line_prompt(string_buffer buffer, char *prompt);
+
+/**
+ Read a text (a sequence of lines) from stdin.
+ The input is terminated by a line containing only a dot character '.'.
+
+ The function returns the accumulated length of all read lines.
+*/
+int string_buffer_read_text_from_stdin(string_buffer buffer);
+
+/**
+ Set the read text prompt.
+*/
+void string_buffer_set_text_prompt(string_buffer buffer, char *prompt);
+
+/**
+ Set the read text continue prompt.
+*/
+void string_buffer_set_text_coninue_prompt(string_buffer buffer, char *prompt);
+
+/**
+ Print a text buffer.
+*/
+void string_buffer_print(string_buffer buffer);
+
+/**
+ Dump the inner structure of a string buffer to stdout.
+ Note: This function is only for use during development.
+*/
+void string_buffer_dump(string_buffer buffer);
+
+#endif /* STRING_BUFFER_H */
+
+/* fin */
Index: source/blender/commandport/utilities/include/hexdump_string.h
===================================================================
--- source/blender/commandport/utilities/include/hexdump_string.h (revision 0)
+++ source/blender/commandport/utilities/include/hexdump_string.h (revision 0)
@@ -0,0 +1,128 @@
+/*
+ * $Id: hexdump_string.h, v 1.0 2007/05/30, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Hexdump functions to debug the Blender Command Port...
+ *
+ * source file: ../src/hexdump_string.c
+ *
+ */
+
+#ifndef HEXDUMP_STRING_H
+#define HEXDUMP_STRING_H
+
+/**
+ Print ascii code table.
+
+ +---+----------------------------------------------------------------+
+ | \ | 0 1 2 3 4 5 6 7 8 9 A B C D E F |
+ +---+----------------------------------------------------------------+
+ | 0 | NUL SOH STX ETX EOT ENQ ACK BEL BS HT LF VT FF CR SO SI |
+ | 1 | DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US |
+ | 2 | SP ! " # $ % & ' ( ) * + , - . / |
+ | 3 | 0 1 2 3 4 5 6 7 8 9 : ; < = > ? |
+ | 4 | @ A B C D E F G H I J K L M N O |
+ | 5 | P Q R S T U V W X Y Z [ \ ] ^ _ |
+ | 6 | ` a b c d e f g h i j k l m n o |
+ | 7 | p q r s t u v w x y z { | } ~ DEL |
+ +---+----------------------------------------------------------------+
+*/
+void print_ascii_code_table();
+
+/**
+ Print the code table used in last column by `hexdump_string()'.
+
+ The character codes are represented by the following characters:
+
+ - the character represented by the code itself - if printable
+ - '>' for tab (0x09 - ascii: HT = Horizontal Tab)
+ - '^' for newline (0x0a - ascii: LF = Line Feed)
+ - '0' for the null character (0x00 - ascii: NUL = Null char.)
+ - '?' for things which might cause problems - and ? itself :)
+
+ +---+----------------------------------------------------------------+
+ | \ | 0 1 2 3 4 5 6 7 8 9 A B C D E F |
+ +---+----------------------------------------------------------------+
+ | 0 | 0 ? ? ? ? ? ? ? ? > ^ ? ? ? ? ? |
+ | 1 | ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? |
+ | 2 | SP ! " # $ % & ' ( ) * + , - . / |
+ | 3 | 0 1 2 3 4 5 6 7 8 9 : ; < = > ? |
+ | 4 | @ A B C D E F G H I J K L M N O |
+ | 5 | P Q R S T U V W X Y Z [ \ ] ^ _ |
+ | 6 | ` a b c d e f g h i j k l m n o |
+ | 7 | p q r s t u v w x y z { | } ~ ? |
+ +---+----------------------------------------------------------------+
+*/
+void print_printable_dump_code_table();
+
+/**
+ Dump the hex codes a string is made of.
+
+ Example:
+
+ The string
+ "eins zwei drei vier fuenf sechs sieben, tab: '\t', newline: '\n' and - to terminate the string - the nullchar: "
+ is dumped as:
+
+ ==============================================================================
+ addr 0 1 2 3 4 5 6 7 8 9 A B C D E F | printable repr.|
+ ------------------------------------------------------------+----------------+
+ 00000000 65 69 6e 73 20 7a 77 65 69 20 64 72 65 69 20 76 |eins zwei drei v|
+ 00000010 69 65 72 20 66 75 65 6e 66 20 73 65 63 68 73 20 |ier fuenf sechs |
+ 00000020 73 69 65 62 65 6e 2c 20 74 61 62 3a 20 27 09 27 |sieben, tab: '>'|
+ 00000030 2c 20 6e 65 77 6c 69 6e 65 3a 20 27 0a 27 20 61 |, newline: '^' a|
+ 00000040 6e 64 20 2d 20 74 6f 20 74 65 72 6d 69 6e 61 74 |nd - to terminat|
+ 00000050 65 20 74 68 65 20 73 74 72 69 6e 67 20 2d 20 74 |e the string - t|
+ 00000060 68 65 20 6e 75 6c 6c 63 68 61 72 3a 20 00 |he nullchar: 0|
+ ==============================================================================
+*/
+void hexdump_string(char* prefix, char* string);
+
+/**
+ Dump the hex codes a string is made of.
+
+ Simple formatting - example:
+
+ The string "eins zwei drei vier fuenf sechs sieben."
+ is dumped as:
+
+ 65 69 6e 73 20 7a 77 65 69 20 64 72 65 69 20 76
+ 69 65 72 20 66 75 65 6e 66 20 73 65 63 68 73 20
+ 73 69 65 62 65 6e 2e 00
+*/
+void simple_hexdump_string(char* string);
+
+/**
+ Test the hexdump functions.
+*/
+void hexdump_string_test();
+
+#endif /* HEXDUMP_STRING_H */
+
+/* fin */
+
Index: source/blender/commandport/utilities/include/message_handler.h
===================================================================
--- source/blender/commandport/utilities/include/message_handler.h (revision 0)
+++ source/blender/commandport/utilities/include/message_handler.h (revision 0)
@@ -0,0 +1,69 @@
+/*
+ * $Id: message_handler.h, v 1.0 2007/06/13, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * The message handler class implements the protocol used by the
+ * commandport for exchanging text messages via a socket connection.
+ * A message is defined as a string of an arbitrary length terminated
+ * with a '\0' character.
+ *
+ * source file: ../src/message_handler.c
+ *
+ */
+
+#ifndef MESSAGE_HANDLER_H
+#define MESSAGE_HANDLER_H
+
+typedef struct message_handler_data* message_handler;
+
+#include "error_codes.h"
+
+/**
+ Make a new message socket handler.
+*/
+message_handler message_handler_new(int socket);
+
+/**
+ Delete a message socket handler.
+*/
+void message_handler_delete(message_handler handler);
+
+/**
+ Send a message.
+ */
+void message_handler_send_message(message_handler handler, char* message);
+
+/**
+ Receive a message.
+ The return value NULL signals the end of the client connection.
+*/
+char* message_handler_receive_message_allocate(message_handler handler);
+
+#endif /* MESSAGE_HANDLER_H */
+
+/* fin */
Index: source/blender/commandport/utilities/include/message_client.h
===================================================================
--- source/blender/commandport/utilities/include/message_client.h (revision 0)
+++ source/blender/commandport/utilities/include/message_client.h (revision 0)
@@ -0,0 +1,84 @@
+/*
+ * $Id: message_client.h, v 1.0 2007/06/13, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * The message client class is the central part of a Blender Command
+ * Port client written in c. It implements the functionality for
+ * connecting and disconnecting to / from a Blender Server and for
+ * sending and receiving text messages.
+ *
+ * source file: ../src/message_client.c
+ *
+ */
+
+#ifndef MESSAGE_CLIENT_H
+#define MESSAGE_CLIENT_H
+
+#include "error_codes.h"
+
+typedef struct message_client_struct *message_client;
+
+/**
+ Make a new message client.
+*/
+message_client message_client_new(char *server_IP_address, unsigned short server_port);
+
+/**
+ Make a new message client.
+
+ If the connection could not been established immediately, retry up to `retries' times.
+ Sleep `retry_sleeptime' seconds before trying again.
+*/
+message_client message_client_new_wait(char *server_IP_address, unsigned short server_port,
+ int retries, float retry_sleeptime);
+
+/**
+ Delete a message client.
+*/
+void message_client_delete(message_client client);
+
+/**
+ Send a message.
+ */
+void message_client_send(message_client client, char* message);
+
+/**
+ Receive a message.
+ The return value NULL signals the end of the client connection.
+ */
+char* message_client_receive_allocate(message_client client);
+
+/**
+ Send a message and return the answer.
+ */
+char* message_client_send_receive_allocate(message_client client, char* message);
+
+#endif /* MESSAGE_CLIENT_H */
+
+/* fin */
+
Index: source/blender/commandport/utilities/include/error_codes.h
===================================================================
--- source/blender/commandport/utilities/include/error_codes.h (revision 0)
+++ source/blender/commandport/utilities/include/error_codes.h (revision 0)
@@ -0,0 +1,52 @@
+/*
+ * $Id: error_codes.h, v 1.0 2007/06/13, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Blender Command Port error codes.
+ *
+ */
+
+#ifndef ERROR_CODES_H
+#define ERROR_CODES_H
+
+#define ERROR_TEXTBUFFER 2
+#define ERROR_MEMORY 3
+#define ERROR_RECEIVE 4
+#define ERROR_SEND 5
+#define ERROR_SOCKET 6
+#define ERROR_CONNECTION 7
+#define ERROR_SYNCHRONIZATION 8
+#define ERROR_UNKNOWN_TYPE 9
+#define ERROR_PARSER 10
+#define ERROR_IN_BCP_PROTOCOL 11
+#define ERROR_BCP_PYTHON 12
+
+#endif /* ERROR_CODES_H */
+
+/* fin */
+
Index: source/blender/commandport/utilities/SConscript
===================================================================
--- source/blender/commandport/utilities/SConscript (revision 0)
+++ source/blender/commandport/utilities/SConscript (revision 0)
@@ -0,0 +1,37 @@
+# -*- mode: python -*-
+#
+# $Id: SConscript, v 1.0 2007/06/13, dietrich, tokyo $
+#
+# ***** BEGIN GPL 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.
+#
+# 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,
+# Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# The Original Code is Copyright (C) 2007 by the Blender Foundation.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Author: Dietrich Bollmann
+# Contributor(s): none yet.
+#
+# ***** END GPL LICENSE BLOCK *****
+#
+# Build file for the Blender Commandport Utilities.
+
+SConscript([
+ 'src/SConscript',
+ ])
+
+# fin.
Index: source/blender/commandport/utilities/src/string_buffer_test.c
===================================================================
--- source/blender/commandport/utilities/src/string_buffer_test.c (revision 0)
+++ source/blender/commandport/utilities/src/string_buffer_test.c (revision 0)
@@ -0,0 +1,123 @@
+/*
+ * $Id: string_buffer_test.c, v 1.0 2007/05/30, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Some functions to test the `string_buffer' functions.
+ *
+ * see: `../include/string_buffer.h' and `../src/string_buffer.c'
+ *
+ * header file: ../include/string_buffer_test.h
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "string_buffer.h"
+
+void string_buffer_test_append()
+{
+ string_buffer text = string_buffer_new();
+
+ string_buffer_append(text, "hi die :)\n");
+ string_buffer_append(text, " was");
+ string_buffer_append(text, " ");
+ string_buffer_append(text, "macht\n");
+ string_buffer_append(text, " das Leben?\n");
+
+ string_buffer_print(text);
+
+ string_buffer_delete(text);
+}
+
+void string_buffer_cleanup_test()
+{
+ /* init buffer */
+ string_buffer buffer = string_buffer_new();
+
+ string_buffer_append(buffer, "hi die :)\n");
+ string_buffer_append(buffer, " was");
+ string_buffer_append(buffer, " ");
+ string_buffer_append(buffer, "macht\n");
+ string_buffer_append(buffer, " das Leben?\n");
+
+ /* clean up the buffer buffer */
+ /* DEBUG */
+ printf("===\n");
+ printf("Buffer before cleanup (length: %d):\n", string_buffer_get_length(buffer));
+ printf("===\n");
+ string_buffer_print(buffer);
+ string_buffer_dump(buffer);
+
+ int length = string_buffer_cleanup(buffer);
+
+ /* DEBUG */
+ printf("Buffer after cleanup (length: %d):\n", string_buffer_get_length(buffer));
+ printf("===\n");
+ string_buffer_print(buffer);
+ string_buffer_dump(buffer);
+
+ string_buffer_delete(buffer);
+}
+
+/**
+ Reading a sequende of non-empty lines from stdin
+ The input is terminated by entering an empty line.
+ */
+void test_string_buffer_read_text_from_stdin()
+{
+ /* allocate a string buffer for the lines to read */
+ string_buffer paragraph = string_buffer_new();
+
+ /* read a paragraph from stdin */
+ int length = string_buffer_read_text_from_stdin(paragraph);
+ printf("\n");
+
+ /* print the paragraph */
+ printf("The paragraph is %d characters long...\n", length);
+ printf("---\n");
+ string_buffer_dump(paragraph);
+ string_buffer_print(paragraph);
+ printf("---\n");
+ printf("\n");
+}
+
+/**
+ main string_buffer testing function...
+*/
+void string_buffer_test()
+{
+ string_buffer_test_append();
+ string_buffer_cleanup_test();
+ test_string_buffer_read_text_from_stdin();
+
+ printf("\nend of string_buffer tests...\n\n");
+}
+
+/* fin */
Index: source/blender/commandport/utilities/src/fsleep.c
===================================================================
--- source/blender/commandport/utilities/src/fsleep.c (revision 0)
+++ source/blender/commandport/utilities/src/fsleep.c (revision 0)
@@ -0,0 +1,58 @@
+/*
+ * $Id: fsleep.c, v 1.0 2007/05/19, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * sleep for an amount of time - the time might be any fraction of seconds given as float.
+ *
+ * header file: ../include/fsleep.h
+ *
+ */
+
+#include <stdlib.h>
+
+/**
+ sleep for an amount of time -
+
+ the time might be any fraction of seconds given as float.
+*/
+int fsleep(float seconds)
+{
+ /* separate in seconds and nanoseconds */
+ int sec = (int) seconds;
+ int nsec = (int) ((seconds - (float) sec) * 1.0e9);
+
+ /* fill timespec to pass to nanosleep() */
+ struct timespec requested_time, remaining;
+ requested_time.tv_sec = sec;
+ requested_time.tv_nsec = nsec;
+
+ /* sleep */
+ nanosleep(&requested_time, &remaining);
+}
+
+/* fin */
Index: source/blender/commandport/utilities/src/bcp_package.c
===================================================================
--- source/blender/commandport/utilities/src/bcp_package.c (revision 0)
+++ source/blender/commandport/utilities/src/bcp_package.c (revision 0)
@@ -0,0 +1,1139 @@
+/*
+ * $Id: bcp_package.c, v 1.0 2007/05/31, dietrich, tokyo $
+ *
+ * ***** BEGIN GPL 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.
+ *
+ * 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,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * The Original Code is Copyright (C) 2007 by the Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Author: Dietrich Bollmann
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ *
+ * Functions to pack and unpack integers, strings and commands into a
+ * single string for sending them over the command port socket.
+ *
+ * header file: ../include/bcp_package.h
+ *
+ */
+
+/* fin */
+/* bcp_package.c */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "bcp_package.h"
+#include "error_codes.h"
+
+/**
+ element type
+*/
+typedef struct element_struct *element;
+typedef struct element_struct {
+ char type;
+ union {
+ int vint;
+ char* vstr;
+ char vcmd;
+ } element;
+ element next;
+} element_struct;
+
+/**
+ package type struct
+*/
+typedef struct bcp_package_struct {
+ element first;
+ element last;
+} bcp_package_struct;
+
+
+/* Declaration of utility functions */
+element new_element_allocate();
+void add_element(bcp_package p, element e);
+void delete_element(element e);
+element new_int_element(int i);
+element new_string_element(char* s);
+int intlen(int e);
+int length_packed_element(element e);
+int length_packed(bcp_package p);
+
+char* pack_element(char* buffer, element e);
+char unpack_element(bcp_package p, char** packed);
+
+int parse_int(char** s);
+char parse_char(char** s);
+char parse_type(char** s);
+void parse_newline(char** s);
+int parse_int_element(char** s);
+char* parse_string(char** s);
+char* parse_string_element(char** s);
+char parse_command_element(char** s);
+
+/* test functions */
+#ifdef BCP_PACKAGE_TEST
+#define BUFFER_SIZE 80
+void print_element(element e);
+void dump_packed_package(bcp_package p);
+void dump_packed_element(element e);
+void dump_element_header(char* header);
+#endif /* BCP_PACKAGE_TEST */
+
+
+/**
+ Make a new package.
+*/
+bcp_package bcp_package_new()
+{
+ bcp_package package;
+ package = (bcp_package) malloc(sizeof(bcp_package_struct));
+
+ if (package == NULL) {
+ fprintf(stderr, "Couldn't allocate memory for new bcp_package!\n");
+ exit(ERROR_MEMORY);
+ }
+
+ package->first = (element) NULL;
+ package->last = (element) NULL;
+
+ return package;
+}
+
+
+/**
+ Delete a package.
+*/
+void bcp_package_delete(bcp_package package)
+{
+ /* empty the package */
+ bcp_package_make_empty(package);
+
+ /* free package structure */
+ free(package);
+}
+
+
+/**
+ Empty a package.
+*/
+void bcp_package_make_empty(bcp_package package)
+{
+ /* delete all elements */
+ element e = package->first;
+ for( ; e != NULL; e = e->next) {
+ delete_element(e);
+ }
+
+ /* set pointers to NULL
+ to indicate that the package is empty */
+ package->first = (element) NULL;
+ package->last = (element) NULL;
+}
+
+
+/**
+ Allocate memory for a new package element.
+*/
+element new_element_allocate()
+{
+ element e;
+ e = (element) malloc(sizeof(element_struct));
+
+ if (e == NULL) {
+ fprintf(stderr, "Couldn't allocate memory for new bcp_package element!\n");
+ exit(ERROR_MEMORY);
+ }
+
+ e->type = BCP_PACKAGE_TYPE_UNDEFINED;
+ e->next = NULL;
+
+ return e;
+}
+
+
+/**
+ Add an element to a package.
+*/
+void add_element(bcp_package p, element e)
+{
+ /* set the 'next' member to NULL
+ to indicate that it is the last element */
+ e->next = (element) NULL;
+
+ /* append the new element to the element list of the package */
+ if (p->first == NULL) {
+ p->first = e;
+ } else {
+ p->last->next = e;
+ }
+ p->last = e;
+}
+
+
+/**
+ Delete a package element.
+*/
+void delete_element(element e)
+{
+ free(e);
+}
+
+/**
+ Make a new integer element.
+*/
+element new_int_element(int i)
+{
+ element e;
+ e = new_element_allocate();
+
+ e->type = BCP_PACKAGE_TYPE_INT;
+ e->element.vint = i;
+
+ return e;
+}
+
+/**
+ Make a new string element.
+*/
+element new_string_element(char* s)
+{
+ element e;
+ e = new_element_allocate();
+
+ e->type = BCP_PACKAGE_TYPE_STRING;
+ e->element.vstr = s;
+
+ return e;
+}
+
+/**
+ Make a new command element.
+*/
+element new_command_element(char command)
+{
+ element e;
+ e = new_element_allocate();
+
+ e->type = BCP_PACKAGE_TYPE_COMMAND;
+ e->element.vcmd = command;
+
+ return e;
+}
+
+/**
+ Add integer.
+*/
+void bcp_package_add_int(bcp_package package, int i)
+{
+ /* make a new integer element */
+ element e;
+ e = new_int_element(i);
+ add_element(package, e);
+}
+
+/**
+ Add string.
+*/
+void bcp_package_add_string(bcp_package package, char* s)
+{
+ /* make a new string element */
+ element e;
+ e = new_string_element(s);
+ add_element(package, e);
+}
+
+/**
+ Add command.
+*/
+void bcp_package_add_command(bcp_package package, char command)
+{
+ /* make a new command element */
+ element e;
+ e = new_command_element(command);
+ add_element(package, e);
+}
+
+/**
+ Calculate the length of an integers string representation.
+*/
+int intlen(int i)
+{
+ /* 0 has the length 1 */
+ if (i == 0) return 1;
+
+ /* calculate length for i > 0 */
+ int length;
+ for (length = 0; i > 0; i /= 10, length++);
+
+ /* done */
+ return length;
+}
+
+/**
+ Calculate the length of a packed element.
+*/
+int length_packed_element(element e)
+{
+ /* an undefined element will not be packed
+ - return 0 */
+ if (e->type == BCP_PACKAGE_TYPE_UNDEFINED) return 0;
+
+ /* length accumulator */
+ int length = 0;
+
+ /* add length of prefix '#' */
+ length += 1;
+
+ /* add length of the element type code
+ - the type is represented by a caracter of length 1 */
+ length += 1;
+
+ /* the header is terminated by '\n' - add 1 */
+ length += 1;
+
+ /* the rest of the header depends on the element type */
+ int vlen;
+ switch (e->type) {
+
+ case BCP_PACKAGE_TYPE_INT:
+
+ /* integer are coded as part of the header
+ example: 123 is coded as "#i123\n" */
+
+ /* add the length of the integer value */
+ length += intlen(e->element.vint);
+
+ /* done */
+ break;
+
+ case BCP_PACKAGE_TYPE_STRING:
+
+ /* the header of a string element
+ contains the lenght of the string.
+ The string value itself followes the header.
+ example: "hallo" is coded as "#s5\nhallo\n"
+ */
+
+ /* calculate the length of the string value */
+ vlen = strlen(e->element.vstr);
+
+ /* the length of the string value is written into the header
+ - add the necessary length */
+ length += intlen(vlen);
+
+ /* add the length of the string value */
+ length += vlen;
+
+ /* to faciliate the readability of the packed representation
+ a newline is added after the value - add its length */
+ length += 1;
+
+ /* done */
+ break;
+
+ case BCP_PACKAGE_TYPE_COMMAND:
+
+ /* commands are characters coded as part of the header
+ example: 'c' is coded as "#cc\n" */
+
+ /* add 1 for the command caracter */
+ length += 1;
+
+ /* done */
+ break;
+
+ default:
+ fprintf(stderr, "Found a bcp_package element with an unknown type!\n");
+ exit(ERROR_UNKNOWN_TYPE);
+ }
+
+ /* done */
+ return length;
+}
+
+/**
+ Calculate the length of the packed
+ representation of a package.
+*/
+int length_packed(bcp_package p)
+{
+ /* add the length of all elements */
+ int length = 0;
+ element e = p->first;
+ for( ; e != NULL; e = e->next) {
+ length += length_packed_element(e);
+ }
+
+ /* done */
+ return length;
+}
+
+/**
+ Code the package
+ as a human readable string.
+*/
+char* bcp_package_pack_allocate(bcp_package package)
+{
+ /* calculate length */
+ int length = length_packed(package);
+
+ /* allocate memory for the packed string representation */
+ char* packed = (char*) malloc((length + 1) * sizeof(char));
+ if (packed == NULL) {
+ fprintf(stderr, "Couldn't allocate memory to pack a bcp_package!\n");
+ exit(ERROR_MEMORY);
+ }
+
+ /* write all elements to the buffer */
+ char* p = packed;
+ element e = package->first;
+ for( ; e != NULL; e = e->next) {
+ p = pack_element(p, e);
+ }
+
+ /* terminate the packed string representation
+ with the null character */
+ *p = '\0';
+
+ /* return the packed representation */
+ return packed;
+}
+
+/**
+ Pack an element.
+*/
+char* pack_element(char* buffer, element e)
+{
+ /* an undefined element will not be packed
+ - return the buffer as it is */
+ if (e->type == BCP_PACKAGE_TYPE_UNDEFINED) return buffer;
+
+ /* the rest of the header depends on the element type */
+ switch (e->type) {
+
+ case BCP_PACKAGE_TYPE_INT:
+
+ /* integer are coded as part of the header
+ example: 123 is coded as "#i123\n" */
+
+ /* add the integer element */
+ buffer += sprintf(buffer, "#i%d\n", e->element.vint);
+
+ /* done */
+ break;
+
+ case BCP_PACKAGE_TYPE_STRING:
+
+ /* the header of a string element
+ contains the lenght of the string.
+ The string value itself followes the header.
+ example: "hallo" is coded as "#s5\nhallo\n"
+ */
+
+ /* write the string header */
+ buffer += sprintf(buffer, "#s%d\n", strlen(e->element.vstr));
+
+ /* write the string itself */
+ buffer += sprintf(buffer, "%s\n", e->element.vstr);
+
+ /* done */
+ break;
+
+ case BCP_PACKAGE_TYPE_COMMAND:
+
+ /* commands are characters coded as part of the header
+ example: 'c' is coded as "#cc\n" */
+
+ /* write the command element */
+ buffer += sprintf(buffer, "#c%c\n", e->element.vcmd);
+
+ /* done */
+ break;
+
+ default:
+ fprintf(stderr, "Found a bcp_package element with an unknown type!\n");
+ exit(ERROR_UNKNOWN_TYPE);
+ }
+
+ /* return a pointer to the next unwritten caracter */
+ return buffer;
+}
+
+/**
+ Unpack the elements in the string `packed'
+ and return the result package.
+*/
+bcp_package bcp_package_unpack(char* packed)
+{
+ /* make a new empty package */
+ bcp_package package;
+ package = bcp_package_new();
+
+ /* unpack all elements */
+ char** p = &packed;
+ char type;
+
+ do {
+ type = unpack_element(package, p);
+ } while (*p != NULL);
+
+ /* return the new package */
+ return package;
+}
+
+/**
+ Unpack the first element in `packed'.
+ A pointer to the next element
+ - or NULL if the current element was the last one -
+ is returned.
+*/
+char unpack_element(bcp_package p, char** packed)
+{
+ /* set return *packed to NULL and
+ return BCP_PACKAGE_TYPE_EMPTY
+ if there are no more elements to parse */
+ if (**packed == '\0') {
+ *packed = NULL; /* NULL to signal that there are no more elements */
+ return BCP_PACKAGE_TYPE_EMPTY; /* return BCP_PACKAGE_TYPE_EMPTY
+ to signal that there are no more elements */
+ }
+
+ /* unpack element type */
+ char type;
+ type = parse_type(packed);
+ /* DEBUG: printf("type: %c, rest: \"%s\"\n", type, *packed); */
+
+ /* print value */
+ int integer;
+ char* str;
+ char command;
+ switch (type) {
+
+ case BCP_PACKAGE_TYPE_UNDEFINED:
+ /* do nothing */
+ break;
+
+ case BCP_PACKAGE_TYPE_INT:
+
+ /* unpack integer */
+ integer = parse_int_element(packed);
+
+ /* add the integer */
+ bcp_package_add_int(p, integer);
+
+ break;
+
+ case BCP_PACKAGE_TYPE_STRING:
+
+ /* unpack string */
+ str = parse_string_element(packed);
+
+ /* add string */
+ bcp_package_add_string(p, str);
+
+ break;
+
+ case BCP_PACKAGE_TYPE_COMMAND:
+
+ /* unpack command */
+ command = parse_command_element(packed);
+
+ /* add a command */
+ bcp_package_add_command(p, command);
+
+ break;
+
+ default:
+ fprintf(stderr, "Found a bcp_package element with an unknown type!\n");
+ exit(ERROR_UNKNOWN_TYPE);
+ }
+
+ /* return type of parsed element */
+ return type;
+}
+
+/**
+ Parse a caracter from the beginning of string `*s'
+ and return it.
+*/
+char parse_char(char** s)
+{
+ /* parse character */
+ char c;
+ int parsed;
+ parsed = sscanf(*s, "%c", &c);
+
+ /* check if the item could be parsed */
+ if (parsed != 1) {
+ fprintf(stderr, "ERROR: Couldn't parse caracter: %s\n", *s);
+ exit(ERROR_PARSER);
+ }
+
+ /* advance to the next caracters */
+ (*s)++;
+
+ /* return parsed char */
+ return c;
+}
+
+/**
+ Parse an integer from the beginning of string `s'
+ and return it.
+*/
+int parse_int(char** s)
+{
+ /* parse character */
+ int i;
+ int parsed;
+ parsed = sscanf(*s, "%d", &i);
+
+ /* check if the item could be parsed */
+ if (parsed != 1) {
+ fprintf(stderr, "ERROR: Couldn't parse integer: %s\n", *s);
+ exit(ERROR_PARSER);
+ }
+
+ /* calculate length of parsed integer string */
+ int length;
+ length = intlen(i);
+
+ /* advance to the next caracters */
+ *s += length;
+
+ /* return the parsed integer */
+ return i;
+}
+
+/**
+ Parse a type from the beginning of string `*s'
+ and return the it.
+*/
+char parse_type(char** s)
+{
+ /* parse number sign (#) */
+ char number_sign;
+ number_sign = parse_char(s);
+
+ /* check if the item could be parsed */
+ if (number_sign != '#') {
+ fprintf(stderr, "ERROR: Couldn't parse type: %s\n", *s);
+ exit(ERROR_PARSER);
+ }
+
+ /* parse the type caracter */
+ char type;
+ type = parse_char(s);
+
+ /* return parsed type */
+ return type;
+}
+
+/**
+ Parse a newline caracter from the beginning of string `*s'.
+*/
+void parse_newline(char** s)
+{
+ /* parse character */
+ char newline;
+ newline = parse_char(s);
+
+ /* check if the item could be parsed */
+ if (newline != '\n') {
+ fprintf(stderr, "ERROR: Couldn't parse newline: %s\n", *s);
+ exit(ERROR_PARSER);
+ }
+}
+
+/**
+ Parse an integer element
+ and return it.
+*/
+int parse_int_element(char** s)
+{
+ /* extract the integer */
+ int i;
+ i = parse_int(s);
+
+ /* parse the newline terminating the header */
+ parse_newline(s);
+
+ /* return parsed integer */
+ return i;
+}
+
+/**
+ Parse a string
+ and return a pointer to it.
+*/
+char* parse_string(char** s)
+{
+ /* extract the length of the string */
+ int length;
+ length = parse_int(s);
+
+ /* parse the newline terminating the header */
+ parse_newline(s);
+
+ /* store pointer to found string */
+ char* str;
+ str = *s;
+
+ /* calculate the position of the newline caracter
+ which terminates the string */
+ *s = *s + length;
+
+ /* overwrite the newline character at the end of the string
+ with a string terminator / null caracter */
+ **s = '\0';
+
+ /* calculate the position of the next packed element */
+ (*s)++;
+
+ /* return pointer to the found string */
+ return str;
+}
+
+/**
+ Parse a string element
+ and return a pointer to it.
+*/
+char* parse_string_element(char** s)
+{
+ /* extract the integer */
+ char* str;
+ str = parse_string(s);
+
+ /* return pointer to parsed string */
+ return str;
+}
+
+/**
+ Parse a command element
+ and return a pointer to it.
+*/
+char parse_command_element(char** s)
+{
+ /* parse character */
+ char command;
+ command = parse_char(s);
+
+ /* calculate the position of the next packed element */
+ (*s)++;
+
+ /* return the parsed command */
+ return command;
+}
+
+/* =========================================================
+ * BCP package enumerator functions
+ * ---------------------------------------------------------
+ */
+
+/**
+ package enumerator type struct
+*/
+typedef struct bcp_package_enumerator_struct {
+ bcp_package package;
+ element next;
+} bcp_package_enumerator_struct;
+
+/**
+ Make a new enumerator.
+*/
+bcp_package_enumerator bcp_package_enumerator_new(bcp_package p)
+{
+ bcp_package_enumerator enumerator;
+ enumerator = (bcp_package_enumerator) malloc(sizeof(bcp_package_enumerator_struct));
+
+ if (enumerator == NULL) {
+ fprintf(stderr, "Couldn't allocate memory for new bcp_package_enumerator!\n");
+ exit(ERROR_MEMORY);
+ }
+
+ enumerator->package = p;
+ enumerator->next = p->first;
+
+ return enumerator;
+}
+
+/**
+ Delete a package enumerator.
+*/
+void bcp_package_enumerator_delete(bcp_package_enumerator enumerator)
+{
+ /* free enumerator structure */
+ free(enumerator);
+}
+
+/**
+ Reset enumerator.
+*/
+void bcp_package_enumerator_reset(bcp_package_enumerator e)
+{
+ e->next = e->package->first;
+}
+
+/**
+ Get next element in package.
+*/
+void* bcp_package_enumerator_get_next_element(bcp_package_enumerator e, char* type)
+{
+ /* get next element */
+ element elem = e->next;
+
+ /* if there is no next element
+ set type to BCP_PACKAGE_TYPE_EMPTY to indicate that there is no further element
+ and return NULL
+ */
+ if (elem == NULL) {
+ *type = BCP_PACKAGE_TYPE_EMPTY;
+ return NULL;
+ }
+
+ /* set enumerators `next' pointer to `elem's next element */
+ e->next = elem->next;
+
+ /* get type of found element */
+ *type = elem->type;
+
+ /* return pointer to value */
+ switch (*type) {
+
+ case BCP_PACKAGE_TYPE_UNDEFINED:
+ return (void*) NULL;
+ break;
+
+ case BCP_PACKAGE_TYPE_INT:
+ return (void*) &(elem->element.vint);
+ break;
+
+ case BCP_PACKAGE_TYPE_STRING:
+ return (void*) elem->element.vstr;
+ break;
+
+ case BCP_PACKAGE_TYPE_COMMAND:
+ return (void*) &(elem->element.vcmd);
+ break;
+
+ default:
+ fprintf(stderr, "Found a bcp_package element with an unknown type!\n");
+ exit(ERROR_UNKNOWN_TYPE);
+ }
+}
+
+/* =========================================================
+ * Test functions
+ * ---------------------------------------------------------
+ */
+
+#ifdef BCP_PACKAGE_TEST
+
+void bcp_package_test()
+{
+ /* stuff needed for the tests */
+ char buffers[BUFFER_SIZE][BUFFER_SIZE];
+
+ /* test */
+ printf("[test] Make a package, add elements, delete package:\n");
+ printf("\n");
+
+ /* make a new package */
+ bcp_package package;
+ package = bcp_package_new();
+
+ /* add some elements */
+ int i;
+ int j = 1;
+ for (i = 0; i < 3; i++) {
+
+ /* add an integer */
+ bcp_package_add_int(package, j);
+
+ /* add a string */
+ sprintf(buffers[i], "Hi, number %d :)", j);
+ bcp_package_add_string(package, buffers[i]);
+
+ /* add a command */
+ char command = 'a' + i;
+ bcp_package_add_command(package, command);
+
+ /* calculate a new example integer */
+ j *= j * 100;
+ }
+
+ /* dump */
+ printf(">>> dumping the original package:\n");
+ dump_package(package);
+ printf("\n");
+
+ /* DEBUG - for a more detailed dump uncomment the following: */
+ /*
+ dump_packed_package(package);
+ printf("\n");
+ */
+
+ /* pack */
+ char* packed;
+ packed = bcp_package_pack_allocate(package);
+
+ /* print packed package */
+ printf(">>> the packed package:\n");
+ printf(">>>%s<<<\n", packed);
+ printf("\n");
+
+ /* delete package */
+ bcp_package_delete(package);
+
+ /* unpack the string `packed' */
+ bcp_package package2;
+ package2 = bcp_package_unpack(packed);
+
+ /* dump */
+ printf(">>> dumping the unpacked package:\n");
+ dump_package(package2);
+ printf("\n");
+
+ /* DEBUG - for a more detailed dump uncomment the following: */
+ /*
+ dump_packed_package(package);
+ printf("\n");
+ */
+
+ /* test the enumerator functions */
+ printf(">>> testing enumerator functions:\n");
+ printf("\n");
+
+ /* make new package enumerator */
+ bcp_package_enumerator enumerator;
+ enumerator = bcp_package_enumerator_new(package2);
+
+ /* header */
+ printf(" listing elements:\n");
+
+ /* print element */
+ i = 0;
+ void* elem;
+ char type;
+ while (1) {
+
+ /* get next element */
+ elem = bcp_package_enumerator_get_next_element(enumerator, &type);
+
+ /* if there are no more elements - exit */
+ if (type == BCP_PACKAGE_TYPE_EMPTY) break;
+
+ /* print index and type of element */
+ printf(" %3d. (%c): ", i, type);
+
+ /* print value */
+ switch (type) {
+
+ case BCP_PACKAGE_TYPE_UNDEFINED:
+ printf("<empty>");
+ break;
+
+ case BCP_PACKAGE_TYPE_INT:
+ printf("%d", *((int*) elem));
+ break;
+
+ case BCP_PACKAGE_TYPE_STRING:
+ printf("\"%s\"", (char*) elem);
+ break;
+
+ case BCP_PACKAGE_TYPE_COMMAND:
+ printf("%c", *((char*) elem));
+ break;
+
+ default:
+ fprintf(stderr, "Found a bcp_package element with an unknown type!\n");
+ exit(ERROR_UNKNOWN_TYPE);
+ }
+
+ printf("\n");
+
+ /* increment element index */
+ i++;
+ }
+
+ /* all elements have been printed */
+ printf(" done.\n");
+
+ /* delete the package enumerator */
+ bcp_package_enumerator_delete(enumerator);
+
+ printf("\n");
+
+ /* delete package */
+ bcp_package_delete(package2);
+
+ /* free the packed string representation */
+ free(packed);
+ packed = NULL;
+
+ /* done :) */
+ printf("bye :)\n");
+ printf("\n");
+}
+
+/**
+ Dump all elements in a package.
+
+ example:
+
+ (package): {
+ 0. (c): 'a'
+ 1. (i): 124,
+ 2. (s): "laber",
+ }
+
+*/
+void dump_package(bcp_package p)
+{
+ /* print first line: type and length of the package */
+ printf(" (package,%d): {\n", length_packed(p));
+
+ /* print elements */
+ int i = 0;
+ element e = p->first;
+ for( ; e != NULL; i++, e = e->next) {
+
+ /* print number, type and value of the ith element */
+ printf(" %3d. (%c): ", i, e->type);
+ print_element(e);
+ printf(",\n");
+ }
+
+ /* print last line */
+ printf(" }\n");
+}
+
+/**
+ Dump an element.
+*/
+void print_element(element e)
+{
+ /* print value */
+ switch (e->type) {
+
+ case BCP_PACKAGE_TYPE_UNDEFINED:
+ printf("<empty>");
+ break;
+
+ case BCP_PACKAGE_TYPE_INT:
+ printf("%d", e->element.vint);
+ break;
+
+ case BCP_PACKAGE_TYPE_STRING:
+ printf("\"%s\"", e->element.vstr);
+ break;
+
+ case BCP_PACKAGE_TYPE_COMMAND:
+ printf("%c", e->element.vcmd);
+ break;
+
+ default:
+ fprintf(stderr, "Found a bcp_package element with an unknown type!\n");
+ exit(ERROR_UNKNOWN_TYPE);
+ }
+}
+
+/**
+ Dump all elements in a package
+ together with their packed representation.
+*/
+void dump_packed_package(bcp_package p)
+{
+ /* print first line: type and length of the package */
+ printf(" package:\n");
+ print