git-svn-id: svn://svn.berlios.de/openocd/trunk@2384 b42882b7-edfa-0310-969c-e2dbd0fdcd60tags/v0.2.0
@@ -1,23 +1,23 @@ | |||
/*************************************************************************** | |||
* Copyright (C) 2009 by Duane Ellis * | |||
* openocd@duaneellis.com * | |||
* * | |||
* 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. * | |||
***************************************************************************/ | |||
// nothing to do here other then export this. | |||
extern flash_driver_t at91sam3_flash; | |||
/*************************************************************************** | |||
* Copyright (C) 2009 by Duane Ellis * | |||
* openocd@duaneellis.com * | |||
* * | |||
* 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. * | |||
***************************************************************************/ | |||
// nothing to do here other then export this. | |||
extern flash_driver_t at91sam3_flash; |
@@ -1,238 +1,238 @@ | |||
/*************************************************************************** | |||
* Copyright (C) 2009 By Duane Ellis * | |||
* openocd@duaneellis.com * | |||
* * | |||
* 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. * | |||
***************************************************************************/ | |||
#include <stdio.h> | |||
#include <stdarg.h> | |||
#include <malloc.h> | |||
#include <string.h> | |||
#include "membuf.h" | |||
struct membuf { | |||
// buflen is alway "+1" bigger then | |||
// what is shown here, the +1 is for | |||
// the NULL string terminator | |||
#define DEFAULT_BUFSIZE 100 | |||
size_t maxlen; // allocated size | |||
size_t curlen; // where we are inserting at | |||
char *_strtoklast; | |||
void *buf; | |||
}; | |||
#define space_avail( pBuf ) (pBuf->maxlen - pBuf->curlen) | |||
#define dataend( pBuf ) ( ((char *)(pBuf->buf)) + pBuf->curlen ) | |||
size_t | |||
membuf_len( struct membuf *pBuf ) | |||
{ | |||
return pBuf->curlen; | |||
} | |||
const void * | |||
membuf_datapointer( struct membuf *pBuf ) | |||
{ | |||
return ((void *)(pBuf->buf)); | |||
} | |||
const char * | |||
membuf_strtok( struct membuf *pBuf, const char *sep, void **pLast ) | |||
{ | |||
if( pBuf ){ | |||
pBuf->_strtoklast = NULL; | |||
*pLast = pBuf; | |||
return strtok_r( ((char *)(pBuf->buf)), sep, &(pBuf->_strtoklast) ); | |||
} else { | |||
// recover our pBuf | |||
pBuf = *((struct membuf **)(pLast)); | |||
return strtok_r( NULL, sep, &(pBuf->_strtoklast) ); | |||
} | |||
} | |||
struct membuf * | |||
membuf_new(void) | |||
{ | |||
// by default - parameters are zero. | |||
struct membuf *pBuf; | |||
pBuf = calloc( 1, sizeof(*pBuf) ); | |||
if( pBuf ){ | |||
// we *ALWAYS* allocate +1 for null terminator. | |||
pBuf->buf = calloc( DEFAULT_BUFSIZE+1, sizeof(char)); | |||
if( pBuf->buf == NULL ){ | |||
free(pBuf); | |||
pBuf = NULL; | |||
} else { | |||
pBuf->maxlen = DEFAULT_BUFSIZE; | |||
} | |||
} | |||
return pBuf; | |||
} | |||
struct membuf * | |||
membuf_grow( struct membuf *pBuf, int n ) | |||
{ | |||
void *vp; | |||
signed int newsize; | |||
// this is a *SIGNED* value | |||
newsize = ((int)(pBuf->maxlen)) + n; | |||
// do not go negative, or too small | |||
if( newsize < DEFAULT_BUFSIZE ){ | |||
newsize = DEFAULT_BUFSIZE; | |||
} | |||
// always alloc +1 for the null terminator | |||
vp = realloc( pBuf->buf, newsize+1 ); | |||
if( vp ){ | |||
pBuf->buf = vp; | |||
pBuf->maxlen = newsize; | |||
return pBuf; | |||
} else { | |||
return NULL; | |||
} | |||
} | |||
void membuf_reset( struct membuf *pBuf ) | |||
{ | |||
pBuf->curlen = 0; | |||
} | |||
void membuf_delete( struct membuf *pBuf ) | |||
{ | |||
if( pBuf ){ | |||
if( pBuf->buf){ | |||
// wack data so it cannot be reused | |||
memset(pBuf->buf,0,pBuf->maxlen); | |||
free(pBuf->buf); | |||
} | |||
// wack dat so it cannot be reused | |||
memset(pBuf,0,sizeof(pBuf)); | |||
free(pBuf); | |||
} | |||
} | |||
int | |||
membuf_sprintf( struct membuf *pBuf , const char *fmt, ... ) | |||
{ | |||
int r; | |||
va_list ap; | |||
va_start( ap, fmt ); | |||
r = membuf_vsprintf( pBuf, fmt, ap ); | |||
va_end(ap); | |||
return r; | |||
} | |||
int | |||
membuf_vsprintf( struct membuf *pBuf, const char *fmt, va_list ap ) | |||
{ | |||
int r; | |||
size_t sa; | |||
int grew; | |||
grew = 0; | |||
for(;;) { | |||
sa = space_avail(pBuf); | |||
// do work | |||
r = vsnprintf( dataend( pBuf ), | |||
sa, | |||
fmt, | |||
ap ); | |||
if( (r > 0) && (((size_t)(r)) < sa) ){ | |||
// Success! | |||
pBuf->curlen += ((size_t)(r)); | |||
// remember: We always alloc'ed +1 | |||
// so this does not overflow | |||
((char *)(pBuf->buf))[ pBuf->curlen ] = 0; | |||
r = 0; | |||
break; | |||
} | |||
// failure | |||
if( r < 0 ){ | |||
// Option(A) format error | |||
// Option(B) glibc2.0 bug | |||
// assume (B). | |||
r = (4 * DEFAULT_BUFSIZE); | |||
} | |||
// don't do this again | |||
if( grew ){ | |||
r = -1; | |||
break; | |||
} | |||
grew = 1; | |||
pBuf = membuf_grow( pBuf, r ); | |||
if(pBuf == NULL){ | |||
// grow failed | |||
r = -1; | |||
break; | |||
} | |||
} | |||
return r; | |||
} | |||
struct membuf * | |||
membuf_strcat( struct membuf *pBuf, const char *pStr ) | |||
{ | |||
return membuf_append( pBuf, pStr, strlen( pStr ) ); | |||
} | |||
struct membuf * | |||
membuf_append( struct membuf *pBuf, const void *pData, size_t len ) | |||
{ | |||
size_t sa; | |||
int r; | |||
// how much room is there? | |||
sa = space_avail( pBuf ); | |||
// will it fit? | |||
if( sa < len ){ | |||
// if not, how much do we need? | |||
r = ((int)(sa - len)); | |||
// do the grow. | |||
pBuf = membuf_grow( pBuf, r ); | |||
// failed? | |||
if(pBuf==NULL){ | |||
return pBuf; | |||
} | |||
} | |||
// append | |||
memcpy( dataend(pBuf), | |||
pData, | |||
len ); | |||
pBuf->curlen += len; | |||
return pBuf; | |||
} | |||
/*************************************************************************** | |||
* Copyright (C) 2009 By Duane Ellis * | |||
* openocd@duaneellis.com * | |||
* * | |||
* 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. * | |||
***************************************************************************/ | |||
#include <stdio.h> | |||
#include <stdarg.h> | |||
#include <malloc.h> | |||
#include <string.h> | |||
#include "membuf.h" | |||
struct membuf { | |||
// buflen is alway "+1" bigger then | |||
// what is shown here, the +1 is for | |||
// the NULL string terminator | |||
#define DEFAULT_BUFSIZE 100 | |||
size_t maxlen; // allocated size | |||
size_t curlen; // where we are inserting at | |||
char *_strtoklast; | |||
void *buf; | |||
}; | |||
#define space_avail( pBuf ) (pBuf->maxlen - pBuf->curlen) | |||
#define dataend( pBuf ) ( ((char *)(pBuf->buf)) + pBuf->curlen ) | |||
size_t | |||
membuf_len( struct membuf *pBuf ) | |||
{ | |||
return pBuf->curlen; | |||
} | |||
const void * | |||
membuf_datapointer( struct membuf *pBuf ) | |||
{ | |||
return ((void *)(pBuf->buf)); | |||
} | |||
const char * | |||
membuf_strtok( struct membuf *pBuf, const char *sep, void **pLast ) | |||
{ | |||
if( pBuf ){ | |||
pBuf->_strtoklast = NULL; | |||
*pLast = pBuf; | |||
return strtok_r( ((char *)(pBuf->buf)), sep, &(pBuf->_strtoklast) ); | |||
} else { | |||
// recover our pBuf | |||
pBuf = *((struct membuf **)(pLast)); | |||
return strtok_r( NULL, sep, &(pBuf->_strtoklast) ); | |||
} | |||
} | |||
struct membuf * | |||
membuf_new(void) | |||
{ | |||
// by default - parameters are zero. | |||
struct membuf *pBuf; | |||
pBuf = calloc( 1, sizeof(*pBuf) ); | |||
if( pBuf ){ | |||
// we *ALWAYS* allocate +1 for null terminator. | |||
pBuf->buf = calloc( DEFAULT_BUFSIZE+1, sizeof(char)); | |||
if( pBuf->buf == NULL ){ | |||
free(pBuf); | |||
pBuf = NULL; | |||
} else { | |||
pBuf->maxlen = DEFAULT_BUFSIZE; | |||
} | |||
} | |||
return pBuf; | |||
} | |||
struct membuf * | |||
membuf_grow( struct membuf *pBuf, int n ) | |||
{ | |||
void *vp; | |||
signed int newsize; | |||
// this is a *SIGNED* value | |||
newsize = ((int)(pBuf->maxlen)) + n; | |||
// do not go negative, or too small | |||
if( newsize < DEFAULT_BUFSIZE ){ | |||
newsize = DEFAULT_BUFSIZE; | |||
} | |||
// always alloc +1 for the null terminator | |||
vp = realloc( pBuf->buf, newsize+1 ); | |||
if( vp ){ | |||
pBuf->buf = vp; | |||
pBuf->maxlen = newsize; | |||
return pBuf; | |||
} else { | |||
return NULL; | |||
} | |||
} | |||
void membuf_reset( struct membuf *pBuf ) | |||
{ | |||
pBuf->curlen = 0; | |||
} | |||
void membuf_delete( struct membuf *pBuf ) | |||
{ | |||
if( pBuf ){ | |||
if( pBuf->buf){ | |||
// wack data so it cannot be reused | |||
memset(pBuf->buf,0,pBuf->maxlen); | |||
free(pBuf->buf); | |||
} | |||
// wack dat so it cannot be reused | |||
memset(pBuf,0,sizeof(pBuf)); | |||
free(pBuf); | |||
} | |||
} | |||
int | |||
membuf_sprintf( struct membuf *pBuf , const char *fmt, ... ) | |||
{ | |||
int r; | |||
va_list ap; | |||
va_start( ap, fmt ); | |||
r = membuf_vsprintf( pBuf, fmt, ap ); | |||
va_end(ap); | |||
return r; | |||
} | |||
int | |||
membuf_vsprintf( struct membuf *pBuf, const char *fmt, va_list ap ) | |||
{ | |||
int r; | |||
size_t sa; | |||
int grew; | |||
grew = 0; | |||
for(;;) { | |||
sa = space_avail(pBuf); | |||
// do work | |||
r = vsnprintf( dataend( pBuf ), | |||
sa, | |||
fmt, | |||
ap ); | |||
if( (r > 0) && (((size_t)(r)) < sa) ){ | |||
// Success! | |||
pBuf->curlen += ((size_t)(r)); | |||
// remember: We always alloc'ed +1 | |||
// so this does not overflow | |||
((char *)(pBuf->buf))[ pBuf->curlen ] = 0; | |||
r = 0; | |||
break; | |||
} | |||
// failure | |||
if( r < 0 ){ | |||
// Option(A) format error | |||
// Option(B) glibc2.0 bug | |||
// assume (B). | |||
r = (4 * DEFAULT_BUFSIZE); | |||
} | |||
// don't do this again | |||
if( grew ){ | |||
r = -1; | |||
break; | |||
} | |||
grew = 1; | |||
pBuf = membuf_grow( pBuf, r ); | |||
if(pBuf == NULL){ | |||
// grow failed | |||
r = -1; | |||
break; | |||
} | |||
} | |||
return r; | |||
} | |||
struct membuf * | |||
membuf_strcat( struct membuf *pBuf, const char *pStr ) | |||
{ | |||
return membuf_append( pBuf, pStr, strlen( pStr ) ); | |||
} | |||
struct membuf * | |||
membuf_append( struct membuf *pBuf, const void *pData, size_t len ) | |||
{ | |||
size_t sa; | |||
int r; | |||
// how much room is there? | |||
sa = space_avail( pBuf ); | |||
// will it fit? | |||
if( sa < len ){ | |||
// if not, how much do we need? | |||
r = ((int)(sa - len)); | |||
// do the grow. | |||
pBuf = membuf_grow( pBuf, r ); | |||
// failed? | |||
if(pBuf==NULL){ | |||
return pBuf; | |||
} | |||
} | |||
// append | |||
memcpy( dataend(pBuf), | |||
pData, | |||
len ); | |||
pBuf->curlen += len; | |||
return pBuf; | |||
} | |||
@@ -1,118 +1,118 @@ | |||
#ifndef HELPER_MEMBUF_H | |||
#define HELPER_MEMBUF_H | |||
/** @file */ | |||
/** @page MEMBUF - an auto-growing string buffer | |||
* | |||
* With OpenOCD often, one must write code that sends text to | |||
* different places.. the historical command_ctx, or JIM output, | |||
* and/or other places. | |||
* | |||
* This is a simple 'string buffer' that auto-grows. | |||
* | |||
* More correctly put, this is a "memory buffer" | |||
* it may contain binary data | |||
* | |||
* Note: Internally the buffer always has a 'null terminator' | |||
*/ | |||
/* contents of this structure are 'opaque' */ | |||
struct membuf; | |||
/** Create a new membuf | |||
* By default the memory buffer has "some non-zero-size" | |||
* (couple hundred bytes, exact amount is opaque) | |||
*/ | |||
struct membuf *membuf_new(void); | |||
/** delete (destroy) the mem buffer | |||
* @param pBuf - buffer to release | |||
*/ | |||
void membuf_delete( struct membuf *pBuf ); | |||
/** grow/shrink a membuf by specified amount. | |||
* @param pBuf - the buffer | |||
* @param amount - the amount to grow or shrink by. | |||
* | |||
* Symantics of 'realloc()' return NULL on failure | |||
*/ | |||
struct membuf *membuf_grow( struct membuf *pBuf, int amount ); | |||
/** how long is this buffer (memlen(), strlen()) | |||
* @param pBuf - the buffer | |||
* | |||
* @returns: length of current buffer. | |||
*/ | |||
size_t membuf_len( struct membuf *pBuf ); | |||
/** reset an membuf to zero length. | |||
* @param pBuf - buffer to reset | |||
* | |||
* Note this does not 'release' the memory buffer | |||
*/ | |||
void membuf_reset( struct membuf *pBuf ); | |||
/** sprintf() to the string buffer | |||
* @param pBuf - buffer to capture sprintf() data into | |||
* @param fmt - printf format | |||
* | |||
* Returns 0 on success | |||
* Returns non-zero on failure | |||
*/ | |||
int membuf_sprintf( struct membuf *pBuf , const char *fmt, ... ); | |||
/** vsprintf() to the string buffer | |||
* @param pBuf - buffer to capture sprintf() data into | |||
* @param fmt - printf format | |||
* @param ap - va_list for fmt | |||
* | |||
* Returns 0 on success | |||
* Returns non-zero on failure | |||
*/ | |||
int membuf_vsprintf( struct membuf *pBuf , const char *fmt, va_list ap); | |||
/** Tokenize lines using strtok() | |||
* @param pBuf - buffer to tokenize | |||
* @param delim - delimiter parameter for strtok_r() | |||
* | |||
* Identical to "strtok()" - pass "pBuff=NULL" on second call | |||
* | |||
* NOTE: This call is <b>destructive</b> to the buffer. | |||
*/ | |||
const char *membuf_strtok( struct membuf *pBuf, const char *delim, void **pSave ); | |||
/** Return pointer to the memory in the buffer | |||
* @param pBuf - buffer | |||
* | |||
* NOTE: Thou shall not modify this pointer, it is <b>CONST</b> | |||
*/ | |||
const void *membuf_datapointer( struct membuf *pBuf ); | |||
/** Append data to the buffer | |||
* @param pBuf - buffer to append | |||
* @param pData - pointer to data to append | |||
* @param len - length of data to append | |||
* | |||
* Modified symantics of "memcpy()". On memory allocation failure | |||
* returns NULL. On success, returns pointer to orginal membuf. | |||
*/ | |||
struct membuf *membuf_append( struct membuf *pBuf, const void *pData, size_t len ); | |||
/** Append string to the buffer | |||
* @param pBuf - buffer to append | |||
* @param str - string to append | |||
* | |||
* Modified symantics of "strcat()". On memory allocation failure | |||
* returns NULL. On success, returns pointer to orginal membuf. | |||
*/ | |||
struct membuf *membuf_strcat( struct membuf *pBuf, const char *s ); | |||
#endif | |||
#ifndef HELPER_MEMBUF_H | |||
#define HELPER_MEMBUF_H | |||
/** @file */ | |||
/** @page MEMBUF - an auto-growing string buffer | |||
* | |||
* With OpenOCD often, one must write code that sends text to | |||
* different places.. the historical command_ctx, or JIM output, | |||
* and/or other places. | |||
* | |||
* This is a simple 'string buffer' that auto-grows. | |||
* | |||
* More correctly put, this is a "memory buffer" | |||
* it may contain binary data | |||
* | |||
* Note: Internally the buffer always has a 'null terminator' | |||
*/ | |||
/* contents of this structure are 'opaque' */ | |||
struct membuf; | |||
/** Create a new membuf | |||
* By default the memory buffer has "some non-zero-size" | |||
* (couple hundred bytes, exact amount is opaque) | |||
*/ | |||
struct membuf *membuf_new(void); | |||
/** delete (destroy) the mem buffer | |||
* @param pBuf - buffer to release | |||
*/ | |||
void membuf_delete( struct membuf *pBuf ); | |||
/** grow/shrink a membuf by specified amount. | |||
* @param pBuf - the buffer | |||
* @param amount - the amount to grow or shrink by. | |||
* | |||
* Symantics of 'realloc()' return NULL on failure | |||
*/ | |||
struct membuf *membuf_grow( struct membuf *pBuf, int amount ); | |||
/** how long is this buffer (memlen(), strlen()) | |||
* @param pBuf - the buffer | |||
* | |||
* @returns: length of current buffer. | |||
*/ | |||
size_t membuf_len( struct membuf *pBuf ); | |||
/** reset an membuf to zero length. | |||
* @param pBuf - buffer to reset | |||
* | |||
* Note this does not 'release' the memory buffer | |||
*/ | |||
void membuf_reset( struct membuf *pBuf ); | |||
/** sprintf() to the string buffer | |||
* @param pBuf - buffer to capture sprintf() data into | |||
* @param fmt - printf format | |||
* | |||
* Returns 0 on success | |||
* Returns non-zero on failure | |||
*/ | |||
int membuf_sprintf( struct membuf *pBuf , const char *fmt, ... ); | |||
/** vsprintf() to the string buffer | |||
* @param pBuf - buffer to capture sprintf() data into | |||
* @param fmt - printf format | |||
* @param ap - va_list for fmt | |||
* | |||
* Returns 0 on success | |||
* Returns non-zero on failure | |||
*/ | |||
int membuf_vsprintf( struct membuf *pBuf , const char *fmt, va_list ap); | |||
/** Tokenize lines using strtok() | |||
* @param pBuf - buffer to tokenize | |||
* @param delim - delimiter parameter for strtok_r() | |||
* | |||
* Identical to "strtok()" - pass "pBuff=NULL" on second call | |||
* | |||
* NOTE: This call is <b>destructive</b> to the buffer. | |||
*/ | |||
const char *membuf_strtok( struct membuf *pBuf, const char *delim, void **pSave ); | |||
/** Return pointer to the memory in the buffer | |||
* @param pBuf - buffer | |||
* | |||
* NOTE: Thou shall not modify this pointer, it is <b>CONST</b> | |||
*/ | |||
const void *membuf_datapointer( struct membuf *pBuf ); | |||
/** Append data to the buffer | |||
* @param pBuf - buffer to append | |||
* @param pData - pointer to data to append | |||
* @param len - length of data to append | |||
* | |||
* Modified symantics of "memcpy()". On memory allocation failure | |||
* returns NULL. On success, returns pointer to orginal membuf. | |||
*/ | |||
struct membuf *membuf_append( struct membuf *pBuf, const void *pData, size_t len ); | |||
/** Append string to the buffer | |||
* @param pBuf - buffer to append | |||
* @param str - string to append | |||
* | |||
* Modified symantics of "strcat()". On memory allocation failure | |||
* returns NULL. On success, returns pointer to orginal membuf. | |||
*/ | |||
struct membuf *membuf_strcat( struct membuf *pBuf, const char *s ); | |||
#endif |