ngspice/src/frontend/dimens.c

217 lines
4.2 KiB
C

/**********
Copyright 1992 Regents of the University of California. All rights reserved.
Author: 1992 David A. Gates, U. C. Berkeley CAD Group
**********/
/*
* Read and write dimension/index arrays via strings.
*/
#include "ngspice/ngspice.h"
#include "ngspice/dvec.h" /* For MAXDIMS */
#include "dimens.h"
/*
* Create a string of the form "12,1,10".
*/
void
dimstring(int *data, int length, char *retstring)
{
int i;
char buf[BSIZE_SP];
if (!data || length < 1)
retstring = "";
buf[0] = '\0';
for (i=0; i < length; i++) {
sprintf(buf + strlen(buf), "%d%s", data[i],
(i < length - 1) ? "," : "");
}
/* XXX Should I return a copy instead? */
/* qui ci devo fare una copia */
strcpy(retstring, buf);
}
/*
* Create a string of the form "[12][1][10]".
*/
void
indexstring(int *data, int length, char *retstring)
{
int i;
char buf[BSIZE_SP];
if (!data || length < 1)
retstring = "";
buf[0] = '\0';
for (i=0; i < length; i++) {
sprintf(buf + strlen(buf), "[%d]", data[i]);
}
strcpy(retstring, buf);
}
/*
* Add one to anstrchr into an array with sizes in dims.
* Return 1 when all counters overflow at once.
*/
int
incindex(int *counts, int numcounts, int *dims, int numdims)
{
int i, start;
if (!counts || numcounts < 1 || !dims || numdims < 1)
return 0;
start = numcounts - 1;
for (i = start; i >= 0; i--) {
if (++counts[i] < dims[i])
break; /* This counter is not maxed out. */
else
counts[i] = 0;
}
if (i == 0)
return(1);
else
return(0);
}
/*
* Count number of empty dimensions in an array.
*/
int
emptydims(int *data, int length)
{
int i, numempty = 0;
for (i=0; i < length; i++) {
if (data[i] == 0)
numempty++;
}
return(numempty);
}
/*
* Read a string of one of the following forms into a dimensions array:
* [12][1][10]
* [12,1,10]
* 12,1,10
* 12, 1, 10
* 12 , 1 , 10
* Basically, we require that all brackets be matched, that all numbers
* be separated by commas or by "][", that all whitespace is ignored, and
* the beginning [ and end ] are ignored if they exist. The only valid
* characters in the string are brackets, commas, spaces, and digits.
* If any dimension is blank, its entry in the array is set to 0.
*
* Return 0 on success, 1 on failure.
*/
int
atodims(char *p, int *data, int *outlength)
{
int length = 0;
int state = 0;
int err = 0;
int needbracket = 0;
char sep = '\0';
if (!data || !outlength)
return 1;
if (!p) {
*outlength = 0;
return 0;
}
while (*p && isspace(*p))
p++;
if (*p == '[') {
p++;
while (*p && isspace(*p))
p++;
needbracket = 1;
}
while (*p && state != 3) {
switch (state) {
case 0: /* p just at or before a number */
if (length >= MAXDIMS) {
if (length == MAXDIMS)
printf("Error: maximum of %d dimensions allowed.\n",
MAXDIMS);
length += 1;
} else if (!isdigit(*p)) {
data[length++] = 0; /* This position was empty. */
} else {
data[length++] = atoi(p);
while (isdigit(*p))
p++;
}
state = 1;
break;
case 1: /* p after a number, looking for ',' or ']' */
if (sep == '\0') {
sep = *p;
}
if (*p == ']' && *p == sep) {
p++;
state = 2;
} else if (*p == ',' && *p == sep) {
p++;
state = 0;
} else /* Funny character following a # */
break;
break;
case 2: /* p after a ']', either at the end or looking for '[' */
if (*p == '[') {
p++;
state = 0;
} else {
state = 3;
}
break;
}
while (*p && isspace(*p))
p++;
}
*outlength = length;
if (length > MAXDIMS) {
return(1);
}
if (state == 3) { /* We finished with a closing bracket */
err = !needbracket;
} else if (*p) { /* We finished by hitting a bad character after a # */
err = 1;
} else { /* We finished by exhausting the string */
err = needbracket;
}
if (err) {
*outlength = 0;
}
return(err);
}
/*
* Skip to the first character that cannot be part of a dimension string.
*/
char *
skipdims(char *p)
{
if (!p)
return NULL;
while(*p && (*p == '[' || *p == ']' || *p == ','
|| isspace(*p) || isdigit(*p)))
p++;
return(p);
}