1037 lines
		
	
	
	
		
			23 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			1037 lines
		
	
	
	
		
			23 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /****************************************************************
 | |
| Copyright 1990 by AT&T Bell Laboratories and Bellcore.
 | |
| 
 | |
| Permission to use, copy, modify, and distribute this software
 | |
| and its documentation for any purpose and without fee is hereby
 | |
| granted, provided that the above copyright notice appear in all
 | |
| copies and that both that the copyright notice and this
 | |
| permission notice and warranty disclaimer appear in supporting
 | |
| documentation, and that the names of AT&T Bell Laboratories or
 | |
| Bellcore or any of their entities not be used in advertising or
 | |
| publicity pertaining to distribution of the software without
 | |
| specific, written prior permission.
 | |
| 
 | |
| AT&T and Bellcore disclaim all warranties with regard to this
 | |
| software, including all implied warranties of merchantability
 | |
| and fitness.  In no event shall AT&T or Bellcore be liable for
 | |
| any special, indirect or consequential damages or any damages
 | |
| whatsoever resulting from loss of use, data or profits, whether
 | |
| in an action of contract, negligence or other tortious action,
 | |
| arising out of or in connection with the use or performance of
 | |
| this software.
 | |
| ****************************************************************/
 | |
| 
 | |
| #include "defs.h"
 | |
| #include "output.h"
 | |
| #include "names.h"
 | |
| #include "format.h"
 | |
| 
 | |
| #define MAX_INIT_LINE 100
 | |
| #define NAME_MAX 64
 | |
| 
 | |
| static int memno2info();
 | |
| 
 | |
| extern char *initbname;
 | |
| extern void def_start();
 | |
| 
 | |
| void list_init_data(Infile, Inname, outfile)
 | |
|  FILE **Infile, *outfile;
 | |
|  char *Inname;
 | |
| {
 | |
|     FILE *sortfp;
 | |
|     int status;
 | |
| 
 | |
|     fclose(*Infile);
 | |
|     *Infile = 0;
 | |
| 
 | |
|     if (status = dsort(Inname, sortfname))
 | |
| 	fatali ("sort failed, status %d", status);
 | |
| 
 | |
|     scrub(Inname); /* optionally unlink Inname */
 | |
| 
 | |
|     if ((sortfp = fopen(sortfname, textread)) == NULL)
 | |
| 	Fatal("Couldn't open sorted initialization data");
 | |
| 
 | |
|     do_init_data(outfile, sortfp);
 | |
|     fclose(sortfp);
 | |
|     scrub(sortfname);
 | |
| 
 | |
| /* Insert a blank line after any initialized data */
 | |
| 
 | |
| 	nice_printf (outfile, "\n");
 | |
| 
 | |
|     if (debugflag && infname)
 | |
| 	 /* don't back block data file up -- it won't be overwritten */
 | |
| 	backup(initfname, initbname);
 | |
| } /* list_init_data */
 | |
| 
 | |
| 
 | |
| 
 | |
| /* do_init_data -- returns YES when at least one declaration has been
 | |
|    written */
 | |
| 
 | |
| int do_init_data(outfile, infile)
 | |
| FILE *outfile, *infile;
 | |
| {
 | |
|     char varname[NAME_MAX], ovarname[NAME_MAX];
 | |
|     ftnint offset;
 | |
|     ftnint type;
 | |
|     int vargroup;	/* 0 --> init, 1 --> equiv, 2 --> common */
 | |
|     int did_one = 0;		/* True when one has been output */
 | |
|     chainp values = CHNULL;	/* Actual data values */
 | |
|     int keepit = 0;
 | |
|     Namep np;
 | |
| 
 | |
|     ovarname[0] = '\0';
 | |
| 
 | |
|     while (rdname (infile, &vargroup, varname) && rdlong (infile, &offset)
 | |
| 	    && rdlong (infile, &type)) {
 | |
| 	if (strcmp (varname, ovarname)) {
 | |
| 
 | |
| 	/* If this is a new variable name, the old initialization has been
 | |
| 	   completed */
 | |
| 
 | |
| 		wr_one_init(outfile, ovarname, &values, keepit);
 | |
| 
 | |
| 		strcpy (ovarname, varname);
 | |
| 		values = CHNULL;
 | |
| 		if (vargroup == 0) {
 | |
| 			if (memno2info(atoi(varname+2), &np)) {
 | |
| 				if (((Addrp)np)->uname_tag != UNAM_NAME) {
 | |
| 					err("do_init_data: expected NAME");
 | |
| 					goto Keep;
 | |
| 					}
 | |
| 				np = ((Addrp)np)->user.name;
 | |
| 				}
 | |
| 			if (!(keepit = np->visused) && !np->vimpldovar)
 | |
| 				warn1("local variable %s never used",
 | |
| 					np->fvarname);
 | |
| 			}
 | |
| 		else {
 | |
|  Keep:
 | |
| 			keepit = 1;
 | |
| 			}
 | |
| 		if (keepit && !did_one) {
 | |
| 			nice_printf (outfile, "/* Initialized data */\n\n");
 | |
| 			did_one = YES;
 | |
| 			}
 | |
| 	} /* if strcmp */
 | |
| 
 | |
| 	values = mkchain((char *)data_value(infile, offset, (int)type), values);
 | |
|     } /* while */
 | |
| 
 | |
| /* Write out the last declaration */
 | |
| 
 | |
|     wr_one_init (outfile, ovarname, &values, keepit);
 | |
| 
 | |
|     return did_one;
 | |
| } /* do_init_data */
 | |
| 
 | |
| 
 | |
|  ftnint
 | |
| wr_char_len(outfile, dimp, n, extra1)
 | |
|  FILE *outfile;
 | |
|  int n;
 | |
|  struct Dimblock *dimp;
 | |
|  int extra1;
 | |
| {
 | |
| 	int i, nd;
 | |
| 	expptr e;
 | |
| 	ftnint rv;
 | |
| 
 | |
| 	if (!dimp) {
 | |
| 		nice_printf (outfile, extra1 ? "[%d+1]" : "[%d]", n);
 | |
| 		return n + extra1;
 | |
| 		}
 | |
| 	nice_printf(outfile, "[%d", n);
 | |
| 	nd = dimp->ndim;
 | |
| 	rv = n;
 | |
| 	for(i = 0; i < nd; i++) {
 | |
| 		e = dimp->dims[i].dimsize;
 | |
| 		if (!ISICON (e))
 | |
| 			err ("wr_char_len:  nonconstant array size");
 | |
| 		else {
 | |
| 			nice_printf(outfile, "*%ld", e->constblock.Const.ci);
 | |
| 			rv *= e->constblock.Const.ci;
 | |
| 			}
 | |
| 		}
 | |
| 	/* extra1 allows for stupid C compilers that complain about
 | |
| 	 * too many initializers in
 | |
| 	 *	char x[2] = "ab";
 | |
| 	 */
 | |
| 	nice_printf(outfile, extra1 ? "+1]" : "]");
 | |
| 	return extra1 ? rv+1 : rv;
 | |
| 	}
 | |
| 
 | |
|  static int ch_ar_dim = -1; /* length of each element of char string array */
 | |
|  static int eqvmemno;	/* kludge */
 | |
| 
 | |
|  static void
 | |
| write_char_init(outfile, Values, namep)
 | |
|  FILE *outfile;
 | |
|  chainp *Values;
 | |
|  Namep namep;
 | |
| {
 | |
| 	struct Equivblock *eqv;
 | |
| 	long size;
 | |
| 	struct Dimblock *dimp;
 | |
| 	int i, nd, type;
 | |
| 	expptr ds;
 | |
| 
 | |
| 	if (!namep)
 | |
| 		return;
 | |
| 	if(nequiv >= maxequiv)
 | |
| 		many("equivalences", 'q', maxequiv);
 | |
| 	eqv = &eqvclass[nequiv];
 | |
| 	eqv->eqvbottom = 0;
 | |
| 	type = namep->vtype;
 | |
| 	size = type == TYCHAR
 | |
| 		? namep->vleng->constblock.Const.ci
 | |
| 		: typesize[type];
 | |
| 	if (dimp = namep->vdim)
 | |
| 		for(i = 0, nd = dimp->ndim; i < nd; i++) {
 | |
| 			ds = dimp->dims[i].dimsize;
 | |
| 			if (!ISICON(ds))
 | |
| 				err("write_char_values: nonconstant array size");
 | |
| 			else
 | |
| 				size *= ds->constblock.Const.ci;
 | |
| 			}
 | |
| 	*Values = revchain(*Values);
 | |
| 	eqv->eqvtop = size;
 | |
| 	eqvmemno = ++lastvarno;
 | |
| 	eqv->eqvtype = type;
 | |
| 	wr_equiv_init(outfile, nequiv, Values, 0);
 | |
| 	def_start(outfile, namep->cvarname, CNULL, "");
 | |
| 	if (type == TYCHAR)
 | |
| 		ind_printf(0, outfile, "((char *)&equiv_%d)\n\n", eqvmemno);
 | |
| 	else
 | |
| 		ind_printf(0, outfile, dimp
 | |
| 			? "((%s *)&equiv_%d)\n\n" : "(*(%s *)&equiv_%d)\n\n",
 | |
| 			c_type_decl(type,0), eqvmemno);
 | |
| 	}
 | |
| 
 | |
| /* wr_one_init -- outputs the initialization of the variable pointed to
 | |
|    by   info.   When   is_addr   is true,   info   is an Addrp; otherwise,
 | |
|    treat it as a Namep */
 | |
| 
 | |
| void wr_one_init (outfile, varname, Values, keepit)
 | |
| FILE *outfile;
 | |
| char *varname;
 | |
| chainp *Values;
 | |
| int keepit;
 | |
| {
 | |
|     static int memno;
 | |
|     static union {
 | |
| 	Namep name;
 | |
| 	Addrp addr;
 | |
|     } info;
 | |
|     Namep namep;
 | |
|     int is_addr, size, type;
 | |
|     ftnint last, loc;
 | |
|     int is_scalar = 0;
 | |
|     char *array_comment = NULL, *name;
 | |
|     chainp cp, values;
 | |
|     extern char datachar[];
 | |
|     static int e1[3] = {1, 0, 1};
 | |
|     ftnint x;
 | |
|     extern int hsize;
 | |
| 
 | |
|     if (!keepit)
 | |
| 	goto done;
 | |
|     if (varname == NULL || varname[1] != '.')
 | |
| 	goto badvar;
 | |
| 
 | |
| /* Get back to a meaningful representation; find the given   memno in one
 | |
|    of the appropriate tables (user-generated variables in the hash table,
 | |
|    system-generated variables in a separate list */
 | |
| 
 | |
|     memno = atoi(varname + 2);
 | |
|     switch(varname[0]) {
 | |
| 	case 'q':
 | |
| 		/* Must subtract eqvstart when the source file
 | |
| 		 * contains more than one procedure.
 | |
| 		 */
 | |
| 		wr_equiv_init(outfile, eqvmemno = memno - eqvstart, Values, 0);
 | |
| 		goto done;
 | |
| 	case 'Q':
 | |
| 		/* COMMON initialization (BLOCK DATA) */
 | |
| 		wr_equiv_init(outfile, memno, Values, 1);
 | |
| 		goto done;
 | |
| 	case 'v':
 | |
| 		break;
 | |
| 	default:
 | |
|  badvar:
 | |
| 		errstr("wr_one_init:  unknown variable name '%s'", varname);
 | |
| 		goto done;
 | |
| 	}
 | |
| 
 | |
|     is_addr = memno2info (memno, &info.name);
 | |
|     if (info.name == (Namep) NULL) {
 | |
| 	err ("wr_one_init -- unknown variable");
 | |
| 	return;
 | |
| 	}
 | |
|     if (is_addr) {
 | |
| 	if (info.addr -> uname_tag != UNAM_NAME) {
 | |
| 	    erri ("wr_one_init -- couldn't get name pointer; tag is %d",
 | |
| 		    info.addr -> uname_tag);
 | |
| 	    namep = (Namep) NULL;
 | |
| 	    nice_printf (outfile, " /* bad init data */");
 | |
| 	} else
 | |
| 	    namep = info.addr -> user.name;
 | |
|     } else
 | |
| 	namep = info.name;
 | |
| 
 | |
| 	/* check for character initialization */
 | |
| 
 | |
|     *Values = values = revchain(*Values);
 | |
|     type = info.name->vtype;
 | |
|     if (type == TYCHAR) {
 | |
| 	for(last = 0; values; values = values->nextp) {
 | |
| 		cp = (chainp)values->datap;
 | |
| 		loc = (ftnint)cp->datap;
 | |
| 		if (loc > last) {
 | |
| 			write_char_init(outfile, Values, namep);
 | |
| 			goto done;
 | |
| 			}
 | |
| 		last = (int)cp->nextp->datap == TYBLANK
 | |
| 			? loc + (int)cp->nextp->nextp->datap
 | |
| 			: loc + 1;
 | |
| 		}
 | |
| 	if (halign && info.name->tag == TNAME) {
 | |
| 		nice_printf(outfile, "static struct { %s fill; char val",
 | |
| 			halign);
 | |
| 		x = wr_char_len(outfile, namep->vdim, ch_ar_dim =
 | |
| 			info.name -> vleng -> constblock.Const.ci, 1);
 | |
| 		if (x %= hsize)
 | |
| 			nice_printf(outfile, "; char fill2[%ld]", hsize - x);
 | |
| 		name = info.name->cvarname;
 | |
| 		nice_printf(outfile, "; } %s_st = { 0,", name);
 | |
| 		wr_output_values(outfile, namep, *Values);
 | |
| 		nice_printf(outfile, " };\n");
 | |
| 		ch_ar_dim = -1;
 | |
| 		def_start(outfile, name, CNULL, name);
 | |
| 		ind_printf(0, outfile, "_st.val\n");
 | |
| 		goto done;
 | |
| 		}
 | |
| 	}
 | |
|     else {
 | |
| 	size = typesize[type];
 | |
| 	loc = 0;
 | |
| 	for(; values; values = values->nextp) {
 | |
| 		if ((int)((chainp)values->datap)->nextp->datap == TYCHAR) {
 | |
| 			write_char_init(outfile, Values, namep);
 | |
| 			goto done;
 | |
| 			}
 | |
| 		last = ((long) ((chainp) values->datap)->datap) / size;
 | |
| 		if (last - loc > 4) {
 | |
| 			write_char_init(outfile, Values, namep);
 | |
| 			goto done;
 | |
| 			}
 | |
| 		loc = last;
 | |
| 		}
 | |
| 	}
 | |
|     values = *Values;
 | |
| 
 | |
|     nice_printf (outfile, "static %s ", c_type_decl (type, 0));
 | |
| 
 | |
|     if (is_addr)
 | |
| 	write_nv_ident (outfile, info.addr);
 | |
|     else
 | |
| 	out_name (outfile, info.name);
 | |
| 
 | |
|     if (namep)
 | |
| 	is_scalar = namep -> vdim == (struct Dimblock *) NULL;
 | |
| 
 | |
|     if (namep && !is_scalar)
 | |
| 	array_comment = type == TYCHAR
 | |
| 		? 0 : wr_ardecls(outfile, namep->vdim, 1L);
 | |
| 
 | |
|     if (type == TYCHAR)
 | |
| 	if (ISICON (info.name -> vleng))
 | |
| 
 | |
| /* We'll make single strings one character longer, so that we can use the
 | |
|    standard C initialization.  All this does is pad an extra zero onto the
 | |
|    end of the string */
 | |
| 		wr_char_len(outfile, namep->vdim, ch_ar_dim =
 | |
| 			info.name -> vleng -> constblock.Const.ci, e1[Ansi]);
 | |
| 	else
 | |
| 		err ("variable length character initialization");
 | |
| 
 | |
|     if (array_comment)
 | |
| 	nice_printf (outfile, "%s", array_comment);
 | |
| 
 | |
|     nice_printf (outfile, " = ");
 | |
|     wr_output_values (outfile, namep, values);
 | |
|     ch_ar_dim = -1;
 | |
|     nice_printf (outfile, ";\n");
 | |
|  done:
 | |
|     frchain(Values);
 | |
| } /* wr_one_init */
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| chainp data_value (infile, offset, type)
 | |
| FILE *infile;
 | |
| ftnint offset;
 | |
| int type;
 | |
| {
 | |
|     char line[MAX_INIT_LINE + 1], *pointer;
 | |
|     chainp vals, prev_val;
 | |
|     long atol();
 | |
|     char *newval;
 | |
| 
 | |
|     if (fgets (line, MAX_INIT_LINE, infile) == NULL) {
 | |
| 	err ("data_value:  error reading from intermediate file");
 | |
| 	return CHNULL;
 | |
|     } /* if fgets */
 | |
| 
 | |
| /* Get rid of the trailing newline */
 | |
| 
 | |
|     if (line[0])
 | |
| 	line[strlen (line) - 1] = '\0';
 | |
| 
 | |
| #define iswhite(x) (isspace (x) || (x) == ',')
 | |
| 
 | |
|     pointer = line;
 | |
|     prev_val = vals = CHNULL;
 | |
| 
 | |
|     while (*pointer) {
 | |
| 	register char *end_ptr, old_val;
 | |
| 
 | |
| /* Move   pointer   to the start of the next word */
 | |
| 
 | |
| 	while (*pointer && iswhite (*pointer))
 | |
| 	    pointer++;
 | |
| 	if (*pointer == '\0')
 | |
| 	    break;
 | |
| 
 | |
| /* Move   end_ptr   to the end of the current word */
 | |
| 
 | |
| 	for (end_ptr = pointer + 1; *end_ptr && !iswhite (*end_ptr);
 | |
| 		end_ptr++)
 | |
| 	    ;
 | |
| 
 | |
| 	old_val = *end_ptr;
 | |
| 	*end_ptr = '\0';
 | |
| 
 | |
| /* Add this value to the end of the list */
 | |
| 
 | |
| 	if (ONEOF(type, MSKREAL|MSKCOMPLEX))
 | |
| 		newval = cpstring(pointer);
 | |
| 	else
 | |
| 		newval = (char *)atol(pointer);
 | |
| 	if (vals) {
 | |
| 	    prev_val->nextp = mkchain(newval, CHNULL);
 | |
| 	    prev_val = prev_val -> nextp;
 | |
| 	} else
 | |
| 	    prev_val = vals = mkchain(newval, CHNULL);
 | |
| 	*end_ptr = old_val;
 | |
| 	pointer = end_ptr;
 | |
|     } /* while *pointer */
 | |
| 
 | |
|     return mkchain((char *)offset, mkchain((char *)type, vals));
 | |
| } /* data_value */
 | |
| 
 | |
|  static void
 | |
| overlapping()
 | |
| {
 | |
| 	extern char *filename0;
 | |
| 	static int warned = 0;
 | |
| 
 | |
| 	if (warned)
 | |
| 		return;
 | |
| 	warned = 1;
 | |
| 
 | |
| 	fprintf(stderr, "Error");
 | |
| 	if (filename0)
 | |
| 		fprintf(stderr, " in file %s", filename0);
 | |
| 	fprintf(stderr, ": overlapping initializations\n");
 | |
| 	nerr++;
 | |
| 	}
 | |
| 
 | |
|  static void make_one_const();
 | |
|  static long charlen;
 | |
| 
 | |
| void wr_output_values (outfile, namep, values)
 | |
| FILE *outfile;
 | |
| Namep namep;
 | |
| chainp values;
 | |
| {
 | |
| 	int type = TYUNKNOWN;
 | |
| 	struct Constblock Const;
 | |
| 	static expptr Vlen;
 | |
| 
 | |
| 	if (namep)
 | |
| 		type = namep -> vtype;
 | |
| 
 | |
| /* Handle array initializations away from scalars */
 | |
| 
 | |
| 	if (namep && namep -> vdim)
 | |
| 		wr_array_init (outfile, namep -> vtype, values);
 | |
| 
 | |
| 	else if (values->nextp && type != TYCHAR)
 | |
| 		overlapping();
 | |
| 
 | |
| 	else {
 | |
| 		make_one_const(type, &Const.Const, values);
 | |
| 		Const.vtype = type;
 | |
| 		Const.vstg = ONEOF(type, MSKREAL|MSKCOMPLEX);
 | |
| 		if (type== TYCHAR) {
 | |
| 			if (!Vlen)
 | |
| 				Vlen = ICON(0);
 | |
| 			Const.vleng = Vlen;
 | |
| 			Vlen->constblock.Const.ci = charlen;
 | |
| 			out_const (outfile, &Const);
 | |
| 			free (Const.Const.ccp);
 | |
| 			}
 | |
| 		else
 | |
| 			out_const (outfile, &Const);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 
 | |
| wr_array_init (outfile, type, values)
 | |
| FILE *outfile;
 | |
| int type;
 | |
| chainp values;
 | |
| {
 | |
|     int size = typesize[type];
 | |
|     long index, main_index = 0;
 | |
|     int k;
 | |
| 
 | |
|     if (type == TYCHAR) {
 | |
| 	nice_printf(outfile, "\"");
 | |
| 	k = 0;
 | |
| 	if (Ansi != 1)
 | |
| 		ch_ar_dim = -1;
 | |
| 	}
 | |
|     else
 | |
| 	nice_printf (outfile, "{ ");
 | |
|     while (values) {
 | |
| 	struct Constblock Const;
 | |
| 
 | |
| 	index = ((long) ((chainp) values->datap)->datap) / size;
 | |
| 	while (index > main_index) {
 | |
| 
 | |
| /* Fill with zeros.  The structure shorthand works because the compiler
 | |
|    will expand the "0" in braces to fill the size of the entire structure
 | |
|    */
 | |
| 
 | |
| 	    switch (type) {
 | |
| 	        case TYREAL:
 | |
| 		case TYDREAL:
 | |
| 		    nice_printf (outfile, "0.0,");
 | |
| 		    break;
 | |
| 		case TYCOMPLEX:
 | |
| 		case TYDCOMPLEX:
 | |
| 		    nice_printf (outfile, "{0},");
 | |
| 		    break;
 | |
| 		case TYCHAR:
 | |
| 			nice_printf(outfile, " ");
 | |
| 			break;
 | |
| 		default:
 | |
| 		    nice_printf (outfile, "0,");
 | |
| 		    break;
 | |
| 	    } /* switch */
 | |
| 	    main_index++;
 | |
| 	} /* while index > main_index */
 | |
| 
 | |
| 	if (index < main_index)
 | |
| 		overlapping();
 | |
| 	else switch (type) {
 | |
| 	    case TYCHAR:
 | |
| 		{ int this_char;
 | |
| 
 | |
| 		if (k == ch_ar_dim) {
 | |
| 			nice_printf(outfile, "\" \"");
 | |
| 			k = 0;
 | |
| 			}
 | |
| 		this_char = (int) ((chainp) values->datap)->
 | |
| 				nextp->nextp->datap;
 | |
| 		if ((int)((chainp)values->datap)->nextp->datap == TYBLANK) {
 | |
| 			main_index += this_char;
 | |
| 			k += this_char;
 | |
| 			while(--this_char >= 0)
 | |
| 				nice_printf(outfile, " ");
 | |
| 			values = values -> nextp;
 | |
| 			continue;
 | |
| 			}
 | |
| 		nice_printf(outfile, str_fmt[this_char], this_char);
 | |
| 		k++;
 | |
| 		} /* case TYCHAR */
 | |
| 	        break;
 | |
| 
 | |
| 	    case TYSHORT:
 | |
| 	    case TYLONG:
 | |
| 	    case TYREAL:
 | |
| 	    case TYDREAL:
 | |
| 	    case TYLOGICAL:
 | |
| 	    case TYCOMPLEX:
 | |
| 	    case TYDCOMPLEX:
 | |
| 		make_one_const(type, &Const.Const, values);
 | |
| 		Const.vtype = type;
 | |
| 		Const.vstg = ONEOF(type, MSKREAL|MSKCOMPLEX);
 | |
| 		out_const(outfile, &Const);
 | |
| 	        break;
 | |
| 	    default:
 | |
| 	        erri("wr_array_init: bad type '%d'", type);
 | |
| 	        break;
 | |
| 	} /* switch */
 | |
| 	values = values->nextp;
 | |
| 
 | |
| 	main_index++;
 | |
| 	if (values && type != TYCHAR)
 | |
| 	    nice_printf (outfile, ",");
 | |
|     } /* while values */
 | |
| 
 | |
|     if (type == TYCHAR) {
 | |
| 	nice_printf(outfile, "\"");
 | |
| 	}
 | |
|     else
 | |
| 	nice_printf (outfile, " }");
 | |
| } /* wr_array_init */
 | |
| 
 | |
| 
 | |
|  static void
 | |
| make_one_const(type, storage, values)
 | |
|  int type;
 | |
|  union Constant *storage;
 | |
|  chainp values;
 | |
| {
 | |
|     union Constant *Const;
 | |
|     register char **L;
 | |
| 
 | |
|     if (type == TYCHAR) {
 | |
| 	char *str, *str_ptr;
 | |
| 	chainp v, prev;
 | |
| 	int b = 0, k, main_index = 0;
 | |
| 
 | |
| /* Find the max length of init string, by finding the highest offset
 | |
|    value stored in the list of initial values */
 | |
| 
 | |
| 	for(k = 1, prev = CHNULL, v = values; v; prev = v, v = v->nextp)
 | |
| 	    ;
 | |
| 	if (prev != CHNULL)
 | |
| 	    k = ((int) (((chainp) prev->datap)->datap)) + 2;
 | |
| 		/* + 2 above for null char at end */
 | |
| 	str = Alloc (k);
 | |
| 	for (str_ptr = str; values; str_ptr++) {
 | |
| 	    int index = (int) (((chainp) values->datap)->datap);
 | |
| 
 | |
| 	    if (index < main_index)
 | |
| 		overlapping();
 | |
| 	    while (index > main_index++)
 | |
| 		*str_ptr++ = ' ';
 | |
| 
 | |
| 		k = (int) (((chainp) values->datap)->nextp->nextp->datap);
 | |
| 		if ((int)((chainp)values->datap)->nextp->datap == TYBLANK) {
 | |
| 			b = k;
 | |
| 			break;
 | |
| 			}
 | |
| 		*str_ptr = k;
 | |
| 		values = values -> nextp;
 | |
| 	} /* for str_ptr */
 | |
| 	*str_ptr = '\0';
 | |
| 	Const = storage;
 | |
| 	Const -> ccp = str;
 | |
| 	Const -> ccp1.blanks = b;
 | |
| 	charlen = str_ptr - str;
 | |
|     } else {
 | |
| 	int i = 0;
 | |
| 	chainp vals;
 | |
| 
 | |
| 	vals = ((chainp)values->datap)->nextp->nextp;
 | |
| 	if (vals) {
 | |
| 		L = (char **)storage;
 | |
| 		do L[i++] = vals->datap;
 | |
| 			while(vals = vals->nextp);
 | |
| 		}
 | |
| 
 | |
|     } /* else */
 | |
| 
 | |
| } /* make_one_const */
 | |
| 
 | |
| 
 | |
| 
 | |
| rdname (infile, vargroupp, name)
 | |
| FILE *infile;
 | |
| int *vargroupp;
 | |
| char *name;
 | |
| {
 | |
|     register int i, c;
 | |
| 
 | |
|     c = getc (infile);
 | |
| 
 | |
|     if (feof (infile))
 | |
| 	return NO;
 | |
| 
 | |
|     *vargroupp = c - '0';
 | |
|     for (i = 1;; i++) {
 | |
| 	if (i >= NAME_MAX)
 | |
| 		Fatal("rdname: oversize name");
 | |
| 	c = getc (infile);
 | |
| 	if (feof (infile))
 | |
| 	    return NO;
 | |
| 	if (c == '\t')
 | |
| 		break;
 | |
| 	*name++ = c;
 | |
|     }
 | |
|     *name = 0;
 | |
|     return YES;
 | |
| } /* rdname */
 | |
| 
 | |
| rdlong (infile, n)
 | |
| FILE *infile;
 | |
| ftnint *n;
 | |
| {
 | |
|     register int c;
 | |
| 
 | |
|     for (c = getc (infile); !feof (infile) && isspace (c); c = getc (infile))
 | |
| 	;
 | |
| 
 | |
|     if (feof (infile))
 | |
| 	return NO;
 | |
| 
 | |
|     for (*n = 0; isdigit (c); c = getc (infile))
 | |
| 	*n = 10 * (*n) + c - '0';
 | |
|     return YES;
 | |
| } /* rdlong */
 | |
| 
 | |
| 
 | |
|  static int
 | |
| memno2info (memno, info)
 | |
|  int memno;
 | |
|  Namep *info;
 | |
| {
 | |
|     chainp this_var;
 | |
|     extern chainp new_vars;
 | |
|     extern struct Hashentry *hashtab, *lasthash;
 | |
|     struct Hashentry *entry;
 | |
| 
 | |
|     for (this_var = new_vars; this_var; this_var = this_var -> nextp) {
 | |
| 	Addrp var = (Addrp) this_var->datap;
 | |
| 
 | |
| 	if (var == (Addrp) NULL)
 | |
| 	    Fatal("memno2info:  null variable");
 | |
| 	else if (var -> tag != TADDR)
 | |
| 	    Fatal("memno2info:  bad tag");
 | |
| 	if (memno == var -> memno) {
 | |
| 	    *info = (Namep) var;
 | |
| 	    return 1;
 | |
| 	} /* if memno == var -> memno */
 | |
|     } /* for this_var = new_vars */
 | |
| 
 | |
|     for (entry = hashtab; entry < lasthash; ++entry) {
 | |
| 	Namep var = entry -> varp;
 | |
| 
 | |
| 	if (var && var -> vardesc.varno == memno && var -> vstg == STGINIT) {
 | |
| 	    *info = (Namep) var;
 | |
| 	    return 0;
 | |
| 	} /* if entry -> vardesc.varno == memno */
 | |
|     } /* for entry = hashtab */
 | |
| 
 | |
|     Fatal("memno2info:  couldn't find memno");
 | |
|     return 0;
 | |
| } /* memno2info */
 | |
| 
 | |
|  static chainp
 | |
| do_string(outfile, v, nloc)
 | |
|  FILEP outfile;
 | |
|  register chainp v;
 | |
|  ftnint *nloc;
 | |
| {
 | |
| 	register chainp cp, v0;
 | |
| 	ftnint dloc, k, loc;
 | |
| 	unsigned long uk;
 | |
| 	char buf[8], *comma;
 | |
| 
 | |
| 	nice_printf(outfile, "{");
 | |
| 	cp = (chainp)v->datap;
 | |
| 	loc = (ftnint)cp->datap;
 | |
| 	comma = "";
 | |
| 	for(v0 = v;;) {
 | |
| 		switch((int)cp->nextp->datap) {
 | |
| 			case TYBLANK:
 | |
| 				k = (ftnint)cp->nextp->nextp->datap;
 | |
| 				loc += k;
 | |
| 				while(--k >= 0) {
 | |
| 					nice_printf(outfile, "%s' '", comma);
 | |
| 					comma = ", ";
 | |
| 					}
 | |
| 				break;
 | |
| 			case TYCHAR:
 | |
| 				uk = (ftnint)cp->nextp->nextp->datap;
 | |
| 				sprintf(buf, chr_fmt[uk], uk);
 | |
| 				nice_printf(outfile, "%s'%s'", comma, buf);
 | |
| 				comma = ", ";
 | |
| 				loc++;
 | |
| 				break;
 | |
| 			default:
 | |
| 				goto done;
 | |
| 			}
 | |
| 		v0 = v;
 | |
| 		if (!(v = v->nextp))
 | |
| 			break;
 | |
| 		cp = (chainp)v->datap;
 | |
| 		dloc = (ftnint)cp->datap;
 | |
| 		if (loc != dloc)
 | |
| 			break;
 | |
| 		}
 | |
|  done:
 | |
| 	nice_printf(outfile, "}");
 | |
| 	*nloc = loc;
 | |
| 	return v0;
 | |
| 	}
 | |
| 
 | |
|  static chainp
 | |
| Ado_string(outfile, v, nloc)
 | |
|  FILEP outfile;
 | |
|  register chainp v;
 | |
|  ftnint *nloc;
 | |
| {
 | |
| 	register chainp cp, v0;
 | |
| 	ftnint dloc, k, loc;
 | |
| 
 | |
| 	nice_printf(outfile, "\"");
 | |
| 	cp = (chainp)v->datap;
 | |
| 	loc = (ftnint)cp->datap;
 | |
| 	for(v0 = v;;) {
 | |
| 		switch((int)cp->nextp->datap) {
 | |
| 			case TYBLANK:
 | |
| 				k = (ftnint)cp->nextp->nextp->datap;
 | |
| 				loc += k;
 | |
| 				while(--k >= 0)
 | |
| 					nice_printf(outfile, " ");
 | |
| 				break;
 | |
| 			case TYCHAR:
 | |
| 				k = (ftnint)cp->nextp->nextp->datap;
 | |
| 				nice_printf(outfile, str_fmt[k], k);
 | |
| 				loc++;
 | |
| 				break;
 | |
| 			default:
 | |
| 				goto done;
 | |
| 			}
 | |
| 		v0 = v;
 | |
| 		if (!(v = v->nextp))
 | |
| 			break;
 | |
| 		cp = (chainp)v->datap;
 | |
| 		dloc = (ftnint)cp->datap;
 | |
| 		if (loc != dloc)
 | |
| 			break;
 | |
| 		}
 | |
|  done:
 | |
| 	nice_printf(outfile, "\"");
 | |
| 	*nloc = loc;
 | |
| 	return v0;
 | |
| 	}
 | |
| 
 | |
|  static char *
 | |
| Len(L,type)
 | |
|  long L;
 | |
|  int type;
 | |
| {
 | |
| 	static char buf[24];
 | |
| 	if (L == 1 && type != TYCHAR)
 | |
| 		return "";
 | |
| 	sprintf(buf, "[%ld]", L);
 | |
| 	return buf;
 | |
| 	}
 | |
| 
 | |
| wr_equiv_init(outfile, memno, Values, iscomm)
 | |
|  FILE *outfile;
 | |
|  int memno;
 | |
|  chainp *Values;
 | |
|  int iscomm;
 | |
| {
 | |
| 	struct Equivblock *eqv;
 | |
| 	char *equiv_name ();
 | |
| 	int curtype, dtype, filltype, filltype1, j, k, wasblank, xtype;
 | |
| 	static char Blank[] = "";
 | |
| 	register char *comma = Blank;
 | |
| 	register chainp cp, v;
 | |
| 	chainp sentinel, values, v1;
 | |
| 	ftnint L, L1, dL, dloc, loc, loc0;
 | |
| 	union Constant Const;
 | |
| 	char imag_buf[50], real_buf[50];
 | |
| 	int szshort = typesize[TYSHORT];
 | |
| 	static char typepref[] = {0, 0, TYSHORT, TYLONG, TYREAL, TYDREAL,
 | |
| 				  TYREAL, TYDREAL, TYLOGICAL, TYCHAR};
 | |
| 	extern int htype;
 | |
| 	char *z;
 | |
| 
 | |
| 	/* add sentinel */
 | |
| 	if (iscomm) {
 | |
| 		L = extsymtab[memno].maxleng;
 | |
| 		xtype = extsymtab[memno].extype;
 | |
| 		}
 | |
| 	else {
 | |
| 		eqv = &eqvclass[memno];
 | |
| 		L = eqv->eqvtop - eqv->eqvbottom;
 | |
| 		xtype = eqv->eqvtype;
 | |
| 		}
 | |
| 
 | |
| 	if (halign && typealign[typepref[xtype]] < typealign[htype])
 | |
| 		xtype = htype;
 | |
| 
 | |
| 	if (xtype != TYCHAR) {
 | |
| 
 | |
| 		/* unless the data include a value of the appropriate
 | |
| 		 * type, we add an extra element in an attempt
 | |
| 		 * to force correct alignment */
 | |
| 
 | |
| 		for(v = *Values;;v = v->nextp) {
 | |
| 			if (!v) {
 | |
| 				dtype = typepref[xtype];
 | |
| 				z = ISREAL(dtype) ? cpstring("0.") : (char *)0;
 | |
| 				k = typesize[dtype];
 | |
| 				if (j = L % k)
 | |
| 					L += k - j;
 | |
| 				v = mkchain((char *)L,
 | |
| 					mkchain((char *)dtype,
 | |
| 						mkchain(z, CHNULL)));
 | |
| 				*Values = mkchain((char *)v, *Values);
 | |
| 				L += k;
 | |
| 				break;
 | |
| 				}
 | |
| 			if ((int)((chainp)v->datap)->nextp->datap == xtype)
 | |
| 				break;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 	sentinel = mkchain((char *)L, mkchain((char *)TYERROR,CHNULL));
 | |
| 	*Values = values = revchain(mkchain((char *)sentinel, *Values));
 | |
| 
 | |
| 	/* use doublereal fillers only if there are doublereal values */
 | |
| 
 | |
| 	k = TYLONG;
 | |
| 	for(v = values; v; v = v->nextp)
 | |
| 		if (ONEOF((int)((chainp)v->datap)->nextp->datap,
 | |
| 				M(TYDREAL)|M(TYDCOMPLEX))) {
 | |
| 			k = TYDREAL;
 | |
| 			break;
 | |
| 			}
 | |
| 	type_choice[0] = k;
 | |
| 
 | |
| 	nice_printf(outfile, "%sstruct {\n", iscomm ? "" : "static ");
 | |
| 	next_tab(outfile);
 | |
| 	loc = loc0 = k = 0;
 | |
| 	curtype = -1;
 | |
| 	for(v = values; v; v = v->nextp) {
 | |
| 		cp = (chainp)v->datap;
 | |
| 		dloc = (ftnint)cp->datap;
 | |
| 		L = dloc - loc;
 | |
| 		if (L < 0) {
 | |
| 			overlapping();
 | |
| 			v1 = cp;
 | |
| 			frchain(&v1);
 | |
| 			v->datap = 0;
 | |
| 			continue;
 | |
| 			}
 | |
| 		dtype = (int)cp->nextp->datap;
 | |
| 		if (dtype == TYBLANK) {
 | |
| 			dtype = TYCHAR;
 | |
| 			wasblank = 1;
 | |
| 			}
 | |
| 		else
 | |
| 			wasblank = 0;
 | |
| 		if (curtype != dtype || L > 0) {
 | |
| 			if (curtype != -1) {
 | |
| 				L1 = (loc - loc0)/dL;
 | |
| 				nice_printf(outfile, "%s e_%d%s;\n",
 | |
| 					typename[curtype], ++k,
 | |
| 					Len(L1,curtype));
 | |
| 				}
 | |
| 			curtype = dtype;
 | |
| 			loc0 = dloc;
 | |
| 			}
 | |
| 		if (L > 0) {
 | |
| 			if (xtype == TYCHAR)
 | |
| 				filltype = TYCHAR;
 | |
| 			else {
 | |
| 				filltype = L % szshort ? TYCHAR
 | |
| 						: type_choice[L/szshort % 4];
 | |
| 				filltype1 = loc % szshort ? TYCHAR
 | |
| 						: type_choice[loc/szshort % 4];
 | |
| 				if (typesize[filltype] > typesize[filltype1])
 | |
| 					filltype = filltype1;
 | |
| 				}
 | |
| 			L1 = L / typesize[filltype];
 | |
| 			nice_printf(outfile, "%s fill_%d[%ld];\n",
 | |
| 				typename[filltype], ++k, L1);
 | |
| 			loc = dloc;
 | |
| 			}
 | |
| 		if (wasblank) {
 | |
| 			loc += (ftnint)cp->nextp->nextp->datap;
 | |
| 			dL = 1;
 | |
| 			}
 | |
| 		else {
 | |
| 			dL = typesize[dtype];
 | |
| 			loc += dL;
 | |
| 			}
 | |
| 		}
 | |
| 	nice_printf(outfile, "} %s = { ", iscomm
 | |
| 		? extsymtab[memno].cextname
 | |
| 		: equiv_name(eqvmemno, CNULL));
 | |
| 	loc = 0;
 | |
| 	for(v = values; ; v = v->nextp) {
 | |
| 		cp = (chainp)v->datap;
 | |
| 		if (!cp)
 | |
| 			continue;
 | |
| 		dtype = (int)cp->nextp->datap;
 | |
| 		if (dtype == TYERROR)
 | |
| 			break;
 | |
| 		dloc = (ftnint)cp->datap;
 | |
| 		if (dloc > loc) {
 | |
| 			nice_printf(outfile, "%s{0}", comma);
 | |
| 			comma = ", ";
 | |
| 			loc = dloc;
 | |
| 			}
 | |
| 		if (comma != Blank)
 | |
| 			nice_printf(outfile, ", ");
 | |
| 		comma = ", ";
 | |
| 		if (dtype == TYCHAR || dtype == TYBLANK) {
 | |
| 			v =  Ansi == 1  ? Ado_string(outfile, v, &loc)
 | |
| 					:  do_string(outfile, v, &loc);
 | |
| 			continue;
 | |
| 			}
 | |
| 		make_one_const(dtype, &Const, v);
 | |
| 		switch(dtype) {
 | |
| 			case TYLOGICAL:
 | |
| 				if (Const.ci < 0 || Const.ci > 1)
 | |
| 					errl(
 | |
| 			  "wr_equiv_init: unexpected logical value %ld",
 | |
| 						Const.ci);
 | |
| 				nice_printf(outfile,
 | |
| 					Const.ci ? "TRUE_" : "FALSE_");
 | |
| 				break;
 | |
| 			case TYSHORT:
 | |
| 			case TYLONG:
 | |
| 				nice_printf(outfile, "%ld", Const.ci);
 | |
| 				break;
 | |
| 			case TYREAL:
 | |
| 				nice_printf(outfile, "%s",
 | |
| 					flconst(real_buf, Const.cds[0]));
 | |
| 				break;
 | |
| 			case TYDREAL:
 | |
| 				nice_printf(outfile, "%s", Const.cds[0]);
 | |
| 				break;
 | |
| 			case TYCOMPLEX:
 | |
| 				nice_printf(outfile, "%s, %s",
 | |
| 					flconst(real_buf, Const.cds[0]),
 | |
| 					flconst(imag_buf, Const.cds[1]));
 | |
| 				break;
 | |
| 			case TYDCOMPLEX:
 | |
| 				nice_printf(outfile, "%s, %s",
 | |
| 					Const.cds[0], Const.cds[1]);
 | |
| 				break;
 | |
| 			default:
 | |
| 				erri("unexpected type %d in wr_equiv_init",
 | |
| 					dtype);
 | |
| 			}
 | |
| 		loc += typesize[dtype];
 | |
| 		}
 | |
| 	nice_printf(outfile, " };\n\n");
 | |
| 	prev_tab(outfile);
 | |
| 	frchain(&sentinel);
 | |
| 	}
 |