static char *SccsId = "@(#)prInst.c 4.15 (TU-Delft) 07/27/92";
/**********************************************************

Name/Version      : xsls/4.15

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

Author(s)         : A.J. van Genderen
Creation date     : 16-Feb-1987
Modified by       : S. de Graaf
Modification date : 08-Dec-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"

extern int out_indent;
extern int language;
extern int dialect;
extern int tog_comma;
extern int tog_pnod;
extern int tog_nnod;
extern int tog_irange;
extern int tog_nodnbr;
extern int noUnconnect;
extern int cirFlag;

extern int saveInOutBuf;

extern float vnbulk;
extern float vpbulk;
extern int vnbulkdefined;
extern int vpbulkdefined;

extern char **globNets;
extern char **globConA;
extern char **globConB;
extern int globNets_cnt;

extern char *projname ();

static int uncon_cnt;
static int r_cnt;
static int c_cnt;
static int x_cnt;
static int m_cnt;
static int f_cnt;

static char fv_ret[32];
static char fv_tmp[32];

prInst (ntw)
struct model_info *ntw;
{
    DM_STREAM *dsp;
#if NCF_RELEASE >= 400
    DM_STREAM *dsp_sim_mc;
    struct stat fsbuf;
#endif
    int i;
    int firstinode;
    int firstinst;
    int outPos ();
    int ready;
    int increment;
    int ninputs;
    char mtype;
    char str[32];
    char buf[32];
    struct cir_net tnetspace;
    struct cir_net *tnet;
    struct term_ref *tref;
    struct model_info *mod;
    struct model_info *findFunc ();
    struct model_info *findDev ();
    struct model_info *findNetw ();
    struct cir_net *findNet ();
    struct cir_net *fnet;
    struct net_ref *tnet_ref;
    struct net_ref *help;
    struct net_ref *expNet ();
    int currTermType;
    int globCon_cnt;
    int globalTerm;
    int globnet_cnt;
    int k;
    int kstop;
    int prPnod;
    int prNnod;
    int has_connect;

    uncon_cnt= 0;
    r_cnt= 0;
    c_cnt= 0;
    x_cnt= 0;
    m_cnt= 0;
    f_cnt= 0;
    globnet_cnt = 0;

    tnet = &tnetspace;
    tnet -> inst_lower = NULL;
    tnet -> inst_upper = NULL;
    tnet -> net_lower = NULL;
    tnet -> net_upper = NULL;
    tnet -> ref_lower = NULL;
    tnet -> ref_upper = NULL;

    dsp = dmOpenStream (ntw -> dkey, "mc", "r");

#if NCF_RELEASE >= 400
    if (!cirFlag && dmStat(ntw -> dkey, "sim_mc", &fsbuf) == 0)
	dsp_sim_mc = dmOpenStream (ntw -> dkey, "sim_mc", "r");
    else
	dsp_sim_mc = NULL;
#endif

    if (language == EDIF)
	oprint (0, "(contents ");

    while (dmGetDesignData (dsp, CIR_MC) > 0) {

	has_connect = 0;
	if (noUnconnect) {
	    saveInOutBuf = 1;
	}

	globCon_cnt = 0;

#if NCF_RELEASE >= 400
        mtype = 0;
	if (dsp_sim_mc) {
	    dmGetDesignData (dsp_sim_mc, CIR_SIM);
	    if (strcmp (csim.inst_name, cmc.inst_name)) {
		fatalErr ("Error in stream 'sim_mc'", NULL);
	    }

	    if (csim.flag == 'f' || csim.flag == 'b')
		mtype = 'f';
	}
	else if (is_func (&cmc)) {
	    mtype = 'f';
	}

	if (mtype == 'f') { 
#else
        if (is_func (&cmc)) {
#endif
	    mtype = 'f';			/* Function */
	    if (language != SLS && language != SIMON)
		fatalErr ("Cannot include function instances",
			  "in a not SLS description");

            ninputs = 1; /* default */
	    getAttrIntValue (cmc.inst_attribute, "n", &ninputs);
	    mod = findFunc (cmc.cell_name, (int)cmc.imported, 
			    ntw -> proj, ninputs);
	    mod -> imported = (ntw -> imported || cmc.imported);
	}
        else if ((mod = findDev (cmc.cell_name, 
			      (int)cmc.imported, ntw -> proj, 0)) == NULL) {
	    mtype = 'n';			/* Network */
	    mod = findNetw (cmc.cell_name, (int)cmc.imported, 
			    ntw -> proj, 1);
	    mod -> imported = (ntw -> imported || cmc.imported);
	}
	else {
	    mod -> imported = (ntw -> imported || cmc.imported);
	    mtype = 'd';			/* Device */
	}

        strcpy (tnet -> inst_name, cmc.inst_name);
        if (cmc.inst_dim > 0) {
	    PALLOC (tnet -> inst_lower, cmc.inst_dim, long);
	    PALLOC (tnet -> inst_upper, cmc.inst_dim, long);
	    tnet -> inst_dim = cmc.inst_dim;

	    for (i = 0; i < cmc.inst_dim; i++) {
		tnet -> inst_lower[i] =
		tnet -> inst_upper[i] = cmc.inst_lower[i];
	    }
	}
	else {
	    tnet -> inst_dim = 0;
	    tnet -> inst_lower = 
	    tnet -> inst_upper = NULL;
	}
	tnet -> ref_dim = 0;  /* this one is of no importance */

        firstinst = 1;
        ready = 0;
        while (! ready) {

	    firstinode = 1;
	    currTermType = -1;

            if (!tog_irange || firstinst) {

		if (language == SLS)
		    out_indent = 4;
		else
		    out_indent = 0;

		if (!tog_irange) {
		    prInNm (&cmc, mtype, &(mod -> prefix[0]), mod -> spec_dev,
			    tnet -> inst_lower, tnet -> inst_upper);
		}
		else if (firstinst) {
		    prInNm (&cmc, mtype, &(mod -> prefix[0]), mod -> spec_dev,
			    cmc.inst_lower, cmc.inst_upper);
		}

		if (mtype == 'f' && language == SLS) {
		    oprint (0, "@");
		    oprint (0, " ");
		}

		if (language == SLS) {
		    oprint (0, mod -> out_name);

		    prPar (&cmc, mod, mtype, 1);
		    prPar (&cmc, mod, mtype, 2);

		    oprint (0, " ");
		    oprint (0, "(");
		}

		if (language == SIMON) {
		    oprint (0, mod -> out_name);
		    oprint (0, " ");
		}

		if (language == EDIF) {
		    oprint (0, "(ViewRef ");
		    if (mtype == 'n')
			oprint (0, "VIEWNAMEDEFAULT ");
		    else if (mtype == 'd')
			oprint (0, "VIEWNAMEDEFAULT ");
		    oprint (0, "(CellRef ");
		    oprint (0, mod -> out_name);
		    if (mtype == 'd') {
			oprint (0, "(libraryRef Primitives)");
		    }
		    else if (mtype == 'n' && mod -> imported == IMPORTED) {
			oprint (0, "(libraryRef ");
#if NCF_RELEASE >= 400
			oprint (0, projname (mod -> proj -> TMPath, 0));
#else
			oprint (0, projname (mod -> proj -> dmpath, 0));
#endif
			oprint (0, ")");
		    }
		    oprint (0, ")");
		    oprint (0, ")");
		}

		out_indent = outPos ();
	    }

            if (language == EDIF) {
		prPar (&cmc, mod, mtype, 1);
	    }
	    else {

	        if (mtype == 'n' && (tog_pnod || tog_nnod)) {

		    prPnod = tog_pnod;
		    prNnod = tog_nnod;

		    for (tref = mod -> terms; 
			 tref != NULL; 
			 tref = tref -> next) {

			if (strcmp (tref -> t -> term_name, "pbulk") == 0)
			    prPnod = 0;
			if (strcmp (tref -> t -> term_name, "nbulk") == 0)
			    prNnod = 0;
		    }

		    if (prPnod) {
			if (firstinode) {
			    firstinode = 0;
			}
			else {
			    if (tog_comma)
				oprint (1, ",");
			    oprint (0, " ");
			}
		        nmprint (0, "pbulk", 0, NULL, NULL, 0, tog_nodnbr, 1);
		    }
		    if (prNnod) {
			if (firstinode) {
			    firstinode = 0;
			}
			else {
			    if (tog_comma)
				oprint (1, ",");
			    oprint (0, " ");
			}
			nmprint (0, "nbulk", 0, NULL, NULL, 0, tog_nodnbr, 1);
		    }
		}

		for (tref = mod -> terms; tref != NULL; tref = tref -> next) {

		    strcpy (tnet -> net_name, tref -> t -> term_name);
		    tnet -> net_dim = tref -> t -> term_dim;
		    tnet -> net_lower = tref -> t -> term_lower;
		    tnet -> net_upper = tref -> t -> term_upper;

		    tnet_ref = expNet (tnet); 
		    while (tnet_ref != NULL) {

			if (language == SIMON) {

			    if (tref -> type == INPUT
				|| tref -> type == INREAD) {

				if (currTermType == -1) {
				    oprint (0, "i(");
				    firstinode = 1;
				}
				currTermType = tref -> type;
			    }
			    else if (tref -> type == INOUT) {
				if (currTermType >= 0 
				    && currTermType != INOUT) {
				    oprint (0, ") ");
				}
				if (currTermType != INOUT) {
				    oprint (0, "io(");
				    firstinode = 1;
				}
				currTermType = tref -> type;
			    }
			    else if (tref -> type == OUTPUT) {
				if (currTermType >= 0 
				    && currTermType != OUTPUT) {
				    oprint (0, ") ");
				}
				if (currTermType != OUTPUT) {
				    oprint (0, "o(");
				    firstinode = 1;
				}
				currTermType = tref -> type;
			    }
			}

			if (firstinode) {
			    firstinode = 0;
			}
			else {
			    if (tog_comma)
			    oprint (1, ",");
			    oprint (0, " ");
			}

			globalTerm = 0;
			if (tref -> t -> term_dim == 0) {
			    for (i = 0; i < globNets_cnt; i++) {
				if (strcmp (globNets[i], 
					    tref -> t -> term_name) == 0) {
				    globalTerm = 1;
				    break;
				}
			    }
			}

			fnet = findNet (tnet_ref -> n);
			if (fnet == NULL) {
			    if (globalTerm) {
				nmprint (0, tref -> t -> term_name, 
					 0, NULL, NULL, 
					 0, tog_nodnbr, 1);
			    }
			    else if (language != SLS) {
				uncon_cnt++;
				sprintf (str, "xxx_%d", uncon_cnt);
				nmprint (0, str, 0, NULL, NULL, 
					 0, tog_nodnbr, 1);
			    }
			}
			else {

			    if (fnet -> net_neqv > 1) {
				has_connect = 1;
			    }

			    if (globalTerm && strcmp (tref -> t -> term_name,
					              fnet -> net_name) != 0) {
				globConA[globCon_cnt] = fnet -> net_name;
				globConB[globCon_cnt] = tref -> t -> term_name;
				globCon_cnt++;
			    }
			    nmprint (0, fnet -> net_name,
					fnet -> net_dim,
					fnet -> net_lower,
					fnet -> net_upper, 0, tog_nodnbr, 1);
			}
			
			help = tnet_ref;
			tnet_ref = tnet_ref -> next;
			FREE (help);
		    }
		}

		if (tog_pnod && mtype == 'd') {
		    if (mod -> vbulkdefined 
			&& ((mod -> spec_dev && vpbulkdefined 
					     && mod -> vbulk == vpbulk)
			    || (!mod -> spec_dev && mod -> vbulk > 0))) {

			if (tog_comma)
			    oprint (1, ",");
			oprint (1, " ");
			nmprint (0, "pbulk", 0, NULL, NULL, 0, tog_nodnbr, 0);
		    }
		}

		if (tog_nnod && mtype == 'd') {
		    if (mod -> vbulkdefined
			&& ((mod -> spec_dev && vnbulkdefined
					     && mod -> vbulk == vnbulk)
			    || (!mod -> spec_dev && mod -> vbulk <= 0))) {

			if (tog_comma)
		        oprint (1, ",");
			oprint (1, " ");
			nmprint (0, "nbulk", 0, NULL, NULL, 0, tog_nodnbr, 0);
		    }
		}

		if (language == SPICE) {
		    switch (mtype) {
			case 'n':
			    oprint (0, " ");
			    oprint (0, mod -> out_name);
			    break;
			case 'd':
			    if (strcmp (cmc.cell_name, "cap") != 0
			    && strcmp (cmc.cell_name, "res") != 0) {
				oprint (0, " ");
			        oprint (0, mod -> out_name);
			    }
			    prPar (&cmc, mod, mtype, 1);
			    prPar (&cmc, mod, mtype, 2);
			    break;
			default:
			    break;
		    }
		}
	    }

	    increment = 0;
	    for (i = cmc.inst_dim - 1; i >= 0; i--) {
		(tnet -> inst_lower[i])++;
		(tnet -> inst_upper[i])++;
		if (tnet -> inst_lower[i] <= cmc.inst_upper[i]) {
		    increment = 1;
		    break;
		}
		else {
		    tnet -> inst_lower[i] =
		    tnet -> inst_upper[i] = cmc.inst_lower[i];
		}
	    }
	    if (increment)
		ready = 0;
	    else
		ready = 1;

	    if (language == SLS) {
		if (ready || !tog_irange)
		    oprint (1, ");");
		else {
		    if (tog_comma)
			oprint (1, ",");
		}
	    }
	    if (language == SIMON) {
		oprint (1, ")");
	    }

	    if (language == EDIF) {
		if (ready || !tog_irange)
	            oprint (0, ")");
	    }
	    else
		oprint (0, "\n");

	    firstinst = 0;
	}

	cmcClean (&cmc);

	for (i = 0; i < globCon_cnt; i++) {

	    /* generate a connection between actual parameter 
	       and global net since the formal parameter is
	       a global net
	    */

	    globnet_cnt++;

            if (language == SPICE) kstop = 2;
            else kstop = 1;

	    for (k = 1; k <= kstop; k++) {
		if (language == SLS)
		    oprint (0, "net {");
		else if (language == SPICE) {
		    if (k == 1)
			sprintf (buf, "rgnet%d ", globnet_cnt);
		    else
			sprintf (buf, "vgnet%d ", globnet_cnt);
		    oprint (0, buf);
		}

		nmprint (0, globConA[i], 0, NULL, NULL, 0, tog_nodnbr, 1);

		if (tog_comma)
		    oprint (1, ",");
		oprint (0, " ");

		nmprint (0, globConB[i], 0, NULL, NULL, 0, tog_nodnbr, 1);

		if (language == SLS)
		    oprint (1, "};");
		else if (language == SPICE) {
		    if (k == 1)
			oprint (1, " 1mohm");
		    else
			oprint (1, " 0v");
                }
		oprint (1, "\n");
	    }
	}

	if (noUnconnect) {
	    saveInOutBuf = 0;
	    if (!has_connect)
		destroyOutBuf ();
	    else
		flushOutBuf ();
	}
    }

    out_indent = 0;

    FREE (tnet -> inst_lower);
    FREE (tnet -> inst_upper);

    dmCloseStream (dsp, COMPLETE);
#if NCF_RELEASE >= 400
    if (dsp_sim_mc) 
	dmCloseStream (dsp_sim_mc, COMPLETE);
#endif
}

prPar (amc, mod, mtype, pass)
struct cir_mc *amc;
struct model_info * mod;
char mtype;
int pass;        /* prPar has two passes: during the first pass parameters
                    are printed, during the second pass comment is printed  */
{
    int pr_par;
    int pr_val;
    int pr_com;
    int com_pen;
    char *attr;
    char *nextAttr ();
    char *par;
    char *val;
    float fval;
    char buf[32];
    char buf2[512];
    double atof ();
    char *fvalPar ();

    com_pen = 0;

    if (amc -> inst_attribute) {
        strcpy (buf2, amc -> inst_attribute);
        attr = &buf2[0];
    }
    else
	attr = NULL;
    while (attr != NULL ) {

	attr = nextAttr (&par, &val, attr);

	pr_par = 0;
	pr_val = 0;
	pr_com = 0;

	if (par != NULL) {

	    switch (mtype) {

		case 'f':

		    if (strcmp (par, "tr") == 0 
		     || strcmp (par, "tf") == 0) {
			pr_par = 1;
			pr_val = 1;
		    }
		    else if (strcmp (par, "n") != 0
			  && strcmp (par, "f") != 0)
			pr_com = 1;
		    break;

		case 'd':

		    if (strcmp (par, "w") == 0 
		     || strcmp (par, "l") == 0) {
			pr_par = 1;
			pr_val = 1;
			if (language == SPICE && dialect == SPICE) {
			    fval = (float)atof (val);
			    switch (par[0]) {
				case 'w':
				    fval -= mod -> dw;
				    break;
				case 'l':
				    fval -= mod -> dl;
				    break;
			    }
			    if (fval <= 0)
				fatalErr ("Non-positive effective",
					  "transistor dimension");
			    val = buf;
			    sprintf (val, "%e", fval);
			}
		    }
		    else if (strcmp (par, "v") == 0) {
			pr_val = 1;
		    }
		    else
			pr_com = 1;
		    break;

		case 'n':

#if NCF_RELEASE >= 400
		    if (strcmp (par, "f") != 0)
#endif
			pr_com = 1;

		    break;
	    }

	    if (pr_par && pass == 1) {
		if (com_pen) {
		    oprint (0, " */");
		    com_pen = 0;
		}
		oprint (0, " ");
		if (language == EDIF) {
		    oprint (0, "(parameterAssign ");
		}
		oprint (0, par);
	    }

	    if (pr_val && pass == 1) {
		if (com_pen) {
		    oprint (0, " */");
		    com_pen = 0;
		}
		if (val != NULL) {
		    if (language == EDIF) {
			oprint (0, "(number ");
		        oprint (0, fvalPar (par, val));
			oprint (0, ")");
		    }
		    else {
			if (pr_par)
			    oprint (0, "=");
			else
			    oprint (0, " ");
		        oprint (0, fvalPar (par, val));
		    }
		}
	    }

	    if (pr_par && pass == 1 && language == EDIF) {
		oprint (0, ")");
	    }

            if (pr_com && pass == 2) {
		if (!com_pen) {
                    if (language == SLS)
		        oprint (0, " /*");
                    else {
		        oprint (0, "\n");
                        startComment ();
                    }
		    com_pen = 1;
		}
		oprint (0, " ");
		oprint (0, par);
		if (val != NULL) {
		    oprint (1, "=");
		    oprint (1, val);
		}
	    }
	}
    }

    if (com_pen) {
        if (language == SLS)
	    oprint (0, " */");
        else
            endComment ();
	com_pen = 0;
    }
}

prInNm (amc, mtype, prefix, spec_dev, lower, upper)
struct cir_mc *amc;
char mtype;
char *prefix;
int spec_dev;
long *lower;
long *upper;
{
    int *acnt;
    char buf[DM_MAXNAME + 12];

    if (language == SLS) {

	if (amc -> inst_name[0] == '_' && amc -> inst_dim == 0)
	    return;

	oprint (0, "{");
	if (amc -> inst_name[0] == '_') {
	    nmprint (1, ".", amc -> inst_dim, 
		     lower, upper, tog_irange, 0, 1);
	}
	else {
	    nmprint (1, amc -> inst_name, amc -> inst_dim, 
		     lower, upper, tog_irange, 0, 1);
	}
	oprint (1, "}");
	oprint (0, " ");

	return;
    }

    switch (mtype) {
	case 'n':
	    prefix = "x";
	    acnt = &x_cnt;
	    break;
	case 'd':
            if (!spec_dev) {
	        if (strcmp (amc -> cell_name, "res") == 0) {
		    if (prefix == NULL || prefix[0] == '\0') prefix = "r";
		    acnt = &r_cnt;
	        }
	        else if (strcmp (amc -> cell_name, "cap") == 0) {
		    if (prefix == NULL || prefix[0] == '\0') prefix = "c";
		    acnt = &c_cnt;
	        }
	        else {
		    if (prefix == NULL || prefix[0] == '\0') prefix = "m";
		    acnt = &m_cnt;
	        }
            }
	    else
		acnt = &m_cnt;
	    break;
	case 'f':
	    prefix = "f";
	    acnt = &f_cnt;
	    break;
    }

    if (amc -> inst_name[0] == '_' && language != EDIF) {
	if (language == SIMON) {
	    sprintf (buf, "xxxinst%d", ++m_cnt);
	}
	else {
	    (*acnt)++;
	    if (prefix != NULL 
            && strncmp (amc -> inst_name, prefix, strlen (prefix)) != 0)
		sprintf (buf, "%s%d", prefix, *acnt);
	    else
		sprintf (buf, "%d", *acnt);
	}
    }
    else if (language == SPICE) {
        if (prefix != NULL 
        && strncmp (amc -> inst_name, prefix, strlen (prefix)) != 0)
	    sprintf (buf, "%s%s", prefix, amc -> inst_name);
	else
	    sprintf (buf, "%s", amc -> inst_name);
    }
    else {
	sprintf (buf, "%s", amc -> inst_name);
    }
       
    if (language == EDIF)
	oprint (0, "(instance ");

    nmprint (0, buf, amc -> inst_dim, lower, upper, tog_irange, 0, 1); 
    oprint (0, " ");
}

/* fvalPar prints a parameters value by using an S.I.
   scale factor if possible 
*/

char *fvalPar (par, val)
char *par;
char *val;
{
    char *pv;
    char *pr;
    char *pt;
    int ncnt;
    int mcnt;
    int pcnt;
    int exp;
    int r;
    int i;
    int negative;

    if (val[0] == '-') {
	negative = 1;
	val++;
    }
    else
	negative = 0;

    pv = val;
    pt = fv_tmp;

    ncnt = -1; /* number of digits after '.' */
    pcnt = 0;  /* precision (total number of digits) */
    while ((*pv >= '0' && *pv <= '9') || *pv == '.') {
	if (*pv == '.') {
	    ncnt = 0;
	}
	else {
	    pcnt++;
	    *pt++ = *pv;
	    if (ncnt >= 0)
		ncnt++;
	}
	pv++;
    }
    *pt = '\0';
    if (ncnt < 0) 
	ncnt = 0;

    exp = 0;
    if (*pv == 'e' || *pv == 'E') {
	if (sscanf (pv + 1, "%d", &exp) != 1)
	    exp = 0;
    }

    if (language == SPICE && dialect == ESPICE) {
        if (strcmp (par, "w") == 0 || strcmp (par, "l") == 0) {
	    exp += 6;   /* because output should be in micron (u) */
	}
    }

    if (language == EDIF) {
	if (exp != 0) {
            if (negative)
	        sprintf (fv_ret, "(e -%s %d)", fv_tmp, exp);
	    else
	        sprintf (fv_ret, "(e %s %d)", fv_tmp, exp);
	}
	else {
            if (negative)
	        sprintf (fv_ret, "-%s", fv_tmp);
	    else
	        sprintf (fv_ret, "%s", fv_tmp);
	}
	return (fv_ret);
    }

    exp = exp + (pcnt - 1) - ncnt;
       /* exp + new ncnt - old ncnt */
    ncnt = pcnt - 1;
    mcnt = 1;  /* number of digits before '.' */

    /* the requirement is: exp % 3 == 0 
			   and no zero before '.' (i.e. mcnt > 0) ! */

    if (exp > 0) {
	r = exp % 3;
	if (r != 0) {
	    if (mcnt - (3 - r) <= 0) {
		exp = exp - r;
		mcnt = mcnt + r;
	    }
	    else {
		exp = exp + (3 - r);
		mcnt = mcnt - (3 - r);
	    }
	}
    }
    else if (exp < 0) {
	r = -exp % 3;
	if (r != 0) {
	    if (mcnt - r <= 0) {
		exp = exp - (3 - r);
		mcnt = mcnt + (3 - r);
	    }
	    else {
		exp = exp + r;
		mcnt = mcnt - r;
	    }
	}
    }

    if (negative) {
	fv_ret[0] = '-';
	pr = fv_ret + 1;
    }
    else
	pr = fv_ret;

    pt = fv_tmp;
    for (i = 0; i < pcnt; i++) {
	if (i == mcnt) *pr++ = '.';
	*pr++ = *pt++;
    }
    while (i < mcnt) {
	*pr++ = '0';    /* trailing zero's */
	i++;
    }

    if (language == SPICE) {

	switch (exp) {
	    case -15:
		sprintf (pr, "f");
		break;
	    case -12:
		sprintf (pr, "p");
		break;
	    case -9:
		sprintf (pr, "n");
		break;
	    case -6:
		sprintf (pr, "u");
		break;
	    case -3:
		sprintf (pr, "m");
		break;
	    case 0:
		sprintf (pr, "");
		break;
	    case 3:
		sprintf (pr, "k");
		break;
	    case 6:
		sprintf (pr, "meg");
		break;
	    case 9:
		sprintf (pr, "g");
		break;
	    case 12:
		sprintf (pr, "t");
		break;
	    default:
		sprintf (pr, "e%d", exp);
		break;
	}
    }
    else if (language == SLS) {

	switch (exp) {
	    case -15:
		sprintf (pr, "f");
		break;
	    case -12:
		sprintf (pr, "p");
		break;
	    case -9:
		sprintf (pr, "n");
		break;
	    case -6:
		sprintf (pr, "u");
		break;
	    case -3:
		sprintf (pr, "m");
		break;
	    case 0:
		sprintf (pr, "");
		break;
	    case 3:
		sprintf (pr, "k");
		break;
	    case 6:
		sprintf (pr, "M");
		break;
	    case 9:
		sprintf (pr, "G");
		break;
	    default:
		sprintf (pr, "e%d", exp);
		break;
	}
    }
    else {
	sprintf (pr, "e%d", exp);
    }

    cutTrail0s (fv_ret);

    return (fv_ret);
}

cutTrail0s (str)
char *str;
{
    char *p;
    char *last;
    int commaPassed;
    
    if (*str == '\0')
	return;

    commaPassed = 0;
    p = str;
    last = str;
    while ((*p >= '0' && *p <= '9') || *p == '.') {
	if (*p == '.') commaPassed = 1;
	if (*p != '0' || !commaPassed) last = p;
	p++;
    }
    if (*last == '.') last--;

    if (p != last) {
	while (*p != '\0') {
	    *++last = *p++;
	}
	*++last = '\0';
    }
}

char *projname (s, definition)
char *s;
int definition;
{
    char *p;
    static char buf[164];

    p = s + strlen (s) + 1;
    while (p >= s && *p != '/') p--;
    p++;
    if (definition) {
	sprintf (buf, "(rename %s \"%s\")", p, s);
    }
    else {
	sprintf (buf, "%s", p);
    }

    return (&buf[0]);
}
