string.c, #1/6, whitespace

This commit is contained in:
rlar 2017-03-25 16:48:22 +01:00
parent fb1c6fc123
commit d48bec757c
1 changed files with 235 additions and 190 deletions

View File

@ -19,24 +19,26 @@ prefix(const char *p, const char *s)
{
while (*p && (*p == *s))
p++, s++;
if (!*p)
return (TRUE);
else
return (FALSE);
}
/* Create a copy of a string. */
char *
copy(const char *str)
{
char *p;
if (!str)
return NULL;
if ((p = TMALLOC(char, strlen(str) + 1)) != NULL)
(void) strcpy(p, str);
(void) strcpy(p, str);
return(p);
}
@ -88,7 +90,6 @@ tvprintf(const char *fmt, va_list args)
p = TREALLOC(char, p, size);
}
return (p == buf) ? copy(p) : p;
}
@ -117,7 +118,7 @@ substring(const char *sub, const char *str)
while (*str) {
if (*str == *sub) {
t = str;
t = str;
for (s = sub; *s; s++) {
if (!*t || (*s != *t++))
break;
@ -127,9 +128,11 @@ substring(const char *sub, const char *str)
}
str++;
}
return (FALSE);
}
/* Append one character to a string. Don't check for overflow. */
/* Almost like strcat( ) XXX */
@ -143,6 +146,7 @@ appendc(char *s, char c)
return;
}
/* Try to identify an integer that begins a string. Stop when a non-
* numeric character is reached.
*/
@ -153,11 +157,13 @@ scannum(char *str)
{
int i = 0;
while(isdigit_c(*str))
while (isdigit_c(*str))
i = i * 10 + *(str++) - '0';
return(i);
}
/* Case insensitive str eq. */
/* Like strcasecmp( ) XXX */
@ -171,9 +177,11 @@ cieq(const char *p, const char *s)
p++;
s++;
}
return (*s ? FALSE : TRUE);
}
/* Case insensitive prefix. */
int
@ -186,135 +194,147 @@ ciprefix(const char *p, const char *s)
p++;
s++;
}
return (TRUE);
}
void
strtolower(char *str)
{
if (str)
while (*str) {
if(isupper_c(*str))
if (isupper_c(*str))
*str = tolower_c(*str);
str++;
}
}
void
strtoupper(char *str)
{
if (str)
while (*str) {
if(islower_c(*str))
if (islower_c(*str))
*str = toupper_c(*str);
str++;
}
}
#ifdef CIDER
/*
* Imported from cider file support/strmatch.c
* Original copyright notice:
* Author: 1991 David A. Gates, U. C. Berkeley CAD Group
*
*/
/*
* Case-insensitive test of whether p is a prefix of s and at least the
* first n characters are the same
*/
int
cinprefix(
register char *p, register char *s,
register int n)
cinprefix(register char *p, register char *s, register int n)
{
if (!p || !s) return( 0 );
while (*p) {
if ((isupper_c(*p) ? tolower_c(*p) : *p) != (isupper_c(*s) ? tolower_c(*s) : *s))
return( 0 );
p++;
s++;
n--;
}
if (n > 0)
return( 0 );
else
return( 1 );
}
if (!p || !s)
return(0);
while (*p) {
if ((isupper_c(*p) ? tolower_c(*p) : *p) != (isupper_c(*s) ? tolower_c(*s) : *s))
return(0);
p++;
s++;
n--;
}
if (n > 0)
return(0);
else
return(1);
}
/*
* Case-insensitive match of prefix string p against string s
* returns the number of matching characters
*
*
*/
int
cimatch(
register char *p, register char *s)
int
cimatch(register char *p, register char *s)
{
register int n = 0;
if (!p || !s) return( 0 );
while (*p) {
if ((isupper_c(*p) ? tolower_c(*p) : *p) != (isupper_c(*s) ? tolower_c(*s) : *s))
return( n );
p++;
s++;
n++;
}
return( n );
}
register int n = 0;
if (!p || !s)
return(0);
while (*p) {
if ((isupper_c(*p) ? tolower_c(*p) : *p) != (isupper_c(*s) ? tolower_c(*s) : *s))
return(n);
p++;
s++;
n++;
}
return(n);
}
#endif /* CIDER */
/*-------------------------------------------------------------------------*
* gettok skips over whitespace and returns the next token found. This is
* the original version. It does not "do the right thing" when you have
* gettok skips over whitespace and returns the next token found. This is
* the original version. It does not "do the right thing" when you have
* parens or commas anywhere in the nodelist. Note that I left this unmodified
* since I didn't want to break any fcns which called it from elsewhere than
* subckt.c. -- SDB 12.3.2003.
*-------------------------------------------------------------------------*/
char *
gettok(char **s)
{
char c;
int paren;
char *beg, *token ; /* return token */
char *beg, *token; /* return token */
paren = 0;
*s = skip_ws(*s);
if (!**s)
return (NULL);
beg = *s ;
beg = *s;
while ((c = **s) != '\0' && !isspace_c(c)) {
if (c == '(')
paren += 1;
else if (c == ')')
paren -= 1;
else if (c == ',' && paren < 1)
break;
(*s)++ ;
if (c == '(')
paren += 1;
else if (c == ')')
paren -= 1;
else if (c == ',' && paren < 1)
break;
(*s)++;
}
token = copy_substring(beg, *s) ;
token = copy_substring(beg, *s);
while (isspace_c(**s) || **s == ',')
(*s)++;
return ( token ) ;
return (token);
}
/*-------------------------------------------------------------------------*
* nexttok skips over whitespaces and the next token in s
* returns NULL if there is nothing left to skip.
* It replaces constructs like txfree(gettok(&actstring)) by
* actstring = nexttok(actstring). This is derived from the original gettok version.
* It does not "do the right thing" when
* you have parens or commas anywhere in the nodelist.
*-------------------------------------------------------------------------*/
* nexttok skips over whitespaces and the next token in s
* returns NULL if there is nothing left to skip.
* It replaces constructs like txfree(gettok(&actstring)) by
* actstring = nexttok(actstring). This is derived from the original gettok version.
* It does not "do the right thing" when
* you have parens or commas anywhere in the nodelist.
*-------------------------------------------------------------------------*/
char *
nexttok(const char *s)
{
@ -324,7 +344,7 @@ nexttok(const char *s)
if (!*s)
return NULL;
for (;*s && !isspace_c(*s); s++)
for (; *s && !isspace_c(*s); s++)
if (*s == '(')
paren += 1;
else if (*s == ')')
@ -340,157 +360,167 @@ nexttok(const char *s)
/*-------------------------------------------------------------------------*
* gettok skips over whitespaces or '=' and returns the next token found,
* gettok skips over whitespaces or '=' and returns the next token found,
* if the token is something like i(xxx), v(yyy), or v(xxx,yyy)
* -- h_vogt 10.07.2010.
*-------------------------------------------------------------------------*/
char *
gettok_iv(char **s)
{
char c;
int paren;
char *token ; /* return token */
SPICE_DSTRING buf ; /* allow any length string */
char *token; /* return token */
SPICE_DSTRING buf; /* allow any length string */
paren = 0;
while ((isspace_c(**s)) || (**s=='='))
while ((isspace_c(**s)) || (**s == '='))
(*s)++;
if ((!**s) || ((**s != 'v') && (**s != 'i') && (**s != 'V') && (**s != 'I')))
return (NULL);
// initialize string
spice_dstring_init(&buf);
// add v or i to buf
spice_dstring_append_char( &buf, *(*s)++ ) ;
spice_dstring_append_char(&buf, *(*s)++);
while ((c = **s) != '\0') {
if (c == '(')
paren += 1;
else if (c == ')')
paren -= 1;
if (isspace_c(c))
if (isspace_c(c))
(*s)++;
else {
spice_dstring_append_char( &buf, *(*s)++ ) ;
if (paren == 0) break;
spice_dstring_append_char(&buf, *(*s)++);
if (paren == 0)
break;
}
}
while (isspace_c(**s) || **s == ',')
(*s)++;
token = copy( spice_dstring_value(&buf) ) ;
spice_dstring_free(&buf) ;
return ( token ) ;
token = copy(spice_dstring_value(&buf));
spice_dstring_free(&buf);
return (token);
}
/*-------------------------------------------------------------------------*
* gettok_noparens was added by SDB on 4.21.2003.
* It acts like gettok, except that it treats parens and commas like
* whitespace while looking for the POLY token. That is, it stops
* parsing and returns when it finds one of those chars. It is called from
* whitespace while looking for the POLY token. That is, it stops
* parsing and returns when it finds one of those chars. It is called from
* 'translate' (subckt.c).
*-------------------------------------------------------------------------*/
char *
gettok_noparens(char **s)
{
char c;
char *beg, *token ; /* return token */
char *beg, *token; /* return token */
*s = skip_ws(*s);
if (!**s)
return (NULL); /* return NULL if we come to end of line */
beg = *s ;
while ((c = **s) != '\0' &&
!isspace_c(c) &&
( **s != '(' ) &&
( **s != ')' ) &&
( **s != ',')
) {
(*s)++ ;
beg = *s;
while ((c = **s) != '\0' &&
!isspace_c(c) &&
(**s != '(') &&
(**s != ')') &&
(**s != ',')
) {
(*s)++;
}
token = copy_substring(beg, *s);
token = copy_substring(beg, *s) ;
/* Now iterate up to next non-whitespace char */
*s = skip_ws(*s);
return ( token ) ;
return (token);
}
char *
gettok_instance(char **s)
{
char c;
char *beg, *token ; /* return token */
char *beg, *token; /* return token */
*s = skip_ws(*s);
if (!**s)
return (NULL); /* return NULL if we come to end of line */
beg = *s ;
while ((c = **s) != '\0' &&
!isspace_c(c) &&
( **s != '(' ) &&
( **s != ')' )
) {
(*s)++ ;
beg = *s;
while ((c = **s) != '\0' &&
!isspace_c(c) &&
(**s != '(') &&
(**s != ')')
) {
(*s)++;
}
token = copy_substring(beg, *s) ;
token = copy_substring(beg, *s);
/* Now iterate up to next non-whitespace char */
*s = skip_ws(*s);
return ( token ) ;
return (token);
}
/* get the next token starting at next non white spice, stopping
at p, if inc_p is true, then including p, else excluding p,
return NULL if p is not found.
If '}', ']' or ')' and nested is true, find corresponding p
*/
char *
gettok_char(char **s, char p, bool inc_p, bool nested)
{
char c;
char *beg, *token ; /* return token */
char *beg, *token; /* return token */
*s = skip_ws(*s);
if (!**s)
return (NULL); /* return NULL if we come to end of line */
beg = *s ;
if (nested && (( p == '}' ) || ( p == ')' ) || ( p == ']'))) {
beg = *s;
if (nested && ((p == '}') || (p == ')') || (p == ']'))) {
char q;
int count = 0;
/* find opening bracket */
if ( p == '}' )
if (p == '}')
q = '{';
else if(p == ']' )
else if (p == ']')
q = '[';
else
q = '(';
/* add string in front of q, excluding q */
while ((c = **s) != '\0' && ( **s != q )) {
(*s)++ ;
while ((c = **s) != '\0' && (**s != q)) {
(*s)++;
}
/* return if nested bracket found, excluding its character */
while ((c = **s) != '\0') {
if (c == q) count++;
else if (c == p) count--;
while ((c = **s) != '\0') {
if (c == q)
count++;
else if (c == p)
count--;
if (count == 0) {
break;
}
(*s)++ ;
(*s)++;
}
}
else
/* just look for p and return string, excluding p */
while ((c = **s) != '\0' && ( **s != p )) {
(*s)++ ;
while ((c = **s) != '\0' && (**s != p)) {
(*s)++;
}
if (c == '\0')
@ -499,48 +529,50 @@ gettok_char(char **s, char p, bool inc_p, bool nested)
if (inc_p)
/* add p */
(*s)++ ;
(*s)++;
token = copy_substring(beg, *s) ;
token = copy_substring(beg, *s);
/* Now iterate up to next non-whitespace char */
*s = skip_ws(*s);
return ( token ) ;
return (token);
}
/*-------------------------------------------------------------------------*
* gettok_node was added by SDB on 12.3.2003
* It acts like gettok, except that it treats parens and commas like
* whitespace (i.e. it ignores them). Use it when parsing through netnames
* (node names) since they may be grouped using ( , ).
*-------------------------------------------------------------------------*/
char *
gettok_node(char **s)
{
char c;
char *token ; /* return token */
char *token; /* return token */
if (*s == NULL)
return NULL;
while (isspace_c(**s) ||
( **s == '(' ) ||
( **s == ')' ) ||
( **s == ',')
)
(**s == '(') ||
(**s == ')') ||
(**s == ',')
)
(*s)++; /* iterate over whitespace and ( , ) */
if (!**s)
return (NULL); /* return NULL if we come to end of line */
token = *s;
while ((c = **s) != '\0' &&
!isspace_c(c) &&
( **s != '(' ) &&
( **s != ')' ) &&
( **s != ',')
) { /* collect chars until whitespace or ( , ) */
while ((c = **s) != '\0' &&
!isspace_c(c) &&
(**s != '(') &&
(**s != ')') &&
(**s != ',')
) { /* collect chars until whitespace or ( , ) */
(*s)++;
}
@ -548,29 +580,32 @@ gettok_node(char **s)
/* Now iterate up to next non-whitespace char */
while (isspace_c(**s) ||
( **s == '(' ) ||
( **s == ')' ) ||
( **s == ',')
)
(**s == '(') ||
(**s == ')') ||
(**s == ',')
)
(*s)++; /* iterate over whitespace and ( , ) */
return ( token ) ;
return (token);
}
/*-------------------------------------------------------------------------*
* get_l_paren iterates the pointer forward in a string until it hits
* the position after the next left paren "(". It returns 0 if it found a left
* the position after the next left paren "(". It returns 0 if it found a left
* paren, and 1 if no left paren is found. It is called from 'translate'
* (subckt.c).
*-------------------------------------------------------------------------*/
int
get_l_paren(char **s)
{
while (**s && ( **s != '(' ) )
while (**s && (**s != '('))
(*s)++;
if (!**s)
return (1);
(*s)++;
if (!**s)
@ -582,15 +617,17 @@ get_l_paren(char **s)
/*-------------------------------------------------------------------------*
* get_r_paren iterates the pointer forward in a string until it hits
* the position after the next right paren ")". It returns 0 if it found a right
* the position after the next right paren ")". It returns 0 if it found a right
* paren, and 1 if no right paren is found. It is called from 'translate'
* (subckt.c).
*-------------------------------------------------------------------------*/
int
get_r_paren(char **s)
{
while (**s && ( **s != ')' ) )
while (**s && (**s != ')'))
(*s)++;
if (!**s)
return (1);
@ -598,7 +635,7 @@ get_r_paren(char **s)
if (!**s)
return (1);
else
else
return 0;
}
@ -607,85 +644,93 @@ get_r_paren(char **s)
* is needed in gettoks (dotcards.c) for right processing of expressions
* like ".plot v( 5,4) v(6)"
*-------------------------------------------------------------------------*/
char *
stripWhiteSpacesInsideParens(char *str)
{
char *token ; /* return token */
SPICE_DSTRING buf ; /* allow any length string */
int i = 0 ; /* index into string */
char *token; /* return token */
SPICE_DSTRING buf; /* allow any length string */
int i = 0; /* index into string */
while ( (str[i] == ' ') || (str[i] == '\t') )
while ((str[i] == ' ') || (str[i] == '\t'))
i++;
spice_dstring_init(&buf) ;
for(i=i; str[i]!='\0'; i++)
{
if ( str[i] != '(' ) {
spice_dstring_append_char( &buf, str[i] ) ;
spice_dstring_init(&buf);
for (i = i; str[i] != '\0'; i++) {
if (str[i] != '(') {
spice_dstring_append_char(&buf, str[i]);
} else {
spice_dstring_append_char( &buf, str[i] ) ;
while ( (str[i++] != ')') ) {
if ( str[i] != ' ' ) spice_dstring_append_char( &buf, str[i] ) ;
spice_dstring_append_char(&buf, str[i]);
while ((str[i++] != ')')) {
if (str[i] != ' ')
spice_dstring_append_char(&buf, str[i]);
}
i--;
}
}
token = copy( spice_dstring_value(&buf) ) ;
spice_dstring_free(&buf) ;
return ( token ) ;
token = copy(spice_dstring_value(&buf));
spice_dstring_free(&buf);
return (token);
}
bool
isquote( char ch )
isquote(char ch)
{
return ( ch == '\'' || ch == '"' );
return (ch == '\'' || ch == '"');
}
bool
is_arith_char( char c )
is_arith_char(char c)
{
if (c != '\0' && strchr("+-*/()<>?:|&^!%\\", c))
return TRUE;
else
if (c != '\0' && strchr("+-*/()<>?:|&^!%\\", c))
return TRUE;
else
return FALSE;
}
bool
str_has_arith_char(char *s)
{
while (*s && *s != '\0') {
if (is_arith_char(*s))
return TRUE;
s++;
}
return FALSE;
}
bool
str_has_arith_char( char *s )
{
while ( *s && *s != '\0' ) {
if ( is_arith_char(*s) ) return TRUE;
s++;
}
return FALSE;
}
int
get_comma_separated_values( char *values[], char *str ) {
int count = 0;
char *ptr, *comma_ptr, keep;
while ( ( comma_ptr = strchr( str, ',' ) ) != NULL ) {
ptr = comma_ptr - 1;
while ( isspace_c(*ptr) ) ptr--;
ptr++; keep = *ptr; *ptr = '\0';
get_comma_separated_values(char *values[], char *str) {
int count = 0;
char *ptr, *comma_ptr, keep;
while ((comma_ptr = strchr(str, ',')) != NULL) {
ptr = comma_ptr - 1;
while (isspace_c(*ptr))
ptr--;
ptr++; keep = *ptr; *ptr = '\0';
values[count++] = strdup(str);
*ptr = keep;
str = skip_ws(comma_ptr + 1);
}
values[count++] = strdup(str);
*ptr = keep;
str = skip_ws(comma_ptr + 1);
}
values[count++] = strdup(str);
return count;
return count;
}
/*
check if the given token matches a model name
either exact
then return 1
either exact
then return 1
or
modulo a trailing model binning extension '\.[0-9]+'
then return 2
modulo a trailing model binning extension '\.[0-9]+'
then return 2
*/
int