/**********
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 "spice.h"
#include "util.h"
#include "ftedata.h"		/* For MAXDIMS */

/*
 * Create a string of the form "12,1,10".
 */
char *
dimstring( data, length )
int *data;
int length;
{
    int i;
    char buf[BSIZE_SP];

    if (!data || length < 1)
	return NULL;

    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? */
    return(buf);
}

/*
 * Create a string of the form "[12][1][10]".
 */
char *
indexstring( data, length )
int *data;
int length;
{
    int i;
    char buf[BSIZE_SP];

    if (!data || length < 1)
	return NULL;

    buf[0] = '\0';
    for (i=0; i < length; i++) {
	sprintf(buf + strlen(buf), "[%d]",  data[i]);
    }
    return(buf);
}

/*
 * Add one to an index into an array with sizes in dims.
 * Return 1 when all counters overflow at once.
 */
int
incindex(counts, numcounts, dims, numdims)
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( data, length )
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( p, data, outlength )
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( p )
char *p;
{
    if (!p)
	return NULL;

    while(*p && (*p == '[' || *p == ']' || *p == ','
	    || isspace(*p) || isdigit(*p)))
	p++;

    return(p);
}
