diff --git a/src/misc/string.c b/src/misc/string.c index de2b870fd..8869404fa 100644 --- a/src/misc/string.c +++ b/src/misc/string.c @@ -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