I think it is important to focus on aspects other than choice of
language. The current patch is w/Tcl, but it could be another language.

Trying to break down the "why" a bit:

Q: Who, realistically, will use it?

Q: What can it be used for?

Q: How should it be integrated?


My thinking so far...

Who: OpenOCD developers. Here I include those that contribute
target library scripts. I don't see "normal" OpenOCD developers
messing around with this. Ideally they should just specify the
target via the target library and then live happily ever after without
worrying about OpenOCD again :-) If end users never mess
around with the scripting language

What: a language w/resource tracking & exception handling +
convenience can lead to less bugs and easier to hack code.

How: currently the scripting support is something internal to
OpenOCD. OpenOCD is not controlled, but rather OpenOCD
executes the scripts. This allows fast roundtrips when talking
to the hw, if roundtrips are required to talk to the PC, then
things are not so convenient.

I've been trying to find some killer app for a scripting language
hosted by OpenOCD:

- write a flash driver in tcl. A flash driver consists of "a few peeks
and pokes". Could a tcl script handle this for non-standard parts?
The eCos + ocl flash drivers have had zero visible success. This
would have to be for OpenOCD developers and not OpenOCD
users I think.
- write variant target support in tcl. The slight arm7/9 variants
could perhaps be written in tcl?

BTW, I've committed some hooks & code to reduce the patch size
for scripting support experiments.

Script support patches will now be *MUCH* smaller and easier
to understand. No change in behaviour, but if I screwed something
up be sure to let me know.

-- 
Øyvind Harboe
http://www.zylin.com/zy1000.html
ARM7 ARM9 XScale Cortex
JTAG debugger and flash programmer
Index: C:/workspace/trunk/src/Makefile.am
===================================================================
--- C:/workspace/trunk/src/Makefile.am  (revision 733)
+++ C:/workspace/trunk/src/Makefile.am  (working copy)
@@ -7,7 +7,7 @@
 endif
 
 
-openocd_SOURCES = $(MAINFILE)
+openocd_SOURCES = $(MAINFILE) jim.c
 
 # set the include path found by configure
 INCLUDES = -I$(top_srcdir)/src/helper \
@@ -78,3 +78,7 @@
        $(top_builddir)/src/flash/libflash.a 
$(top_builddir)/src/target/libtarget.a \
        $(top_builddir)/src/pld/libpld.a \
        $(FTDI2232LIB) $(FTD2XXLIB) $(MINGWLDADD) $(LIBUSB)
+
+       
+       
+nobase_dist_pkglib_DATA = tcl/commands.tcl
Index: C:/workspace/trunk/src/openocd.c
===================================================================
--- C:/workspace/trunk/src/openocd.c    (revision 733)
+++ C:/workspace/trunk/src/openocd.c    (working copy)
@@ -49,6 +49,10 @@
 #include <unistd.h>
 #include <errno.h>
 
+#define JIM_EMBEDDED
+#include "jim.h"
+
+
 /* Give TELNET a way to find out what version this is */
 int handle_version_command(struct command_context_s *cmd_ctx, char *cmd, char 
**args, int argc)
 {
@@ -154,11 +158,169 @@
 {
 }
 
-/* Hook to add scripting language */
+
+
+
+
+Jim_Interp *interp;
+command_context_t *active_cmd_ctx;
+
+static void tcl_output(void *privData, const char *file, int line, 
+               const char *function, const char *string)
+{              
+       Jim_Obj *tclOutput=(Jim_Obj *)privData;
+
+       Jim_AppendString(interp, tclOutput, string, strlen(string));
+}
+
+/* try to execute as Jim command, otherwise fall back to standard command.
+
+       Note that even if the Jim command caused an error, then we succeeded
+       to execute it, hence this fn pretty much always returns ERROR_OK. 
+
+ */
 int jim_command(command_context_t *context, char *line)
 {
-       LOG_ERROR("Syntax error");
-       return ERROR_COMMAND_SYNTAX_ERROR;
+       int retval=ERROR_OK;
+       active_cmd_ctx=context;
+       int retcode=Jim_Eval(interp, line);
+       active_cmd_ctx=NULL;
+       
+       const char *result;
+       int reslen;
+    result = Jim_GetString(Jim_GetResult(interp), &reslen);
+    if (retcode == JIM_ERR) {
+           int len, i;
+       
+           LOG_USER_N("Runtime error, file \"%s\", line %d:" JIM_NL,
+                   interp->errorFileName, interp->errorLine);
+           LOG_USER_N("    %s" JIM_NL,
+                   Jim_GetString(interp->result, NULL));
+           Jim_ListLength(interp, interp->stackTrace, &len);
+           for (i = 0; i < len; i+= 3) {
+               Jim_Obj *objPtr;
+               const char *proc, *file, *line;
+       
+               Jim_ListIndex(interp, interp->stackTrace, i, &objPtr, JIM_NONE);
+               proc = Jim_GetString(objPtr, NULL);
+               Jim_ListIndex(interp, interp->stackTrace, i+1, &objPtr,
+                       JIM_NONE);
+               file = Jim_GetString(objPtr, NULL);
+               Jim_ListIndex(interp, interp->stackTrace, i+2, &objPtr,
+                       JIM_NONE);
+               line = Jim_GetString(objPtr, NULL);
+               LOG_USER_N("In procedure '%s' called at file \"%s\", line %s" 
JIM_NL,
+                       proc, file, line);
+           }
+    } else if (retcode == JIM_EXIT) {
+       // ignore.
+        //exit(Jim_GetExitCode(interp));
+    } else {
+        if (reslen) {
+               int i;
+               char buff[256+1];
+               for (i=0; i<reslen; i+=256)
+               {
+                       int chunk;
+                       chunk=reslen-i;
+                       if (chunk>256)
+                               chunk=256;
+                       strncpy(buff, result, chunk);
+                       buff[chunk]=0; 
+               LOG_USER_N("%s", buff);
+               }
+               LOG_USER_N("%s", "\n");
+        }
+    }
+       return retval;
+}
+
+static int startLoop=0;
+
+static int
+Jim_Command_openocd_ignore(Jim_Interp *interp, 
+                                   int argc,
+                                   Jim_Obj *const *argv,
+                                   int ignore)
+{
+       int retval;
+    char *cmd = (char*)Jim_GetString(argv[1], NULL);
+
+       lockBigLock();
+       
+    Jim_Obj *tclOutput = Jim_NewStringObj(interp, "", 0);
+    
+    if (startLoop)
+    {
+       // We don't know whether or not the telnet/gdb server is running...
+       target_call_timer_callbacks_now();
+    }
+       
+       log_add_callback(tcl_output, tclOutput);
+    retval=command_run_line_internal(active_cmd_ctx, cmd);
+    
+    if (startLoop)
+    {
+       target_call_timer_callbacks_now();
+    }
+       log_remove_callback(tcl_output, tclOutput);
+    
+       Jim_SetResult(interp, tclOutput);
+    unlockBigLock();
+        
+    return (ignore||(retval==ERROR_OK))?JIM_OK:JIM_ERR;
+}
+
+static int
+Jim_Command_openocd(Jim_Interp *interp, 
+                                   int argc,
+                                   Jim_Obj *const *argv)
+{
+       return Jim_Command_openocd_ignore(interp, argc, argv, 1); 
+}
+
+static int
+Jim_Command_openocd_throw(Jim_Interp *interp, 
+                                   int argc,
+                                   Jim_Obj *const *argv)
+{
+       return Jim_Command_openocd_ignore(interp, argc, argv, 0); 
+}
+  
+
+
+
+/* find full path to file */
+static int
+Jim_Command_find(Jim_Interp *interp, 
+                                   int argc,
+                                   Jim_Obj *const *argv)
+{
+       if (argc!=2)
+               return JIM_ERR;
+       char *file = (char*)Jim_GetString(argv[1], NULL);
+       char *full_path=find_file(file);
+       if (full_path==NULL)
+               return JIM_ERR;
+    Jim_Obj *result = Jim_NewStringObj(interp, full_path, strlen(full_path));
+    free(full_path);
+    
+       Jim_SetResult(interp, result);
+       return JIM_OK;
+}
+
+
+void initJim(void)
+{
+    Jim_InitEmbedded();
+  
+    /* Create an interpreter */
+    interp = Jim_CreateInterp();
+    /* Add all the Jim core commands */
+    Jim_RegisterCoreCommands(interp);
+    Jim_CreateCommand(interp, "openocd", Jim_Command_openocd, NULL, NULL);
+    Jim_CreateCommand(interp, "openocd_throw", Jim_Command_openocd_throw, 
NULL, NULL);
+    Jim_CreateCommand(interp, "find", Jim_Command_find, NULL, NULL);
 }
 
 int main(int argc, char *argv[])
@@ -163,6 +325,8 @@
 
 int main(int argc, char *argv[])
 {
+       initJim();
+       
        /* initialize commandline interface */
        command_context_t *cmd_ctx, *cfg_cmd_ctx;
        cmd_ctx = command_init();
@@ -188,7 +352,7 @@
        if (log_init(cmd_ctx) != ERROR_OK)
                return EXIT_FAILURE;
        LOG_DEBUG("log init complete");
-       
+
        LOG_OUTPUT( OPENOCD_VERSION "\n" );
        
        
@@ -214,6 +378,8 @@
        if (parse_cmdline_args(cfg_cmd_ctx, argc, argv) != ERROR_OK)
                return EXIT_FAILURE;
 
+    Jim_Eval(interp, "source [find tcl/commands.tcl]");
+
        if (parse_config_file(cfg_cmd_ctx) != ERROR_OK)
                return EXIT_FAILURE;
        
@@ -225,6 +391,9 @@
        if (daemon_startup)
                command_run_line(cmd_ctx, "reset");
 
+
+       startLoop=1;
+
        /* handle network connections */
        server_loop(cmd_ctx);
 
Index: C:/workspace/trunk/src/tcl/commands.tcl
===================================================================
--- C:/workspace/trunk/src/tcl/commands.tcl     (revision 0)
+++ C:/workspace/trunk/src/tcl/commands.tcl     (revision 0)
@@ -0,0 +1,4 @@
+# implements Tcl procedures/functions
+proc peek {address} {
+       return [openocd mdw $address]
+}
\ No newline at end of file
_______________________________________________
Openocd-development mailing list
[email protected]
https://lists.berlios.de/mailman/listinfo/openocd-development

Reply via email to