static char *SccsId = "@(#)print.c 4.9 (TU-Delft) 07/22/92";
/**********************************************************

Name/Version      : xsls/4.9

Language          : C
Operating system  : UNIX SYSTEM V
Host machine      : HP9000

Author(s)         : A.J. van Genderen
Creation date     : 16-Feb-1987
Modified by       : A.J. van Genderen
Modification date : 16-Feb-1987


        Delft University of Technology
        Department of Electrical Engineering
        Network Theory Section
        Mekelweg 4 - P.O.Box 5031
        2600 GA DELFT
        The Netherlands

        Phone : 015 - 786234

        COPYRIGHT (C) 1987 , All rights reserved
**********************************************************/
#include "incl.h"

#define  MAXLL  80      /* maximum output line length */

extern FILE *fp_out;
extern int language;
extern int tog_comma;
extern int tog_range;
extern int tog_nodnbr;
extern int tog_nobrack;
extern int tog_use0;
extern int tog_vss0;
extern int tog_gnd0;
extern char node0[];

int out_indent = 0;     /* output indent */
int out_tabstep = 8;    /* output tab step, don't make it zero ! */

int saveInOutBuf = 0;
int save2 = 0;

static char buf[200];
static int bufpos = 0;
static int buf_filled = 0;
static int cpos = 0;
static int cpos_save = 0;
static int comment = 0;

struct nametable {
    int nr;
    char *name;
};

static struct nametable *ntab = NULL;
static int ntabNr = 0;
static int ntabN = 0;
static int ntabSize = 0;

nmprint (concat, name, dim, lower, upper, pr_range, pr_nbr, definition)
int concat;   /* concat this name to the previous one */
char *name;
long dim;
long *lower;
long *upper;
int pr_range;  /* print range */
int pr_nbr;  /* print number instead of indentifier */
int definition;
{
    int i;
    char buf1[DM_MAXNAME + 132];
    char buf2[32];
    char *ps;
    struct cir_net *onet;
    struct net_ref *nref;
    struct net_ref *help;
    struct net_ref *expNet ();

    if (! tog_range && pr_range) {
	PALLOC (onet, 1, struct cir_net);
	strcpy (onet -> net_name, name);
	onet -> net_dim = dim;
	onet -> net_lower = lower;
	onet -> net_upper = upper;
	onet -> inst_dim = 0;
	onet -> ref_dim = 0;
	nref = expNet (onet);
	while (nref != NULL) {
	    help = nref;
	    nmprint (0, nref -> n -> net_name, nref -> n -> net_dim,
		     nref -> n -> net_lower, nref -> n -> net_upper, 0, pr_nbr,
		     definition);
	    if (nref -> next != NULL) {
		if (language == EDIF) {
		    oprint (0, ")");
		    oprint (0, "(port ");
		}
		else {
		    if (tog_comma)
			oprint (1, ",");
		    oprint (0, " ");
		}
	    }
	    nref = nref -> next;
	    FREE (help);
	}
	FREE (onet);
	return;
    }

    if (language == EDIF) {
        if (dim > 0) {
	    if (pr_range) {
		if (!tog_nobrack)
		    oprint (concat, "(array ");
	    }
	    else {
		if (!tog_nobrack)
                    oprint (concat, "(member ");
	    }
	    oprint (0, name);
	    for (i = 0; i < dim; i++) {

		if (pr_range && lower[i] != 0) {
		    fatalErr (
		    "Error: lower boundary unequal 0 exists in database.",
		    "Use option to expand names that are in array form.");
		}

		if (i < dim - 1 || i == 0)
		    if (!tog_nobrack)
	                oprint (0, " ");
		    else
	                oprint (0, "_");
		if (pr_range)
		    /* we must assume lower[i] == 0 */
		    sprintf (buf1, "%d", upper[i] + 1);
		else
		    sprintf (buf1, "%d", lower[i]);
		oprint (0, buf1);
	    }
	    if (!tog_nobrack)
	        oprint (0, ")");
	}
	else if ((name[0] >= '0' && name[0] <= '9') || name[0] == '_') {
	    if (definition)
	        sprintf (buf1, "(rename &%s \"%s\")", name, name);
	    else
	        sprintf (buf1, "&%s", name);
	    oprint (concat, buf1);
	}
	else
	    oprint (concat, name);
	return;
    }

    sprintf (buf1, "%s", name);
    if (dim > 0) {
	sprintf (buf1 + strlen (buf1), "[");
	for (i = 0; i < dim; i++) {
	    if (pr_range)
	        sprintf (buf1 + strlen (buf1), "%d..%d", lower[i], upper[i]);
	    else
	        sprintf (buf1 + strlen (buf1), "%d", lower[i]);
	    if (i + 1 < dim)
	        sprintf (buf1 + strlen (buf1), ",");
	}
	sprintf (buf1 + strlen (buf1), "]");
    }

    if (pr_nbr
	|| (tog_use0 && test0 (buf1) == 0)) {
	sprintf (buf2, "%d", nameNbr (buf1));
	oprint (concat, buf2);
    }
    else {
	if (tog_nobrack)
	    for (ps = buf1; *ps != '\0'; ps++) {
		if (*ps == '[' || *ps == ']' || *ps == ',') {
		    *ps = '_';
	    }
	}
	oprint (concat, buf1);
    }
}

/* nameNbr returns a number for the string 'name'
*/

int nameNbr (name)
char *name;
{
    int nr;
    
    nr = testNameNbr (name);
    
    if (nr < 0) {
        if (test0 (name) == 0)
	    return (assignNameNbr (name, 0));
        else if (tog_nodnbr)
	    return (assignNameNbr (name, -1));
    }
    else
	return (nr);
}

testNameNbr (name)
char *name;
{
    int i;

    for (i = 0; i < ntabN; i++) {
	if (strcmp (ntab[i].name, name) == 0) {
	    break;
	}
    }

    if (i == ntabN)
	return (-1);
    else
	return (ntab[i].nr);
}

test0 (name)
char *name;
{
    if (tog_use0) {
	if (tog_vss0) {
	    if ((name[0] == 'v' && name[1] == 's' && name[2] == 's')
	    || (name[0] == 'V' && name[1] == 'S' && name[2] == 'S')) {
		return (0);
	    }
	}
	if (tog_gnd0) {
	    if ((name[0] == 'g' && name[1] == 'n' && name[2] == 'd')
	    || (name[0] == 'G' && name[1] == 'N' && name[2] == 'D')) {
		return (0);
	    }
	}
	if (node0[0] != '\0') {
	    int l = strlen (node0);
	    if (strlen (name) < l)
		l = strlen (name);
	    if (strncmp (node0, name, l) == 0) {
		return (0);
	    }
	}
    }

    return (-1);
}

int assignNameNbr (name, nr)      /* name should not exist already ! */
char *name;
int nr;
{
    if (ntabN >= ntabSize) {
	if (ntabSize == 0) {
	    ntabSize = 50;
	    PALLOC (ntab, ntabSize, struct nametable);
	}
	else {
	    ntabSize = 2 * ntabSize;
	    REPALLOC (ntab, ntabSize, struct nametable);
	}
    }
    PALLOC (ntab[ntabN].name, strlen (name) + 1, char)
    strcpy (ntab[ntabN].name, name);

    if (nr < 0) nr = ++ntabNr;

    ntab[ntabN].nr = nr;

    ntabN++;

    return (nr);
}

nameNbrReset ()
{
    int i;

    for (i = 0; i < ntabN; i++) {
	FREE (ntab[i].name);
    }

    ntabN = 0;
    ntabNr = 0;
}

/* ntabprint prints the name table used by nameNbr ()
*/

ntabprint ()
{
    int nr;
    int i;
    char buf1[32];

    oprint (0, "*");
    oprint (0, "\n");
    oprint (0, "* ");

    out_indent = 3;
    out_tabstep = 15;

    for (nr = 0; nr <= ntabNr; nr++) {
	for (i = 0; i < ntabN; i++) {
	    if (ntab[i].nr == nr) {
		oprint (0, "\t");
		sprintf (buf1, "%2d", ntab[i].nr);
		oprint (0, buf1);
		oprint (1, " ");
		oprint (1, ntab[i].name);
		if (i + 1 < ntabN)
		    oprint (0, " ");
	    }
	}
    }
    oprint (0, "\n");
    oprint (0, "* ");
    oprint (0, "\n");

    out_indent = 0;
    out_tabstep = 8;
}

startComment ()
{
    switch (language) {
	case SLS :
	    oprint (0, "/*");
	    break;
	case SPICE :
	case SIMON :
	    oprint (0, "*");
	    break;
    }
}

endComment ()
{
    switch (language) {
	case SLS :
	    oprint (0, "*/");
	    oprint (0, "\n");
	    break;
	case SPICE :
	case SIMON :
	    break;
    }
}

oprint (concat, s)
int concat;
char *s;
{
    if (buf_filled) {
	if (! concat) {
	    opr (buf);     /* first, flush current contents of buffer */
	    bufpos = 0;
	}
    }
    else
	buf_filled = 1;

    sprintf (buf + bufpos, "%s", s);
    bufpos += strlen (s);

    if (concat && save2 != saveInOutBuf) {
	fprintf (stderr, "internal error: ?? oprint ??\n");
	die ();
    }
    save2 = saveInOutBuf;
}

/* outPos returns current position and flushes the buffer 
*/

int outPos ()  
{
    opr (buf);
    buf[0] = '\0';
    buf_filled = 0;
    bufpos = 0;
    save2 = saveInOutBuf;
    return (cpos);
}

/* A second output buffer 'helpBuf' with toggle 'saveInOutBuf' is provided
   for destroying some last part of the output.
*/

static char *helpBuf = NULL;
static int helpBufSize = 0;

destroyOutBuf ()
{
    if (save2) {
	buf[0] = '\0';
	buf_filled = 0;
	bufpos = 0;
    }

    helpBuf[0] = '\0';

    cpos = cpos_save;

    save2 = saveInOutBuf;
}

flushOutBuf ()
{
    opr (buf);

    buf[0] = '\0';
    buf_filled = 0;
    bufpos = 0;

    fprintf (fp_out, "%s", helpBuf);
    helpBuf[0] = '\0';

    save2 = saveInOutBuf;
}

/* opr is the lowest level print routine 
*/

static opr (s)
char *s;
{
    int len;
    int endnewline;
    int pr;
    char *ps;

    if (save2) {
	if (helpBuf == NULL) {
	    helpBufSize = 1000;
	    PALLOC (helpBuf, helpBufSize, char);
	    helpBuf[0] = '\0';
	}
	else if (strlen (helpBuf) > helpBufSize - 100) {
	    helpBufSize = helpBufSize + 1000;
	    REPALLOC (helpBuf, helpBufSize, char);
	}
    }

    if (language == EDIF) {
	opredif (s);
	return;
    }

    if (s[0] != '*') 
	while (cpos < out_indent) {
	    if (save2) sprintf (helpBuf + strlen (helpBuf), " ");
	    else fprintf (fp_out, " ");
	    cpos++;
	}

    if (s[0] == '\t') {
	while ((cpos - out_indent) % out_tabstep != 0 && cpos < MAXLL - 1) {
	    if (save2) sprintf (helpBuf + strlen (helpBuf), " ");
	    else fprintf (fp_out, " ");
	    cpos++;
	}
	s = s + 1;
    }

    len = strlen (s);
    if (len > 0 && s[len-1] == '\n') {
	len--;
	endnewline = 1;
    }
    else
	endnewline = 0;


    pr = 1;

    if (len + cpos >= MAXLL) {
	if (save2) sprintf (helpBuf + strlen (helpBuf), "\n");
	else fprintf (fp_out, "\n");
	cpos = 0;
	if (language == SPICE) {
	    if (comment) {
		if (save2) sprintf (helpBuf + strlen (helpBuf), "* ");
		else fprintf (fp_out, "* ");
	    }
	    else {
		if (save2) sprintf (helpBuf + strlen (helpBuf), "+ ");
		else fprintf (fp_out, "+ ");
	    }
	    cpos += 2;
	}
	if (language == SIMON) {
	    if (comment) {
		if (save2) sprintf (helpBuf + strlen (helpBuf), "* ");
		else fprintf (fp_out, "* ");
	    }
	    else {
		if (save2) sprintf (helpBuf + strlen (helpBuf), "# ");
		else fprintf (fp_out, "# ");
	    }
	    cpos += 2;
	}
	while (cpos < out_indent) {
	    if (save2) sprintf (helpBuf + strlen (helpBuf), " ");
	    else fprintf (fp_out, " ");
	    cpos++;
	}
	ps = s;
	while (*ps == ' ')
	    ps++;
	if (*ps == '\0')
	    pr = 0;
    }

    if (language == SPICE || language == SIMON) {
	if (cpos == 0 && s[0] == '*')
	    comment = 1;
	if (endnewline)
	    comment = 0;
    }

    if (pr) {
	if (save2) sprintf (helpBuf + strlen (helpBuf), "%s", s);
	else fprintf (fp_out, "%s", s);
    }

    if (endnewline)
	cpos = 0;
    else
	cpos += len;

    if (!save2)
	cpos_save = cpos;
}

static opredif (str)
char   *str;
{
    char    c;
    static int  i = -1,
                n = 0,
                s = 0;

    while ((c = *str++) != NULL) {
	if (c == '\t')
	    c = ' ';
	if (c == '(') {
	    i++;
	    s = 1;
	}
	if (c == ')') {
	    i--;
	    s = 0;
	}
	if (c == '\n')
	    continue;
	if (c == '(') {
	    if (save2) sprintf (helpBuf + strlen (helpBuf), "\n");
	    else fprintf (fp_out, "\n");
	    for (n = 0; n < i; n++) {
		if (save2) sprintf (helpBuf + strlen (helpBuf), "  ");
		else fprintf (fp_out, "  ");
	    }
	}
	if (c == ' ' && s == 1) {
	    if (save2) sprintf (helpBuf + strlen (helpBuf), "%c", c);
	    else fprintf (fp_out, "%c", c);
	}
	if (c != ' ') {
	    if (save2) sprintf (helpBuf + strlen (helpBuf), "%c", c);
	    else fprintf (fp_out, "%c", c);
	}
	if (i < -1) {
	    if (save2) sprintf (helpBuf + strlen (helpBuf), "\n");
	    else fprintf (fp_out, "\n");
	}
    }
}

