2011-12-13 20:57:45 +01:00
|
|
|
|
/* -----------------------------------------------------------------
|
|
|
|
|
|
FILE: dstring.c
|
2010-03-25 23:44:37 +01:00
|
|
|
|
DESCRIPTION:This file contains the routines for manipulating dynamic strings.
|
|
|
|
|
|
----------------------------------------------------------------- */
|
2011-12-11 19:05:00 +01:00
|
|
|
|
#include "ngspice/ngspice.h"
|
2010-03-25 23:44:37 +01:00
|
|
|
|
#include <stdarg.h>
|
2011-12-11 19:05:00 +01:00
|
|
|
|
#include "ngspice/dstring.h"
|
2010-03-25 23:44:37 +01:00
|
|
|
|
|
|
|
|
|
|
/* definitions local to this file only */
|
|
|
|
|
|
|
|
|
|
|
|
/* ********************** TYPE DEFINITIONS ************************* */
|
|
|
|
|
|
|
|
|
|
|
|
/* ********************** STATIC DEFINITIONS ************************* */
|
|
|
|
|
|
/*
|
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
|
*
|
|
|
|
|
|
* spice_dstring_init --
|
|
|
|
|
|
*
|
|
|
|
|
|
* Initializes a dynamic string, discarding any previous contents
|
|
|
|
|
|
* of the string (spice_dstring_free should have been called already
|
|
|
|
|
|
* if the dynamic string was previously in use).
|
|
|
|
|
|
*
|
|
|
|
|
|
* Results:
|
|
|
|
|
|
* None.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Side effects:
|
|
|
|
|
|
* The dynamic string is initialized to be empty.
|
|
|
|
|
|
*
|
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
void spice_dstring_init(SPICE_DSTRINGPTR dsPtr)
|
|
|
|
|
|
{
|
|
|
|
|
|
dsPtr->string = dsPtr->staticSpace ;
|
|
|
|
|
|
dsPtr->length = 0 ;
|
|
|
|
|
|
dsPtr->spaceAvl = SPICE_DSTRING_STATIC_SIZE ;
|
2010-10-09 13:42:10 +02:00
|
|
|
|
dsPtr->staticSpace[0] = '\0';
|
2010-03-25 23:44:37 +01:00
|
|
|
|
} /* end spice_dstring_init() */
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
|
*
|
|
|
|
|
|
* spice_dstring_append --
|
|
|
|
|
|
*
|
|
|
|
|
|
* Append more characters to the current value of a dynamic string.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Results:
|
|
|
|
|
|
* The return value is a pointer to the dynamic string's new value.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Side effects:
|
|
|
|
|
|
* Length bytes from string (or all of string if length is less
|
|
|
|
|
|
* than zero) are added to the current value of the string. Memory
|
|
|
|
|
|
* gets reallocated if needed to accomodate the string's new size.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Notes: char *string; String to append. If length is -1 then
|
|
|
|
|
|
* this must be null-terminated.
|
|
|
|
|
|
* INT length; Number of characters from string to append.
|
|
|
|
|
|
* If < 0, then append all of string, up to null at end.
|
|
|
|
|
|
*
|
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
|
*/
|
|
|
|
|
|
char *spice_dstring_append(SPICE_DSTRINGPTR dsPtr,char *string,int length)
|
|
|
|
|
|
{
|
|
|
|
|
|
int newSize ; /* needed size */
|
|
|
|
|
|
char *newString ; /* newly allocated string buffer */
|
|
|
|
|
|
char *dst ; /* destination */
|
|
|
|
|
|
char *end ; /* end of string */
|
|
|
|
|
|
|
|
|
|
|
|
if( length < 0){
|
2010-11-06 17:54:11 +01:00
|
|
|
|
length = (int) strlen(string) ;
|
2010-03-25 23:44:37 +01:00
|
|
|
|
}
|
|
|
|
|
|
newSize = length + dsPtr->length ;
|
|
|
|
|
|
|
|
|
|
|
|
/* -----------------------------------------------------------------
|
|
|
|
|
|
* Allocate a larger buffer for the string if the current one isn't
|
|
|
|
|
|
* large enough. Allocate extra space in the new buffer so that there
|
|
|
|
|
|
* will be room to grow before we have to allocate again.
|
|
|
|
|
|
----------------------------------------------------------------- */
|
|
|
|
|
|
if (newSize >= dsPtr->spaceAvl) {
|
|
|
|
|
|
dsPtr->spaceAvl = 2 * newSize ;
|
2010-10-28 21:32:34 +02:00
|
|
|
|
newString = TMALLOC(char, dsPtr->spaceAvl) ;
|
2011-06-22 19:17:40 +02:00
|
|
|
|
memcpy(newString, dsPtr->string, (size_t) dsPtr->length) ;
|
2010-03-25 23:44:37 +01:00
|
|
|
|
if (dsPtr->string != dsPtr->staticSpace) {
|
|
|
|
|
|
txfree(dsPtr->string) ;
|
|
|
|
|
|
}
|
|
|
|
|
|
dsPtr->string = newString;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* -----------------------------------------------------------------
|
|
|
|
|
|
* Copy the new string into the buffer at the end of the old
|
|
|
|
|
|
* one.
|
|
|
|
|
|
----------------------------------------------------------------- */
|
|
|
|
|
|
for( dst = dsPtr->string + dsPtr->length, end = string+length;
|
|
|
|
|
|
string < end; string++, dst++) {
|
|
|
|
|
|
*dst = *string ;
|
|
|
|
|
|
}
|
2010-10-09 13:42:10 +02:00
|
|
|
|
*dst = '\0' ;
|
2010-03-25 23:44:37 +01:00
|
|
|
|
dsPtr->length += length ;
|
|
|
|
|
|
|
|
|
|
|
|
return(dsPtr->string) ;
|
|
|
|
|
|
|
|
|
|
|
|
} /* end spice_dstring_append() */
|
|
|
|
|
|
|
2012-12-09 13:27:53 +01:00
|
|
|
|
/*
|
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
|
*
|
|
|
|
|
|
* spice_dstring_append_lower --
|
|
|
|
|
|
*
|
|
|
|
|
|
* Append more characters converted to lower case to the current
|
|
|
|
|
|
* value of a dynamic string.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Results:
|
|
|
|
|
|
* The return value is a pointer to the dynamic string's new value.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Side effects:
|
|
|
|
|
|
* Length bytes from string (or all of string if length is less
|
|
|
|
|
|
* than zero) are added to the current value of the string. Memory
|
|
|
|
|
|
* gets reallocated if needed to accomodate the string's new size.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Notes: char *string; String to append. If length is -1 then
|
|
|
|
|
|
* this must be null-terminated.
|
|
|
|
|
|
* INT length; Number of characters from string to append.
|
|
|
|
|
|
* If < 0, then append all of string, up to null at end.
|
|
|
|
|
|
*
|
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
|
*/
|
|
|
|
|
|
char *spice_dstring_append_lower(SPICE_DSTRINGPTR dsPtr,char *string,int length)
|
|
|
|
|
|
{
|
|
|
|
|
|
int newSize ; /* needed size */
|
|
|
|
|
|
char *newString ; /* newly allocated string buffer */
|
|
|
|
|
|
char *dst ; /* destination */
|
|
|
|
|
|
char *end ; /* end of string */
|
|
|
|
|
|
|
|
|
|
|
|
if( length < 0){
|
|
|
|
|
|
length = (int) strlen(string) ;
|
|
|
|
|
|
}
|
|
|
|
|
|
newSize = length + dsPtr->length ;
|
|
|
|
|
|
|
|
|
|
|
|
/* -----------------------------------------------------------------
|
|
|
|
|
|
* Allocate a larger buffer for the string if the current one isn't
|
|
|
|
|
|
* large enough. Allocate extra space in the new buffer so that there
|
|
|
|
|
|
* will be room to grow before we have to allocate again.
|
|
|
|
|
|
----------------------------------------------------------------- */
|
|
|
|
|
|
if (newSize >= dsPtr->spaceAvl) {
|
|
|
|
|
|
dsPtr->spaceAvl = 2 * newSize ;
|
|
|
|
|
|
newString = TMALLOC(char, dsPtr->spaceAvl) ;
|
|
|
|
|
|
memcpy(newString, dsPtr->string, (size_t) dsPtr->length) ;
|
|
|
|
|
|
if (dsPtr->string != dsPtr->staticSpace) {
|
|
|
|
|
|
txfree(dsPtr->string) ;
|
|
|
|
|
|
}
|
|
|
|
|
|
dsPtr->string = newString;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* -----------------------------------------------------------------
|
|
|
|
|
|
* Copy the new string into the buffer at the end of the old
|
|
|
|
|
|
* one.
|
|
|
|
|
|
----------------------------------------------------------------- */
|
|
|
|
|
|
for( dst = dsPtr->string + dsPtr->length, end = string+length;
|
|
|
|
|
|
string < end; string++, dst++) {
|
|
|
|
|
|
if( isupper(*string) ) {
|
|
|
|
|
|
*dst = (char)tolower(*string) ;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
*dst = *string ;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
*dst = '\0' ;
|
|
|
|
|
|
dsPtr->length += length ;
|
|
|
|
|
|
|
|
|
|
|
|
return(dsPtr->string) ;
|
|
|
|
|
|
|
|
|
|
|
|
} /* end spice_dstring_append_lower() */
|
|
|
|
|
|
|
2010-03-25 23:44:37 +01:00
|
|
|
|
/* -----------------------------------------------------------------
|
|
|
|
|
|
* Function: add character c to dynamic string dstr_p.
|
|
|
|
|
|
* ----------------------------------------------------------------- */
|
|
|
|
|
|
char *spice_dstring_append_char( SPICE_DSTRINGPTR dstr_p, char c)
|
|
|
|
|
|
{
|
2013-07-18 19:28:52 +02:00
|
|
|
|
return spice_dstring_append( dstr_p, &c, 1 ) ;
|
2010-03-25 23:44:37 +01:00
|
|
|
|
} /* end spice_dstring_append_char() */
|
|
|
|
|
|
|
|
|
|
|
|
static int spice_format_length( va_list args, char *fmt )
|
|
|
|
|
|
{
|
|
|
|
|
|
int i ; /* integer */
|
|
|
|
|
|
int len ; /* length of format */
|
|
|
|
|
|
int size_format ; /* width of field */
|
|
|
|
|
|
int found_special ; /* look for special characters */
|
|
|
|
|
|
char *s ; /* string */
|
2011-06-26 22:00:03 +02:00
|
|
|
|
double d ;
|
2010-03-25 23:44:37 +01:00
|
|
|
|
|
|
|
|
|
|
/* -----------------------------------------------------------------
|
|
|
|
|
|
* First find length of buffer.
|
|
|
|
|
|
----------------------------------------------------------------- */
|
|
|
|
|
|
len = 0 ;
|
|
|
|
|
|
while(fmt && *fmt){
|
|
|
|
|
|
if( *fmt == '%' ){
|
|
|
|
|
|
fmt++ ;
|
|
|
|
|
|
if( *fmt == '%' ){
|
|
|
|
|
|
len++ ;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
/* -----------------------------------------------------------------
|
|
|
|
|
|
* We have a real formatting character, loop until we get a special
|
|
|
|
|
|
* character.
|
|
|
|
|
|
----------------------------------------------------------------- */
|
|
|
|
|
|
if( *fmt == '.' || *fmt == '-' ){
|
|
|
|
|
|
fmt++ ; /* skip over these characters */
|
|
|
|
|
|
}
|
|
|
|
|
|
size_format = atoi(fmt) ;
|
|
|
|
|
|
if( size_format > 0 ){
|
|
|
|
|
|
len += size_format ;
|
|
|
|
|
|
}
|
|
|
|
|
|
found_special = FALSE ;
|
|
|
|
|
|
for( ; fmt && *fmt ; fmt++ ){
|
|
|
|
|
|
switch( *fmt ){
|
|
|
|
|
|
case 's':
|
|
|
|
|
|
s = va_arg(args, char *) ;
|
|
|
|
|
|
if( s ){
|
2010-11-06 21:17:19 +01:00
|
|
|
|
len += (int) strlen(s) ;
|
2010-03-25 23:44:37 +01:00
|
|
|
|
}
|
|
|
|
|
|
found_special = TRUE ;
|
|
|
|
|
|
break ;
|
|
|
|
|
|
case 'i':
|
|
|
|
|
|
case 'd':
|
|
|
|
|
|
case 'o':
|
|
|
|
|
|
case 'x':
|
|
|
|
|
|
case 'X':
|
|
|
|
|
|
case 'u':
|
|
|
|
|
|
i = va_arg(args, int) ;
|
|
|
|
|
|
len += 10 ;
|
|
|
|
|
|
found_special = TRUE ;
|
|
|
|
|
|
break ;
|
|
|
|
|
|
case 'c':
|
2011-06-26 22:00:03 +02:00
|
|
|
|
i = va_arg(args, int) ;
|
2010-03-25 23:44:37 +01:00
|
|
|
|
len++ ;
|
|
|
|
|
|
found_special = TRUE ;
|
|
|
|
|
|
break ;
|
|
|
|
|
|
case 'f':
|
|
|
|
|
|
case 'e':
|
|
|
|
|
|
case 'F':
|
|
|
|
|
|
case 'g':
|
|
|
|
|
|
case 'G':
|
2011-06-26 22:00:03 +02:00
|
|
|
|
d = va_arg(args, double) ;
|
2010-03-25 23:44:37 +01:00
|
|
|
|
len += 35 ;
|
|
|
|
|
|
found_special = TRUE ;
|
|
|
|
|
|
break ;
|
|
|
|
|
|
default:
|
|
|
|
|
|
;
|
|
|
|
|
|
} /* end switch() */
|
|
|
|
|
|
|
|
|
|
|
|
if( found_special ){
|
|
|
|
|
|
break ;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
len++ ;
|
|
|
|
|
|
}
|
|
|
|
|
|
fmt++ ;
|
|
|
|
|
|
} /* end while() */
|
|
|
|
|
|
va_end(args) ;
|
|
|
|
|
|
|
|
|
|
|
|
return(len) ;
|
|
|
|
|
|
|
|
|
|
|
|
} /* end Ymessage_format_length() */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
char *spice_dstring_print( SPICE_DSTRINGPTR dsPtr,char *format, ... )
|
|
|
|
|
|
{
|
|
|
|
|
|
va_list args ;
|
|
|
|
|
|
int format_len ; /* length of format */
|
|
|
|
|
|
int length ; /* new length */
|
|
|
|
|
|
int orig_length ; /* original length of buffer */
|
|
|
|
|
|
char *buffer ; /* proper length of buffer */
|
|
|
|
|
|
|
|
|
|
|
|
/* -----------------------------------------------------------------
|
|
|
|
|
|
* First get the length of the buffer needed.
|
|
|
|
|
|
----------------------------------------------------------------- */
|
|
|
|
|
|
va_start( args, format ) ;
|
|
|
|
|
|
format_len = spice_format_length(args,format) ;
|
|
|
|
|
|
|
|
|
|
|
|
/* -----------------------------------------------------------------
|
|
|
|
|
|
* Next allocate the proper buffer size.
|
|
|
|
|
|
----------------------------------------------------------------- */
|
|
|
|
|
|
orig_length = dsPtr->length ;
|
|
|
|
|
|
length = orig_length + format_len + 1 ;
|
|
|
|
|
|
buffer = spice_dstring_setlength( dsPtr, length) ;
|
|
|
|
|
|
|
|
|
|
|
|
/* -----------------------------------------------------------------
|
|
|
|
|
|
* Convert the format.
|
|
|
|
|
|
----------------------------------------------------------------- */
|
|
|
|
|
|
va_start( args, format ) ;
|
|
|
|
|
|
if( format ){
|
|
|
|
|
|
vsprintf( buffer + orig_length, format, args ) ;
|
2010-11-06 17:54:11 +01:00
|
|
|
|
dsPtr->length = (int) strlen(buffer) ;
|
2010-03-25 23:44:37 +01:00
|
|
|
|
} else {
|
|
|
|
|
|
buffer = NULL ;
|
|
|
|
|
|
}
|
|
|
|
|
|
va_end(args) ;
|
|
|
|
|
|
return( buffer ) ;
|
|
|
|
|
|
|
|
|
|
|
|
} /* end spice_dstring_print() */
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
|
*
|
|
|
|
|
|
* _spice_dstring_setlength --
|
|
|
|
|
|
*
|
|
|
|
|
|
* Change the length of a dynamic string. This can cause the
|
|
|
|
|
|
* string to either grow or shrink, depending on the value of
|
|
|
|
|
|
* length.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Results:
|
|
|
|
|
|
* Returns the current string buffer.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Side effects:
|
|
|
|
|
|
* The length of dsPtr is changed to length but a null byte is not
|
|
|
|
|
|
* stored at that position in the string. Use spice_dstring_setlength
|
|
|
|
|
|
* for that function. If length is larger
|
|
|
|
|
|
* than the space allocated for dsPtr, then a panic occurs.
|
|
|
|
|
|
*
|
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
char *_spice_dstring_setlength(SPICE_DSTRINGPTR dsPtr,int length)
|
|
|
|
|
|
{
|
|
|
|
|
|
char *newString ;
|
|
|
|
|
|
|
|
|
|
|
|
if (length < 0) {
|
|
|
|
|
|
length = 0 ;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (length >= dsPtr->spaceAvl) {
|
|
|
|
|
|
|
|
|
|
|
|
dsPtr->spaceAvl = length+1;
|
2010-10-28 21:32:34 +02:00
|
|
|
|
newString = TMALLOC(char, dsPtr->spaceAvl) ;
|
2010-03-25 23:44:37 +01:00
|
|
|
|
/* -----------------------------------------------------------------
|
|
|
|
|
|
* SPECIAL NOTE: must use memcpy, not strcpy, to copy the string
|
|
|
|
|
|
* to a larger buffer, since there may be embedded NULLs in the
|
|
|
|
|
|
* string in some cases.
|
|
|
|
|
|
----------------------------------------------------------------- */
|
2011-06-22 19:17:40 +02:00
|
|
|
|
memcpy(newString, dsPtr->string, (size_t) dsPtr->length) ;
|
2010-03-25 23:44:37 +01:00
|
|
|
|
if( dsPtr->string != dsPtr->staticSpace ) {
|
|
|
|
|
|
txfree(dsPtr->string) ;
|
|
|
|
|
|
}
|
|
|
|
|
|
dsPtr->string = newString ;
|
|
|
|
|
|
}
|
|
|
|
|
|
dsPtr->length = length ;
|
|
|
|
|
|
return(dsPtr->string) ;
|
|
|
|
|
|
|
|
|
|
|
|
} /* end _spice_dstring_setlength() */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
|
*
|
|
|
|
|
|
* spice_dstring_setlength --
|
|
|
|
|
|
*
|
|
|
|
|
|
* Change the length of a dynamic string. This can cause the
|
|
|
|
|
|
* string to either grow or shrink, depending on the value of
|
|
|
|
|
|
* length.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Results:
|
|
|
|
|
|
* Returns the current string buffer.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Side effects:
|
|
|
|
|
|
* The length of dsPtr is changed to length and a null byte is
|
|
|
|
|
|
* stored at that position in the string. If length is larger
|
|
|
|
|
|
* than the space allocated for dsPtr, then a panic occurs.
|
|
|
|
|
|
*
|
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
char *spice_dstring_setlength(SPICE_DSTRINGPTR dsPtr,int length)
|
|
|
|
|
|
{
|
|
|
|
|
|
char *str_p ; /* newly create string */
|
|
|
|
|
|
|
|
|
|
|
|
str_p = _spice_dstring_setlength( dsPtr,length) ;
|
2010-10-09 13:42:10 +02:00
|
|
|
|
str_p[length] = '\0' ;
|
2010-03-25 23:44:37 +01:00
|
|
|
|
return( str_p ) ;
|
|
|
|
|
|
|
|
|
|
|
|
} /* end spice_dstring_setlength() */
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
|
*
|
|
|
|
|
|
* spice_dstring_free --
|
|
|
|
|
|
*
|
|
|
|
|
|
* Frees up any memory allocated for the dynamic string and
|
|
|
|
|
|
* reinitializes the string to an empty state.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Results:
|
|
|
|
|
|
* None.
|
|
|
|
|
|
*
|
|
|
|
|
|
* Side effects:
|
|
|
|
|
|
* The previous contents of the dynamic string are lost, and
|
|
|
|
|
|
* the new value is an empty string.
|
|
|
|
|
|
*
|
|
|
|
|
|
*----------------------------------------------------------------------
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
void spice_dstring_free(SPICE_DSTRINGPTR dsPtr)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (dsPtr->string != dsPtr->staticSpace) {
|
|
|
|
|
|
txfree(dsPtr->string) ;
|
|
|
|
|
|
}
|
|
|
|
|
|
dsPtr->string = dsPtr->staticSpace ;
|
|
|
|
|
|
dsPtr->length = 0 ;
|
|
|
|
|
|
dsPtr->spaceAvl = SPICE_DSTRING_STATIC_SIZE;
|
2010-10-09 13:42:10 +02:00
|
|
|
|
dsPtr->staticSpace[0] = '\0' ;
|
2010-03-25 23:44:37 +01:00
|
|
|
|
|
|
|
|
|
|
} /* end spice_dstring_free() */
|