249 lines
6.0 KiB
C
249 lines
6.0 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"
|
|
#include "ngspice/stringskip.h"
|
|
|
|
|
|
/*
|
|
* Create a string of the form "12,1,10".
|
|
*
|
|
* Parameters
|
|
* dim_data: Array of sizes of dimensions, [12, 1, 10] for the example
|
|
* n_dim: Number of elements in the array, 3 in the example
|
|
* retstring: Address of buffer where the string is returned.
|
|
|
|
* Remarks
|
|
* It is assumed that the buffer in retstring is large enough, which for
|
|
* MAXDIMS, would require MAXDIMS * 11 bytes in the worst case assuming
|
|
* 32-bit ints. A looser but more general bound only assuming 8-bit bytes
|
|
* would be MAXDIMS * (3 * sizeof(int) + 1).
|
|
*/
|
|
void
|
|
dimstring(const int *dim_data, int n_dim, char *retstring)
|
|
{
|
|
/* Handle case of no dimensions */
|
|
if (dim_data == (int *) NULL || n_dim < 1) {
|
|
*retstring = '\0';
|
|
return;
|
|
}
|
|
|
|
/* Append each dimension */
|
|
retstring += sprintf(retstring, "%d", dim_data[0]); /* first */
|
|
int i;
|
|
for (i = 1; i < n_dim; i++) { /* rest are prefixed by a comma */
|
|
retstring += sprintf(retstring, ",%d", dim_data[i]);
|
|
}
|
|
} /* end of function dimstring */
|
|
|
|
|
|
|
|
/*
|
|
* Create a string of the form "[12][1][10]" in retstring.
|
|
*
|
|
* Parameters
|
|
* dim_data: Array of sizes of dimensions, [12, 1, 10] for the example
|
|
* n_dim: Number of elements in the array, 3 in the example
|
|
* retstring: Address of buffer where the string is returned.
|
|
|
|
* Remarks
|
|
* It is assumed that the buffer in retstring is large enough, which for
|
|
* MAXDIMS, would require MAXDIMS * 12 + 1 bytes in the worst case assuming
|
|
* 32-bit ints. A looser but more general bound only assuming 8-bit bytes
|
|
* would be MAXDIMS * (3 * sizeof(int) + 2) + 1.
|
|
*/
|
|
void
|
|
indexstring(const int *dim_data, int n_dim, char *retstring)
|
|
{
|
|
/* Handle case of no dimensions */
|
|
if (dim_data == (int *) NULL || n_dim < 1) {
|
|
*retstring = '\0';
|
|
return;
|
|
}
|
|
|
|
/* Append each dimension */
|
|
int i;
|
|
for (i = 0; i < n_dim; i++) {
|
|
retstring += sprintf(retstring, "[%d]", dim_data[i]);
|
|
}
|
|
} /* end of function indexstring */
|
|
|
|
|
|
|
|
/*
|
|
* 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, const 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);
|
|
}
|
|
|
|
|
|
/*
|
|
* 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;
|
|
}
|
|
|
|
p = skip_ws(p);
|
|
|
|
if (*p == '[') {
|
|
p = skip_ws(p + 1);
|
|
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_c(*p)) {
|
|
data[length++] = 0; /* This position was empty. */
|
|
} else {
|
|
data[length++] = atoi(p);
|
|
while (isdigit_c(*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;
|
|
}
|
|
|
|
p = skip_ws(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);
|
|
}
|
|
|
|
|
|
|
|
#ifdef COMPILE_UNUSED_FUNCTIONS
|
|
/* #ifdef COMPILE_UNUSED_FUNCTIONS added 2019-03-31 */
|
|
/*
|
|
* 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);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* 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_c(*p) || isdigit_c(*p)))
|
|
p++;
|
|
|
|
return (p);
|
|
}
|
|
#endif /* COMPILE_UNUSED_FUNCTIONS */
|