# HG changeset patch
# User etisserant
# Date 1230057464 -3600
# Node ID f2ef79f3dba0a93951be136207ce34d0027a911b
# Parent 47d29c4b55a30331175d71b50b633a6f5862c407
Added native (not a plugin) asynchronous python eval function block - Beta. Code cleanup in C code templates.
diff -r 47d29c4b55a3 -r f2ef79f3dba0 plugger.py
--- a/plugger.py Tue Dec 23 19:31:28 2008 +0100
+++ b/plugger.py Tue Dec 23 19:37:44 2008 +0100
@@ -1078,6 +1078,23 @@
return debug_code
+ def Generate_plc_python(self):
+ """
+ Generate trace/debug code out of PLC variable list
+ """
+ self.GetIECProgramsAndVariables()
+
+ python_eval_fb_list = []
+ for v in self._VariablesList :
+ if v["vartype"] == "FB" and v["type"] == "PYTHON_EVAL":
+ python_eval_fb_list.append(v)
+ python_eval_fb_count = len(python_eval_fb_list)
+
+ # prepare debug code
+ python_code = targets.code("plc_python") % {
+ "python_eval_fb_count": python_eval_fb_count}
+ return python_code
+
def Generate_plc_common_main(self):
"""
Use plugins layout given in LocationCFilesAndCFLAGS to
@@ -1175,6 +1192,8 @@
for generator, filename, name in [
# debugger code
(self.Generate_plc_debugger, "plc_debugger.c", "Debugger"),
+ # IEC<->python gateway code
+ (self.Generate_plc_python, "plc_python.c", "IEC-Python gateway"),
# init/cleanup/retrieve/publish, run and align code
(self.Generate_plc_common_main,"plc_common_main.c","Common runtime")]:
try:
@@ -1408,7 +1427,7 @@
# This will block thread if more than one call is waiting
elif debug_vars is not None:
wx.CallAfter(self.logger.write_warning,
- "debug data not coherent %d != %d"%(len(debug_vars), len(self.TracedIECPath)))
+ "Debug data not coherent %d != %d\n"%(len(debug_vars), len(self.TracedIECPath)))
elif debug_tick == -1:
#wx.CallAfter(self.logger.write, "Debugger unavailable\n")
pass
diff -r 47d29c4b55a3 -r f2ef79f3dba0 pous.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pous.xml Tue Dec 23 19:37:44 2008 +0100
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff -r 47d29c4b55a3 -r f2ef79f3dba0 runtime/PLCObject.py
--- a/runtime/PLCObject.py Tue Dec 23 19:31:28 2008 +0100
+++ b/runtime/PLCObject.py Tue Dec 23 19:37:44 2008 +0100
@@ -23,8 +23,9 @@
#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
import Pyro.core as pyro
-from threading import Timer
+from threading import Timer, Thread
import ctypes, os, commands
+import time
if os.name in ("nt", "ce"):
from _ctypes import LoadLibrary as dlopen
@@ -107,6 +108,10 @@
self._resumeDebug = self.PLClibraryHandle.resumeDebug
self._resumeDebug.restype = None
+
+ self._PythonIterator = self.PLClibraryHandle.PythonIterator
+ self._PythonIterator.restype = ctypes.c_char_p
+ self._PythonIterator.argtypes = [ctypes.c_char_p]
return True
except:
@@ -128,6 +133,7 @@
self._WaitDebugData = lambda:-1
self._suspendDebug = lambda:None
self._resumeDebug = lambda:None
+ self._PythonIterator = lambda:""
self.PLClibraryHandle = None
# Unload library explicitely
if getattr(self,"_PLClibraryHandle",None) is not None:
@@ -163,6 +169,18 @@
return True
return False
+ def PythonThreadProc(self):
+ res = ""
+ print "PythonThreadProc started"
+ while self.PLCStatus == "Started":
+ cmd = self._PythonIterator(res)
+ print "_PythonIterator(", res, ") -> ", cmd
+ try :
+ res = eval(cmd)
+ except Exception,e:
+ res = "#EXCEPTION : "+str(e)
+ print res
+ print "PythonThreadProc finished"
def StartPLC(self, debug=False):
print "StartPLC"
@@ -174,6 +192,8 @@
self.PLCStatus = "Started"
if self.statuschange is not None:
self.statuschange(self.PLCStatus)
+ self.PythonThread = Thread(target=self.PythonThreadProc)
+ self.PythonThread.start()
return True
else:
print "_StartPLC did not return 0 !"
@@ -270,6 +290,13 @@
for idx in idxs:
self._RegisterDebugVariable(idx)
self._resumeDebug()
+
+ class IEC_STRING(ctypes.Structure):
+ """
+ Must be changed according to changes in iec_types.h
+ """
+ _fields_ = [("len", ctypes.c_uint8),
+ ("body", ctypes.c_char * 40)]
TypeTranslator = {"BOOL" : (ctypes.c_uint8, lambda x:x.value!=0),
"STEP" : (ctypes.c_uint8, lambda x:x.value),
@@ -278,7 +305,7 @@
"SINT" : (ctypes.c_int8, lambda x:x.value),
"USINT" : (ctypes.c_uint8, lambda x:x.value),
"BYTE" : (ctypes.c_uint8, lambda x:x.value),
- "STRING" : (None, None),#TODO
+ "STRING" : (IEC_STRING, lambda x:x.body[:x.len]),
"INT" : (ctypes.c_int16, lambda x:x.value),
"UINT" : (ctypes.c_uint16, lambda x:x.value),
"WORD" : (ctypes.c_uint16, lambda x:x.value),
diff -r 47d29c4b55a3 -r f2ef79f3dba0 targets/Linux/plc_Linux_main.c
--- a/targets/Linux/plc_Linux_main.c Tue Dec 23 19:31:28 2008 +0100
+++ b/targets/Linux/plc_Linux_main.c Tue Dec 23 19:37:44 2008 +0100
@@ -1,3 +1,7 @@
+/**
+ * Linux specific code
+ **/
+
#include
#include
#include
@@ -5,16 +9,14 @@
#include
#include
+/* provided by POUS.C */
+extern int common_ticktime__;
+
long AtomicCompareExchange(long* atomicvar,long compared, long exchange)
{
return __sync_val_compare_and_swap(atomicvar, compared, exchange);
}
-//long AtomicExchange(long* atomicvar,long exchange)
-//{
-// return __sync_lock_test_and_set(atomicvar, exchange);
-//}
-
void PLC_GetTime(IEC_TIME *CURRENT_TIME)
{
clock_gettime(CLOCK_REALTIME, CURRENT_TIME);
@@ -64,9 +66,12 @@
static int __debug_tick;
-static pthread_mutex_t wait_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t python_wait_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t python_mutex = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t debug_wait_mutex = PTHREAD_MUTEX_INITIALIZER;
static pthread_mutex_t debug_mutex = PTHREAD_MUTEX_INITIALIZER;
+#define maxval(a,b) ((a>b)?a:b)
int startPLC(int argc,char **argv)
{
struct sigevent sigev;
@@ -79,7 +84,8 @@
sigev.sigev_notify_attributes = NULL;
sigev.sigev_notify_function = PLC_timer_notify;
- pthread_mutex_lock(&wait_mutex);
+ pthread_mutex_lock(&debug_wait_mutex);
+ pthread_mutex_lock(&python_wait_mutex);
timer_create (CLOCK_REALTIME, &sigev, &PLC_timer);
if( __init(argc,argv) == 0 ){
@@ -111,7 +117,7 @@
timer_delete (PLC_timer);
__cleanup();
__debug_tick = -1;
- pthread_mutex_unlock(&wait_mutex);
+ pthread_mutex_unlock(&debug_wait_mutex);
}
extern int __tick;
@@ -119,7 +125,7 @@
int WaitDebugData()
{
/* Wait signal from PLC thread */
- pthread_mutex_lock(&wait_mutex);
+ pthread_mutex_lock(&debug_wait_mutex);
return __debug_tick;
}
@@ -127,25 +133,49 @@
* This is supposed to unlock debugger thread in WaitDebugData*/
void InitiateDebugTransfer()
{
- /* Leave debugger section */
- pthread_mutex_unlock(&debug_mutex);
/* remember tick */
__debug_tick = __tick;
/* signal debugger thread it can read data */
- pthread_mutex_unlock(&wait_mutex);
+ pthread_mutex_unlock(&debug_wait_mutex);
}
-void suspendDebug()
+void suspendDebug(void)
{
- __DEBUG = 0;
/* Prevent PLC to enter debug code */
pthread_mutex_lock(&debug_mutex);
}
-void resumeDebug()
+void resumeDebug(void)
{
- __DEBUG = 1;
/* Let PLC enter debug code */
pthread_mutex_unlock(&debug_mutex);
}
+/* from plc_python.c */
+int WaitPythonCommands(void)
+{
+ /* Wait signal from PLC thread */
+ pthread_mutex_lock(&python_wait_mutex);
+}
+
+/* Called by PLC thread on each new python command*/
+void UnBlockPythonCommands(void)
+{
+ /* signal debugger thread it can read data */
+ pthread_mutex_unlock(&python_wait_mutex);
+}
+
+int TryLockPython(void)
+{
+ return pthread_mutex_trylock(&python_mutex) == 0;
+}
+
+void UnLockPython(void)
+{
+ pthread_mutex_unlock(&python_mutex);
+}
+
+void LockPython(void)
+{
+ pthread_mutex_lock(&python_mutex);
+}
diff -r 47d29c4b55a3 -r f2ef79f3dba0 targets/Win32/plc_Win32_main.c
--- a/targets/Win32/plc_Win32_main.c Tue Dec 23 19:31:28 2008 +0100
+++ b/targets/Win32/plc_Win32_main.c Tue Dec 23 19:37:44 2008 +0100
@@ -1,18 +1,20 @@
+/**
+ * Win32 specific code
+ **/
+
#include
#include
#include
#include
+/* provided by POUS.C */
+extern int common_ticktime__;
+
long AtomicCompareExchange(long* atomicvar, long compared, long exchange)
{
return InterlockedCompareExchange(atomicvar, exchange, compared);
}
-//long AtomicExchange(long* atomicvar,long exchange)
-//{
-// return InterlockedExchange(atomicvar, exchange);
-//}
-
struct _timeb timetmp;
void PLC_GetTime(IEC_TIME *CURRENT_TIME)
{
@@ -64,9 +66,11 @@
HANDLE PLC_thread;
HANDLE debug_sem;
-HANDLE wait_sem;
-#define MAX_SEM_COUNT 1
-
+HANDLE debug_wait_sem;
+HANDLE python_sem;
+HANDLE python_wait_sem;
+
+#define maxval(a,b) ((a>b)?a:b)
int startPLC(int argc,char **argv)
{
unsigned long thread_id = 0;
@@ -76,25 +80,50 @@
debug_sem = CreateSemaphore(
NULL, // default security attributes
1, // initial count
- MAX_SEM_COUNT, // maximum count
+ 1, // maximum count
NULL); // unnamed semaphore
if (debug_sem == NULL)
{
- printf("CreateMutex error: %d\n", GetLastError());
+ printf("startPLC CreateSemaphore debug_sem error: %d\n", GetLastError());
return;
}
- wait_sem = CreateSemaphore(
+ debug_wait_sem = CreateSemaphore(
NULL, // default security attributes
0, // initial count
- MAX_SEM_COUNT, // maximum count
- NULL); // unnamed semaphore
-
- if (wait_sem == NULL)
- {
- printf("CreateMutex error: %d\n", GetLastError());
- return;
- }
+ 1, // maximum count
+ NULL); // unnamed semaphore
+
+ if (debug_wait_sem == NULL)
+ {
+ printf("startPLC CreateSemaphore debug_wait_sem error: %d\n", GetLastError());
+ return;
+ }
+
+ python_sem = CreateSemaphore(
+ NULL, // default security attributes
+ 1, // initial count
+ 1, // maximum count
+ NULL); // unnamed semaphore
+
+ if (python_sem == NULL)
+ {
+ printf("startPLC CreateSemaphore python_sem error: %d\n", GetLastError());
+ return;
+ }
+ python_wait_sem = CreateSemaphore(
+ NULL, // default security attributes
+ 0, // initial count
+ 1, // maximum count
+ NULL); // unnamed semaphore
+
+
+ if (python_wait_sem == NULL)
+ {
+ printf("startPLC CreateSemaphore python_wait_sem error: %d\n", GetLastError());
+ return;
+ }
+
/* Create a waitable timer */
PLC_timer = CreateWaitableTimer(NULL, FALSE, "WaitableTimer");
@@ -133,9 +162,9 @@
WaitForSingleObject(PLC_thread, INFINITE);
__cleanup();
__debug_tick = -1;
- ReleaseSemaphore(wait_sem, 1, NULL);
+ ReleaseSemaphore(debug_wait_sem, 1, NULL);
CloseHandle(debug_sem);
- CloseHandle(wait_sem);
+ CloseHandle(debug_wait_sem);
CloseHandle(PLC_timer);
CloseHandle(PLC_thread);
}
@@ -143,30 +172,58 @@
/* from plc_debugger.c */
int WaitDebugData()
{
- WaitForSingleObject(wait_sem, INFINITE);
+ WaitForSingleObject(debug_wait_sem, INFINITE);
return __debug_tick;
}
-/* Called by PLC thread when debug_pu//blish finished
+/* Called by PLC thread when debug_publish finished
* This is supposed to unlock debugger thread in WaitDebugData*/
void InitiateDebugTransfer()
{
/* remember tick */
__debug_tick = __tick;
/* signal debugger thread it can read data */
- ReleaseSemaphore(wait_sem, 1, NULL);
+ ReleaseSemaphore(debug_wait_sem, 1, NULL);
}
void suspendDebug()
{
- __DEBUG = 0;
/* Prevent PLC to enter debug code */
WaitForSingleObject(debug_sem, INFINITE);
}
void resumeDebug()
{
- __DEBUG = 1;
/* Let PLC enter debug code */
ReleaseSemaphore(debug_sem, 1, NULL);
}
+
+/* from plc_python.c */
+int WaitPythonCommands(void)
+{
+ /* Wait signal from PLC thread */
+ WaitForSingleObject(python_wait_sem, INFINITE);
+}
+
+/* Called by PLC thread on each new python command*/
+void UnBlockPythonCommands(void)
+{
+ /* signal debugger thread it can read data */
+ ReleaseSemaphore(python_wait_sem, 1, NULL);
+}
+
+int TryLockPython(void)
+{
+ return WaitForSingleObject(python_sem, 0) == WAIT_OBJECT_0;
+}
+
+void UnLockPython(void)
+{
+ ReleaseSemaphore(python_sem, 1, NULL);
+}
+
+void LockPython(void)
+{
+ WaitForSingleObject(python_sem, INFINITE);
+}
+
diff -r 47d29c4b55a3 -r f2ef79f3dba0 targets/plc_common_main.c
--- a/targets/plc_common_main.c Tue Dec 23 19:31:28 2008 +0100
+++ b/targets/plc_common_main.c Tue Dec 23 19:37:44 2008 +0100
@@ -1,41 +1,35 @@
-/*
- * Prototypes for function provided by arch-specific code (main)
- * concatained after this template
- ** /
+/**
+ * Code common to all C targets
+ **/
+#include "iec_types.h"
/*
- * Functions and variables provied by generated C softPLC
- **/
-extern int common_ticktime__;
-
-/*
- * Functions and variables provied by plc.c
- **/
-void run(long int tv_sec, long int tv_nsec);
-
-#define maxval(a,b) ((a>b)?a:b)
-
-#include "iec_types.h"
-/*#include "stdio.h" /* For debug */
-
-/*
- * Functions and variables provied by generated C softPLC
+ * Prototypes of functions provied by generated C softPLC
**/
void config_run__(int tick);
void config_init__(void);
+
+/*
+ * Prototypes of functions provied by generated target C code
+ * */
void __init_debug(void);
void __cleanup_debug(void);
+/*void __retrieve_debug(void);*/
+void __publish_debug(void);
+void __init_python(void);
+void __cleanup_python(void);
+void __retrieve_python(void);
+void __publish_python(void);
/*
- * Functions and variables to export to generated C softPLC and plugins
+ * Variables used by generated C softPLC and plugins
**/
-
IEC_TIME __CURRENT_TIME;
-IEC_BOOL __DEBUG;
int __tick = -1;
+/* Help to quit cleanly when init fail at a certain level */
static int init_level = 0;
/*
@@ -52,10 +46,14 @@
%(retrieve_calls)s
+ __retrieve_python();
+
/*__retrieve_debug();*/
config_run__(__tick);
+ __publish_python();
+
__publish_debug();
%(publish_calls)s
@@ -169,3 +167,8 @@
}
}
}
+
+/**
+ * Prototypes for function provided by arch-specific code (main)
+ * is concatained hereafter
+ **/
\ No newline at end of file
diff -r 47d29c4b55a3 -r f2ef79f3dba0 targets/plc_debug.c
--- a/targets/plc_debug.c Tue Dec 23 19:31:28 2008 +0100
+++ b/targets/plc_debug.c Tue Dec 23 19:37:44 2008 +0100
@@ -53,10 +53,7 @@
void __init_debug()
{
%(variables_pointer_type_table_initializer)s
-AtomicCompareExchange(
- &buffer_state,
- BUFFER_BUSY,
- BUFFER_FREE);
+ buffer_state = BUFFER_FREE;
}
void __cleanup_debug()
diff -r 47d29c4b55a3 -r f2ef79f3dba0 targets/plc_python.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/targets/plc_python.c Tue Dec 23 19:37:44 2008 +0100
@@ -0,0 +1,179 @@
+/*
+ * Python Asynchronous execution code
+ *
+ * PLC put python commands in a fifo, respecting execution order
+ * with the help of C pragmas inserted in python_eval FB code
+ *
+ * Buffer content is read asynchronously, (from non real time part),
+ * commands are executed and result stored for later use by PLC.
+ *
+ * In this implementation, fifo is a list of pointer to python_eval
+ * function blocks structures. Some local variables have been added in
+ * python_eval interface. We use those local variables as buffer and state
+ * flags.
+ *
+ * */
+
+#include "iec_types_all.h"
+#include "POUS.h"
+#include
+
+/* The fifo (fixed size, as number of FB is fixed) */
+static PYTHON_EVAL* EvalFBs[%(python_eval_fb_count)d];
+/* Producer and consumer cursors */
+static long Current_PLC_EvalFB;
+static long Current_Python_EvalFB;
+
+/* A global IEC-Python gateway state, for use inside python_eval FBs*/
+static int PythonState;
+#define PYTHON_LOCKED_BY_PYTHON 0
+#define PYTHON_LOCKED_BY_PLC 1
+#define PYTHON_MUSTWAKEUP 2
+
+/* Each python_eval FunctionBlock have it own state */
+#define PYTHON_FB_FREE 0
+#define PYTHON_FB_REQUESTED 1
+#define PYTHON_FB_PROCESSING 2
+#define PYTHON_FB_ANSWERED 3
+
+int WaitPythonCommands(void);
+void UnBlockPythonCommands(void);
+int TryLockPython(void);
+void UnLockPython(void);
+void LockPython(void);
+
+void __init_python()
+{
+ int i;
+ /* Initialize cursors */
+ Current_Python_EvalFB = 0;
+ Current_PLC_EvalFB = 0;
+ PythonState = PYTHON_LOCKED_BY_PYTHON;
+ for(i = 0; i < %(python_eval_fb_count)d; i++)
+ EvalFBs[i] = NULL;
+}
+
+void __cleanup_python()
+{
+}
+
+void __retrieve_python()
+{
+ /* Check Python thread is not being
+ * modifying internal python_eval data */
+ PythonState = TryLockPython() ?
+ PYTHON_LOCKED_BY_PLC :
+ PYTHON_LOCKED_BY_PYTHON;
+ /* If python thread _is_ in, then PythonState remains PYTHON_LOCKED_BY_PYTHON
+ * and python_eval will no do anything */
+}
+
+void __publish_python()
+{
+ if(PythonState & PYTHON_LOCKED_BY_PLC){
+ /* If runnig PLC did push something in the fifo*/
+ if(PythonState & PYTHON_MUSTWAKEUP){
+ /* WakeUp python thread */
+ UnBlockPythonCommands();
+ }
+ UnLockPython();
+ }
+}
+/**
+ * Called by the PLC, each time a python_eval
+ * FB instance is executed
+ */
+void __PythonEvalFB(PYTHON_EVAL* data__)
+{
+ /* python thread is not in ? */
+ if( PythonState & PYTHON_LOCKED_BY_PLC){
+ /* Rising edge on TRIG */
+ if(data__->TRIG && !data__->TRIGM1 &&
+ /* and not already being processed */
+ data__->STATE == PYTHON_FB_FREE)
+ {
+ /* Get a new line */
+ Current_PLC_EvalFB = (Current_PLC_EvalFB + 1) %% %(python_eval_fb_count)d;
+ /* Enter the block in the fifo
+ /* Don't have to check if fifo cell is free
+ * as fifo size == FB count, and a FB cannot
+ * be requested twice */
+ EvalFBs[Current_PLC_EvalFB] = data__;
+ /* copy CODE in variable into BUFFER local*/
+ data__->BUFFER = data__->CODE;
+ /* Set ACK pin to low so that we can set a rising edge on result */
+ data__->ACK = 0;
+ /* Mark FB busy */
+ data__->STATE = PYTHON_FB_REQUESTED;
+ /* Have to wakeup python thread in case he was asleep */
+ PythonState |= PYTHON_MUSTWAKEUP;
+ //printf("__PythonEvalFB push %%*s\n",data__->BUFFER.len, data__->BUFFER.body);
+ }else if(data__->STATE == PYTHON_FB_ANSWERED){
+ data__->RESULT = data__->BUFFER;
+ data__->ACK = 1;
+ data__->STATE = PYTHON_FB_FREE;
+ //printf("__PythonEvalFB pop %%*s\n",data__->BUFFER.len, data__->BUFFER.body);
+ }
+ /* retain value for trig
+ * do this only when PYTHON_LOCKED_BY_PLC
+ * to avoid missed rising edge due to asynchronism */
+ data__->TRIGM1 = data__->TRIG;
+ }
+}
+
+char* PythonIterator(char* result)
+{
+ char* next_command;
+ PYTHON_EVAL* data__;
+ //printf("PythonIterator result %%s\n", result);
+ /* take python mutex to prevent changing PLC data while PLC running */
+ LockPython();
+ /* Get current FB */
+ data__ = EvalFBs[Current_Python_EvalFB];
+ if(data__ && /* may be null at first run */
+ data__->STATE == PYTHON_FB_PROCESSING){ /* some answer awaited*/
+ /* If result not None */
+ if(result){
+ /* Get results len */
+ data__->BUFFER.len = strlen(result);
+ /* prevent results overrun */
+ if(data__->BUFFER.len > STR_MAX_LEN)
+ {
+ data__->BUFFER.len = STR_MAX_LEN;
+ /* TODO : signal error */
+ }
+ /* Copy results to buffer */
+ strncpy(data__->BUFFER.body, result, data__->BUFFER.len);
+ }else{
+ data__->BUFFER.len = 0;
+ }
+ /* remove block from fifo*/
+ EvalFBs[Current_Python_EvalFB] = NULL;
+ /* Mark block as answered */
+ data__->STATE = PYTHON_FB_ANSWERED;
+ /* Get a new line */
+ Current_Python_EvalFB = (Current_Python_EvalFB + 1) %% %(python_eval_fb_count)d;
+ }
+ /* while next slot is empty */
+ while(((data__ = EvalFBs[Current_Python_EvalFB]) == NULL) ||
+ /* or doesn't contain command */
+ data__->STATE != PYTHON_FB_REQUESTED)
+ {
+ UnLockPython();
+ /* wait next FB to eval */
+ WaitPythonCommands();
+ LockPython();
+ }
+ /* Mark block as processing */
+ data__->STATE = PYTHON_FB_PROCESSING;
+ //printf("PythonIterator\n");
+ /* make BUFFER a null terminated string */
+ data__->BUFFER.body[data__->BUFFER.len] = 0;
+ /* next command is BUFFER */
+ next_command = data__->BUFFER.body;
+ /* free python mutex */
+ UnLockPython();
+ /* return the next command to eval */
+ return next_command;
+}
+
diff -r 47d29c4b55a3 -r f2ef79f3dba0 tests/python/beremiz.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/python/beremiz.xml Tue Dec 23 19:37:44 2008 +0100
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff -r 47d29c4b55a3 -r f2ef79f3dba0 tests/python/plc.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/python/plc.xml Tue Dec 23 19:37:44 2008 +0100
@@ -0,0 +1,189 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ pytest_var3
+
+
+
+
+
+
+ pytest_var1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ pytest_var4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ pytest_var2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+