src/helper/configuration.h
- Log output handlers now get a "const char *line"
- Added "const" to parameter.
src/helper/command.c
src/helper/command.h
- New function: 'command_output_text()'
- Log output handlers now get a "const char *line"
src/helper/options.c
- Log output handlers now get a "const char *line"
src/server/telnet_server.c
- DO not transmit NULL bytes via TELNET.
- Log output handlers now get a "const char *line"
src/server/gdb_server.c
- Log output handlers now get a "const char *line"
*** THIS INCLUDES PORTIONS OF A PATCH FROM Oyvind sent
previously to the mailing list for TCL users try
src/target/target.c
*** THIS INCLUDES PORTIONS OF A PATCH FROM Oyvind sent
previously to the mailing list for TCL users try
src/target/target.h
*** THIS INCLUDES PORTIONS OF A PATCH FROM Oyvind sent
previously to the mailing list for TCL users try
src/openocd.c
- **MAJOR** Work: New TCL/Jim function: mem2array
- **MAJOR** Work: Redirect Tcl/Jim stdio output to remote users.
- Previously: TCL output did not go to GDB.
- Previously: TCL output did not go to TELNET
- Previously: TCL output only goes to control console.
- This fixes that problem.
+ Created callbacks:
+openocd_jim_fwrite()
+openocd_jim_fread()
+openocd_jim_vfprintf()
+openocd_jim_fflush()
+openocd_jim_fgets()
src/Makefile.am
- New TCL files.
- Future note: This should be more automated. As the list of
'tcl' files grows maintaning this list will suck.
src/Jim.c
- ** THIS INCLUDES A PREVIOUS PATCH I SENT EARLIER **
- that impliments many [format] specifies JIM did not support.
- Jim_FormatString() - **MAJOR** work.
- Previously only supported "%s" "%d" and "%c"
- And what support existed had bugs.
- NEW: *MANY* formating parameters are now supported.
- TODO: The "precision" specifier is not supported.
** NEW ** This patch.
- Jim_StringToWide() test if no conversion occured.
- Jim_StringToIndex() test if no conversion occured.
- Jim_StringToDouble() test if no conversion occured.
** NEW ** This Patch. Major Work.
- Previously output from JIM did not get sent to GDB
- Ditto: Output to Telnet session.
- Above items are now fixed - By introducing callbacks
new function pointers in the "interp" structure.
- Helpers that call the callbacks.
- New function: Jim_fprintf()
- New function: Jim_vfprintf()
- New function: Jim_fwrite()
- New function: Jim_fread()
- New function: Jim_fflush()
- New function: Jim_fgets()
By default: the output is to STDIO as previous.
The "openocd.c" - redirects the output as needed.
- Jim_Panic() - Send panic to both STDERR and the interps
specified STDERR output as a 2nd choice.
- Now JIM's "stdin/stdout/stderr" paramters are "void *"
and are no longer "FILE *".
src/Jim.h
- **MAJOR**
- New JIM STDIO callbacks in the "interp" structure.
- change: "stdin/stdout/stderr" are now "void *" cookies.
- New JIM stdio helper functions.
git-svn-id: svn://svn.berlios.de/openocd/trunk@755 b42882b7-edfa-0310-969c-e2dbd0fdcd60
This commit is contained in:
295
src/openocd.c
295
src/openocd.c
@@ -165,6 +165,191 @@ void unlockBigLock()
|
||||
Jim_Interp *interp;
|
||||
command_context_t *active_cmd_ctx;
|
||||
|
||||
static int
|
||||
new_int_array_element( Jim_Interp * interp,
|
||||
const char *varname,
|
||||
int idx,
|
||||
u32 val )
|
||||
{
|
||||
char *namebuf;
|
||||
Jim_Obj *nameObjPtr, *valObjPtr;
|
||||
int result;
|
||||
|
||||
namebuf = alloca( strlen(varname) + 30 );
|
||||
sprintf( namebuf, "%s(%d)", varname, idx );
|
||||
|
||||
|
||||
nameObjPtr = Jim_NewStringObj(interp, namebuf, -1);
|
||||
valObjPtr = Jim_NewIntObj(interp, val );
|
||||
Jim_IncrRefCount(nameObjPtr);
|
||||
Jim_IncrRefCount(valObjPtr);
|
||||
result = Jim_SetVariable(interp, nameObjPtr, valObjPtr);
|
||||
Jim_DecrRefCount(interp, nameObjPtr);
|
||||
Jim_DecrRefCount(interp, valObjPtr);
|
||||
// printf( "%s = 0%08x\n", namebuf, val );
|
||||
return result;
|
||||
}
|
||||
|
||||
static int
|
||||
Jim_Command_mem2array( Jim_Interp *interp, int argc, Jim_Obj *const *argv)
|
||||
{
|
||||
target_t *target;
|
||||
long l;
|
||||
u32 width;
|
||||
u32 endian;
|
||||
u32 len;
|
||||
u32 addr;
|
||||
u32 count;
|
||||
u32 v;
|
||||
const char *varname;
|
||||
u8 buffer[4096];
|
||||
int i,n,e,retval;
|
||||
|
||||
|
||||
/* argv[1] = name of array to receive the data
|
||||
* argv[2] = desired width
|
||||
* argv[3] = memory address
|
||||
* argv[4] = length in bytes to read
|
||||
*/
|
||||
if( argc != 5 ){
|
||||
Jim_WrongNumArgs( interp, 1, argv, "varname width addr nelems" );
|
||||
return JIM_ERR;
|
||||
}
|
||||
varname = Jim_GetString( argv[1], &len );
|
||||
/* given "foo" get space for worse case "foo(%d)" .. add 20 */
|
||||
|
||||
|
||||
e = Jim_GetLong( interp, argv[2], &l );
|
||||
width = l;
|
||||
if( e != JIM_OK ){
|
||||
return e;
|
||||
}
|
||||
|
||||
e = Jim_GetLong( interp, argv[3], &l );
|
||||
addr = l;
|
||||
if( e != JIM_OK ){
|
||||
return e;
|
||||
}
|
||||
e = Jim_GetLong( interp, argv[4], &l );
|
||||
len = l;
|
||||
if( e != JIM_OK ){
|
||||
return e;
|
||||
}
|
||||
switch(width){
|
||||
case 8:
|
||||
width = 1;
|
||||
break;
|
||||
case 16:
|
||||
width = 2;
|
||||
break;
|
||||
case 32:
|
||||
width = 4;
|
||||
break;
|
||||
default:
|
||||
Jim_SetResult(interp,
|
||||
Jim_NewEmptyStringObj(interp));
|
||||
Jim_AppendStrings( interp, Jim_GetResult(interp),
|
||||
"Invalid width param, must be 8/16/32", NULL );
|
||||
return JIM_ERR;
|
||||
}
|
||||
if( len == 0 ){
|
||||
Jim_SetResult(interp,
|
||||
Jim_NewEmptyStringObj(interp));
|
||||
Jim_AppendStrings( interp, Jim_GetResult(interp),
|
||||
"mem2array: zero width read?", NULL );
|
||||
return JIM_ERR;
|
||||
}
|
||||
if( (addr + (len * width)) < addr ){
|
||||
Jim_SetResult(interp,
|
||||
Jim_NewEmptyStringObj(interp));
|
||||
Jim_AppendStrings( interp, Jim_GetResult(interp),
|
||||
"mem2array: addr + len - wraps to zero?", NULL );
|
||||
return JIM_ERR;
|
||||
}
|
||||
/* absurd transfer size? */
|
||||
if( len > 65536 ){
|
||||
Jim_SetResult(interp,
|
||||
Jim_NewEmptyStringObj(interp));
|
||||
Jim_AppendStrings( interp, Jim_GetResult(interp),
|
||||
"mem2array: absurd > 64K item request", NULL );
|
||||
return JIM_ERR;
|
||||
}
|
||||
|
||||
if( (width == 1) ||
|
||||
((width == 2) && ((addr & 1) == 0)) ||
|
||||
((width == 4) && ((addr & 3) == 0)) ){
|
||||
/* all is well */
|
||||
} else {
|
||||
char buf[100];
|
||||
Jim_SetResult(interp,
|
||||
Jim_NewEmptyStringObj(interp));
|
||||
sprintf( buf,
|
||||
"mem2array address: 0x%08x is not aligned for %d byte reads",
|
||||
addr, width );
|
||||
|
||||
Jim_AppendStrings( interp, Jim_GetResult(interp),
|
||||
buf , NULL );
|
||||
return JIM_ERR;
|
||||
}
|
||||
|
||||
target = get_current_target( active_cmd_ctx );
|
||||
|
||||
/* Transfer loop */
|
||||
|
||||
/* index counter */
|
||||
n = 0;
|
||||
/* assume ok */
|
||||
e = JIM_OK;
|
||||
while( len ){
|
||||
|
||||
/* Slurp... in buffer size chunks */
|
||||
|
||||
count = len; /* in objects.. */
|
||||
if( count > (sizeof(buffer)/width)){
|
||||
count = (sizeof(buffer)/width);
|
||||
}
|
||||
|
||||
retval = target->type->read_memory( target,
|
||||
addr,
|
||||
width,
|
||||
count,
|
||||
buffer );
|
||||
|
||||
if( retval != ERROR_OK ){
|
||||
/* BOO !*/
|
||||
LOG_ERROR("mem2array: Read @ 0x%08x, w=%d, cnt=%d, failed",
|
||||
addr, width, count );
|
||||
Jim_SetResult(interp,
|
||||
Jim_NewEmptyStringObj(interp));
|
||||
Jim_AppendStrings( interp, Jim_GetResult(interp),
|
||||
"mem2array: cannot read memory", NULL );
|
||||
e = JIM_ERR;
|
||||
len = 0;
|
||||
} else {
|
||||
v = 0; /* shut up gcc */
|
||||
for( i = 0 ; i < count ; i++, n++ ){
|
||||
switch(width){
|
||||
case 4:
|
||||
v = target_buffer_get_u32( target, &buffer[i*width] );
|
||||
break;
|
||||
case 2:
|
||||
v = target_buffer_get_u16( target, &buffer[i*width] );
|
||||
break;
|
||||
case 1:
|
||||
v = buffer[i] & 0x0ff;
|
||||
break;
|
||||
}
|
||||
new_int_array_element( interp, varname, n, v );
|
||||
}
|
||||
len -= count;
|
||||
}
|
||||
}
|
||||
Jim_SetResult(interp,
|
||||
Jim_NewEmptyStringObj(interp));
|
||||
|
||||
return JIM_OK;
|
||||
}
|
||||
|
||||
static void tcl_output(void *privData, const char *file, int line,
|
||||
const char *function, const char *string)
|
||||
{
|
||||
@@ -323,6 +508,97 @@ Jim_Command_echo(Jim_Interp *interp,
|
||||
return JIM_OK;
|
||||
}
|
||||
|
||||
static size_t
|
||||
openocd_jim_fwrite( const void *_ptr, size_t size, size_t n, void *cookie )
|
||||
{
|
||||
size_t nbytes;
|
||||
const char *ptr;
|
||||
|
||||
/* make it a char easier to read code */
|
||||
ptr = _ptr;
|
||||
|
||||
nbytes = size * n;
|
||||
if( nbytes == 0 ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( !active_cmd_ctx ){
|
||||
/* FIXME: Where should this go? */
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
/* do we have to chunk it? */
|
||||
if( ptr[ nbytes ] == 0 ){
|
||||
/* no it is a C style string */
|
||||
command_output_text( active_cmd_ctx, ptr );
|
||||
return;
|
||||
}
|
||||
/* GRR we must chunk - not null terminated */
|
||||
while( nbytes ){
|
||||
char chunk[128+1];
|
||||
int x;
|
||||
|
||||
x = nbytes;
|
||||
if( x > 128 ){
|
||||
x = 128;
|
||||
}
|
||||
/* copy it */
|
||||
memcpy( chunk, ptr, x );
|
||||
/* terminate it */
|
||||
chunk[n] = 0;
|
||||
/* output it */
|
||||
command_output_text( active_cmd_ctx, chunk );
|
||||
ptr += x;
|
||||
nbytes -= x;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static size_t
|
||||
openocd_jim_fread(void *ptr, size_t size, size_t n, void *cookie )
|
||||
{
|
||||
/* TCL wants to read... tell him no */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
openocd_jim_vfprintf( void *cookie, const char *fmt, va_list ap )
|
||||
{
|
||||
char *cp;
|
||||
int n;
|
||||
|
||||
n = -1;
|
||||
if( active_cmd_ctx ){
|
||||
cp = alloc_vprintf( fmt, ap );
|
||||
if( cp ){
|
||||
command_output_text( active_cmd_ctx, cp );
|
||||
n = strlen(cp);
|
||||
free(cp);
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
static int
|
||||
openocd_jim_fflush( void *cookie )
|
||||
{
|
||||
/* nothing to flush */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *
|
||||
openocd_jim_fgets( char *s, int size, void *cookie )
|
||||
{
|
||||
/* not supported */
|
||||
errno = ENOTSUP;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void initJim(void)
|
||||
{
|
||||
Jim_InitEmbedded();
|
||||
@@ -335,6 +611,17 @@ void initJim(void)
|
||||
Jim_CreateCommand(interp, "openocd_throw", Jim_Command_openocd_throw, NULL, NULL);
|
||||
Jim_CreateCommand(interp, "find", Jim_Command_find, NULL, NULL);
|
||||
Jim_CreateCommand(interp, "echo", Jim_Command_echo, NULL, NULL);
|
||||
Jim_CreateCommand(interp, "mem2array", Jim_Command_mem2array, NULL, NULL );
|
||||
|
||||
/* Set Jim's STDIO */
|
||||
interp->cookie_stdin = NULL;
|
||||
interp->cookie_stdout = NULL;
|
||||
interp->cookie_stderr = NULL;
|
||||
interp->cb_fwrite = openocd_jim_fwrite;
|
||||
interp->cb_fread = openocd_jim_fread ;
|
||||
interp->cb_vfprintf = openocd_jim_vfprintf;
|
||||
interp->cb_fflush = openocd_jim_fflush;
|
||||
interp->cb_fgets = openocd_jim_fgets;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
@@ -422,3 +709,11 @@ int main(int argc, char *argv[])
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Local Variables: **
|
||||
* tab-width: 4 **
|
||||
* c-basic-offset: 4 **
|
||||
* End: **
|
||||
*/
|
||||
|
||||
|
||||
Reference in New Issue
Block a user