+
+void process_jim_events(void)
+{
+#if !BUILD_ECOSBOARD
+ static int recursion = 0;
+
+ if (!recursion)
+ {
+ recursion++;
+ Jim_ProcessEvents (interp, JIM_ALL_EVENTS|JIM_DONT_WAIT);
+ recursion--;
+ }
+#endif
+}
+
+void register_jim(struct command_context_s *cmd_ctx, const char *name, int (*cmd)(Jim_Interp *interp, int argc, Jim_Obj *const *argv), const char *help)
+{
+ Jim_CreateCommand(interp, name, cmd, NULL, NULL);
+
+ /* FIX!!! it would be prettier to invoke add_help_text...
+ * accumulate help text in Tcl helptext list. */
+ Jim_Obj *helptext=Jim_GetGlobalVariableStr(interp, "ocd_helptext", JIM_ERRMSG);
+ if (Jim_IsShared(helptext))
+ helptext = Jim_DuplicateObj(interp, helptext);
+
+ Jim_Obj *cmd_entry=Jim_NewListObj(interp, NULL, 0);
+
+ Jim_Obj *cmd_list=Jim_NewListObj(interp, NULL, 0);
+ Jim_ListAppendElement(interp, cmd_list, Jim_NewStringObj(interp, name, -1));
+
+ Jim_ListAppendElement(interp, cmd_entry, cmd_list);
+ Jim_ListAppendElement(interp, cmd_entry, Jim_NewStringObj(interp, help, -1));
+ Jim_ListAppendElement(interp, helptext, cmd_entry);
+}
+
+/* return global variable long value or 0 upon failure */
+long jim_global_long(const char *variable)
+{
+ Jim_Obj *objPtr=Jim_GetGlobalVariableStr(interp, variable, JIM_ERRMSG);
+ long t;
+ if (Jim_GetLong(interp, objPtr, &t)==JIM_OK)
+ {
+ return t;
+ }
+ return 0;
+}
+
+#define DEFINE_PARSE_NUM_TYPE(name, type, func, min, max) \
+ int parse##name(const char *str, type *ul) \
+ { \
+ if (!*str) \
+ return ERROR_COMMAND_ARGUMENT_INVALID; \
+ char *end; \
+ *ul = func(str, &end, 0); \
+ if (*end) \
+ return ERROR_COMMAND_ARGUMENT_INVALID; \
+ if ((max == *ul) && (ERANGE == errno)) \
+ return ERROR_COMMAND_ARGUMENT_OVERFLOW; \
+ if (min && (min == *ul) && (ERANGE == errno)) \
+ return ERROR_COMMAND_ARGUMENT_UNDERFLOW; \
+ return ERROR_OK; \
+ }
+DEFINE_PARSE_NUM_TYPE(_ulong, unsigned long , strtoul, 0, ULONG_MAX)
+DEFINE_PARSE_NUM_TYPE(_ullong, unsigned long long, strtoull, 0, ULLONG_MAX)
+DEFINE_PARSE_NUM_TYPE(_long, long , strtol, LONG_MIN, LONG_MAX)
+DEFINE_PARSE_NUM_TYPE(_llong, long long, strtoll, LLONG_MIN, LLONG_MAX)
+
+#define DEFINE_PARSE_WRAPPER(name, type, min, max, functype, funcname) \
+ int parse##name(const char *str, type *ul) \
+ { \
+ functype n; \
+ int retval = parse##funcname(str, &n); \
+ if (ERROR_OK != retval) \
+ return retval; \
+ if (n > max) \
+ return ERROR_COMMAND_ARGUMENT_OVERFLOW; \
+ if (min) \
+ return ERROR_COMMAND_ARGUMENT_UNDERFLOW; \
+ *ul = n; \
+ return ERROR_OK; \
+ }
+
+#define DEFINE_PARSE_ULONG(name, type, min, max) \
+ DEFINE_PARSE_WRAPPER(name, type, min, max, unsigned long, _ulong)
+DEFINE_PARSE_ULONG(_uint, unsigned, 0, UINT_MAX)
+DEFINE_PARSE_ULONG(_u32, uint32_t, 0, UINT32_MAX)
+DEFINE_PARSE_ULONG(_u16, uint16_t, 0, UINT16_MAX)
+DEFINE_PARSE_ULONG(_u8, uint8_t, 0, UINT8_MAX)
+
+#define DEFINE_PARSE_LONG(name, type, min, max) \
+ DEFINE_PARSE_WRAPPER(name, type, min, max, long, _long)
+DEFINE_PARSE_LONG(_int, int, n < INT_MIN, INT_MAX)
+DEFINE_PARSE_LONG(_s32, int32_t, n < INT32_MIN, INT32_MAX)
+DEFINE_PARSE_LONG(_s16, int16_t, n < INT16_MIN, INT16_MAX)
+DEFINE_PARSE_LONG(_s8, int8_t, n < INT8_MIN, INT8_MAX)