1 /****************************************************************
2 Copyright 1990 by AT&T Bell Laboratories and Bellcore.
4 Permission to use, copy, modify, and distribute this software
5 and its documentation for any purpose and without fee is hereby
6 granted, provided that the above copyright notice appear in all
7 copies and that both that the copyright notice and this
8 permission notice and warranty disclaimer appear in supporting
9 documentation, and that the names of AT&T Bell Laboratories or
10 Bellcore or any of their entities not be used in advertising or
11 publicity pertaining to distribution of the software without
12 specific, written prior permission.
14 AT&T and Bellcore disclaim all warranties with regard to this
15 software, including all implied warranties of merchantability
16 and fitness. In no event shall AT&T or Bellcore be liable for
17 any special, indirect or consequential damages or any damages
18 whatsoever resulting from loss of use, data or profits, whether
19 in an action of contract, negligence or other tortious action,
20 arising out of or in connection with the use or performance of
22 ****************************************************************/
29 #define MAX_INIT_LINE 100
32 static int memno2info();
34 extern char *initbname;
35 extern void def_start();
37 void list_init_data(Infile, Inname, outfile)
38 FILE **Infile, *outfile;
47 if (status = dsort(Inname, sortfname))
48 fatali ("sort failed, status %d", status);
50 scrub(Inname); /* optionally unlink Inname */
52 if ((sortfp = fopen(sortfname, textread)) == NULL)
53 Fatal("Couldn't open sorted initialization data");
55 do_init_data(outfile, sortfp);
59 /* Insert a blank line after any initialized data */
61 nice_printf (outfile, "\n");
63 if (debugflag && infname)
64 /* don't back block data file up -- it won't be overwritten */
65 backup(initfname, initbname);
66 } /* list_init_data */
70 /* do_init_data -- returns YES when at least one declaration has been
73 int do_init_data(outfile, infile)
74 FILE *outfile, *infile;
76 char varname[NAME_MAX], ovarname[NAME_MAX];
79 int vargroup; /* 0 --> init, 1 --> equiv, 2 --> common */
80 int did_one = 0; /* True when one has been output */
81 chainp values = CHNULL; /* Actual data values */
87 while (rdname (infile, &vargroup, varname) && rdlong (infile, &offset)
88 && rdlong (infile, &type)) {
89 if (strcmp (varname, ovarname)) {
91 /* If this is a new variable name, the old initialization has been
94 wr_one_init(outfile, ovarname, &values, keepit);
96 strcpy (ovarname, varname);
99 if (memno2info(atoi(varname+2), &np)) {
100 if (((Addrp)np)->uname_tag != UNAM_NAME) {
101 err("do_init_data: expected NAME");
104 np = ((Addrp)np)->user.name;
106 if (!(keepit = np->visused) && !np->vimpldovar)
107 warn1("local variable %s never used",
114 if (keepit && !did_one) {
115 nice_printf (outfile, "/* Initialized data */\n\n");
120 values = mkchain((char *)data_value(infile, offset, (int)type), values);
123 /* Write out the last declaration */
125 wr_one_init (outfile, ovarname, &values, keepit);
132 wr_char_len(outfile, dimp, n, extra1)
135 struct Dimblock *dimp;
143 nice_printf (outfile, extra1 ? "[%d+1]" : "[%d]", n);
146 nice_printf(outfile, "[%d", n);
149 for(i = 0; i < nd; i++) {
150 e = dimp->dims[i].dimsize;
152 err ("wr_char_len: nonconstant array size");
154 nice_printf(outfile, "*%ld", e->constblock.Const.ci);
155 rv *= e->constblock.Const.ci;
158 /* extra1 allows for stupid C compilers that complain about
159 * too many initializers in
162 nice_printf(outfile, extra1 ? "+1]" : "]");
163 return extra1 ? rv+1 : rv;
166 static int ch_ar_dim = -1; /* length of each element of char string array */
167 static int eqvmemno; /* kludge */
170 write_char_init(outfile, Values, namep)
175 struct Equivblock *eqv;
177 struct Dimblock *dimp;
183 if(nequiv >= maxequiv)
184 many("equivalences", 'q', maxequiv);
185 eqv = &eqvclass[nequiv];
188 size = type == TYCHAR
189 ? namep->vleng->constblock.Const.ci
191 if (dimp = namep->vdim)
192 for(i = 0, nd = dimp->ndim; i < nd; i++) {
193 ds = dimp->dims[i].dimsize;
195 err("write_char_values: nonconstant array size");
197 size *= ds->constblock.Const.ci;
199 *Values = revchain(*Values);
201 eqvmemno = ++lastvarno;
203 wr_equiv_init(outfile, nequiv, Values, 0);
204 def_start(outfile, namep->cvarname, CNULL, "");
206 ind_printf(0, outfile, "((char *)&equiv_%d)\n\n", eqvmemno);
208 ind_printf(0, outfile, dimp
209 ? "((%s *)&equiv_%d)\n\n" : "(*(%s *)&equiv_%d)\n\n",
210 c_type_decl(type,0), eqvmemno);
213 /* wr_one_init -- outputs the initialization of the variable pointed to
214 by info. When is_addr is true, info is an Addrp; otherwise,
215 treat it as a Namep */
217 void wr_one_init (outfile, varname, Values, keepit)
229 int is_addr, size, type;
232 char *array_comment = NULL, *name;
234 extern char datachar[];
235 static int e1[3] = {1, 0, 1};
241 if (varname == NULL || varname[1] != '.')
244 /* Get back to a meaningful representation; find the given memno in one
245 of the appropriate tables (user-generated variables in the hash table,
246 system-generated variables in a separate list */
248 memno = atoi(varname + 2);
251 /* Must subtract eqvstart when the source file
252 * contains more than one procedure.
254 wr_equiv_init(outfile, eqvmemno = memno - eqvstart, Values, 0);
257 /* COMMON initialization (BLOCK DATA) */
258 wr_equiv_init(outfile, memno, Values, 1);
264 errstr("wr_one_init: unknown variable name '%s'", varname);
268 is_addr = memno2info (memno, &info.name);
269 if (info.name == (Namep) NULL) {
270 err ("wr_one_init -- unknown variable");
274 if (info.addr -> uname_tag != UNAM_NAME) {
275 erri ("wr_one_init -- couldn't get name pointer; tag is %d",
276 info.addr -> uname_tag);
277 namep = (Namep) NULL;
278 nice_printf (outfile, " /* bad init data */");
280 namep = info.addr -> user.name;
284 /* check for character initialization */
286 *Values = values = revchain(*Values);
287 type = info.name->vtype;
288 if (type == TYCHAR) {
289 for(last = 0; values; values = values->nextp) {
290 cp = (chainp)values->datap;
291 loc = (ftnint)cp->datap;
293 write_char_init(outfile, Values, namep);
296 last = (int)cp->nextp->datap == TYBLANK
297 ? loc + (int)cp->nextp->nextp->datap
300 if (halign && info.name->tag == TNAME) {
301 nice_printf(outfile, "static struct { %s fill; char val",
303 x = wr_char_len(outfile, namep->vdim, ch_ar_dim =
304 info.name -> vleng -> constblock.Const.ci, 1);
306 nice_printf(outfile, "; char fill2[%ld]", hsize - x);
307 name = info.name->cvarname;
308 nice_printf(outfile, "; } %s_st = { 0,", name);
309 wr_output_values(outfile, namep, *Values);
310 nice_printf(outfile, " };\n");
312 def_start(outfile, name, CNULL, name);
313 ind_printf(0, outfile, "_st.val\n");
318 size = typesize[type];
320 for(; values; values = values->nextp) {
321 if ((int)((chainp)values->datap)->nextp->datap == TYCHAR) {
322 write_char_init(outfile, Values, namep);
325 last = ((long) ((chainp) values->datap)->datap) / size;
326 if (last - loc > 4) {
327 write_char_init(outfile, Values, namep);
335 nice_printf (outfile, "static %s ", c_type_decl (type, 0));
338 write_nv_ident (outfile, info.addr);
340 out_name (outfile, info.name);
343 is_scalar = namep -> vdim == (struct Dimblock *) NULL;
345 if (namep && !is_scalar)
346 array_comment = type == TYCHAR
347 ? 0 : wr_ardecls(outfile, namep->vdim, 1L);
350 if (ISICON (info.name -> vleng))
352 /* We'll make single strings one character longer, so that we can use the
353 standard C initialization. All this does is pad an extra zero onto the
355 wr_char_len(outfile, namep->vdim, ch_ar_dim =
356 info.name -> vleng -> constblock.Const.ci, e1[Ansi]);
358 err ("variable length character initialization");
361 nice_printf (outfile, "%s", array_comment);
363 nice_printf (outfile, " = ");
364 wr_output_values (outfile, namep, values);
366 nice_printf (outfile, ";\n");
374 chainp data_value (infile, offset, type)
379 char line[MAX_INIT_LINE + 1], *pointer;
380 chainp vals, prev_val;
384 if (fgets (line, MAX_INIT_LINE, infile) == NULL) {
385 err ("data_value: error reading from intermediate file");
389 /* Get rid of the trailing newline */
392 line[strlen (line) - 1] = '\0';
394 #define iswhite(x) (isspace (x) || (x) == ',')
397 prev_val = vals = CHNULL;
400 register char *end_ptr, old_val;
402 /* Move pointer to the start of the next word */
404 while (*pointer && iswhite (*pointer))
406 if (*pointer == '\0')
409 /* Move end_ptr to the end of the current word */
411 for (end_ptr = pointer + 1; *end_ptr && !iswhite (*end_ptr);
418 /* Add this value to the end of the list */
420 if (ONEOF(type, MSKREAL|MSKCOMPLEX))
421 newval = cpstring(pointer);
423 newval = (char *)atol(pointer);
425 prev_val->nextp = mkchain(newval, CHNULL);
426 prev_val = prev_val -> nextp;
428 prev_val = vals = mkchain(newval, CHNULL);
431 } /* while *pointer */
433 return mkchain((char *)offset, mkchain((char *)type, vals));
439 extern char *filename0;
440 static int warned = 0;
446 fprintf(stderr, "Error");
448 fprintf(stderr, " in file %s", filename0);
449 fprintf(stderr, ": overlapping initializations\n");
453 static void make_one_const();
456 void wr_output_values (outfile, namep, values)
461 int type = TYUNKNOWN;
462 struct Constblock Const;
466 type = namep -> vtype;
468 /* Handle array initializations away from scalars */
470 if (namep && namep -> vdim)
471 wr_array_init (outfile, namep -> vtype, values);
473 else if (values->nextp && type != TYCHAR)
477 make_one_const(type, &Const.Const, values);
479 Const.vstg = ONEOF(type, MSKREAL|MSKCOMPLEX);
484 Vlen->constblock.Const.ci = charlen;
485 out_const (outfile, &Const);
486 free (Const.Const.ccp);
489 out_const (outfile, &Const);
494 wr_array_init (outfile, type, values)
499 int size = typesize[type];
500 long index, main_index = 0;
503 if (type == TYCHAR) {
504 nice_printf(outfile, "\"");
510 nice_printf (outfile, "{ ");
512 struct Constblock Const;
514 index = ((long) ((chainp) values->datap)->datap) / size;
515 while (index > main_index) {
517 /* Fill with zeros. The structure shorthand works because the compiler
518 will expand the "0" in braces to fill the size of the entire structure
524 nice_printf (outfile, "0.0,");
528 nice_printf (outfile, "{0},");
531 nice_printf(outfile, " ");
534 nice_printf (outfile, "0,");
538 } /* while index > main_index */
540 if (index < main_index)
546 if (k == ch_ar_dim) {
547 nice_printf(outfile, "\" \"");
550 this_char = (int) ((chainp) values->datap)->
552 if ((int)((chainp)values->datap)->nextp->datap == TYBLANK) {
553 main_index += this_char;
555 while(--this_char >= 0)
556 nice_printf(outfile, " ");
557 values = values -> nextp;
560 nice_printf(outfile, str_fmt[this_char], this_char);
572 make_one_const(type, &Const.Const, values);
574 Const.vstg = ONEOF(type, MSKREAL|MSKCOMPLEX);
575 out_const(outfile, &Const);
578 erri("wr_array_init: bad type '%d'", type);
581 values = values->nextp;
584 if (values && type != TYCHAR)
585 nice_printf (outfile, ",");
588 if (type == TYCHAR) {
589 nice_printf(outfile, "\"");
592 nice_printf (outfile, " }");
593 } /* wr_array_init */
597 make_one_const(type, storage, values)
599 union Constant *storage;
602 union Constant *Const;
605 if (type == TYCHAR) {
608 int b = 0, k, main_index = 0;
610 /* Find the max length of init string, by finding the highest offset
611 value stored in the list of initial values */
613 for(k = 1, prev = CHNULL, v = values; v; prev = v, v = v->nextp)
616 k = ((int) (((chainp) prev->datap)->datap)) + 2;
617 /* + 2 above for null char at end */
619 for (str_ptr = str; values; str_ptr++) {
620 int index = (int) (((chainp) values->datap)->datap);
622 if (index < main_index)
624 while (index > main_index++)
627 k = (int) (((chainp) values->datap)->nextp->nextp->datap);
628 if ((int)((chainp)values->datap)->nextp->datap == TYBLANK) {
633 values = values -> nextp;
638 Const -> ccp1.blanks = b;
639 charlen = str_ptr - str;
644 vals = ((chainp)values->datap)->nextp->nextp;
646 L = (char **)storage;
647 do L[i++] = vals->datap;
648 while(vals = vals->nextp);
653 } /* make_one_const */
657 rdname (infile, vargroupp, name)
669 *vargroupp = c - '0';
672 Fatal("rdname: oversize name");
690 for (c = getc (infile); !feof (infile) && isspace (c); c = getc (infile))
696 for (*n = 0; isdigit (c); c = getc (infile))
697 *n = 10 * (*n) + c - '0';
703 memno2info (memno, info)
708 extern chainp new_vars;
709 extern struct Hashentry *hashtab, *lasthash;
710 struct Hashentry *entry;
712 for (this_var = new_vars; this_var; this_var = this_var -> nextp) {
713 Addrp var = (Addrp) this_var->datap;
715 if (var == (Addrp) NULL)
716 Fatal("memno2info: null variable");
717 else if (var -> tag != TADDR)
718 Fatal("memno2info: bad tag");
719 if (memno == var -> memno) {
722 } /* if memno == var -> memno */
723 } /* for this_var = new_vars */
725 for (entry = hashtab; entry < lasthash; ++entry) {
726 Namep var = entry -> varp;
728 if (var && var -> vardesc.varno == memno && var -> vstg == STGINIT) {
731 } /* if entry -> vardesc.varno == memno */
732 } /* for entry = hashtab */
734 Fatal("memno2info: couldn't find memno");
739 do_string(outfile, v, nloc)
744 register chainp cp, v0;
749 nice_printf(outfile, "{");
750 cp = (chainp)v->datap;
751 loc = (ftnint)cp->datap;
754 switch((int)cp->nextp->datap) {
756 k = (ftnint)cp->nextp->nextp->datap;
759 nice_printf(outfile, "%s' '", comma);
764 uk = (ftnint)cp->nextp->nextp->datap;
765 sprintf(buf, chr_fmt[uk], uk);
766 nice_printf(outfile, "%s'%s'", comma, buf);
776 cp = (chainp)v->datap;
777 dloc = (ftnint)cp->datap;
782 nice_printf(outfile, "}");
788 Ado_string(outfile, v, nloc)
793 register chainp cp, v0;
796 nice_printf(outfile, "\"");
797 cp = (chainp)v->datap;
798 loc = (ftnint)cp->datap;
800 switch((int)cp->nextp->datap) {
802 k = (ftnint)cp->nextp->nextp->datap;
805 nice_printf(outfile, " ");
808 k = (ftnint)cp->nextp->nextp->datap;
809 nice_printf(outfile, str_fmt[k], k);
818 cp = (chainp)v->datap;
819 dloc = (ftnint)cp->datap;
824 nice_printf(outfile, "\"");
835 if (L == 1 && type != TYCHAR)
837 sprintf(buf, "[%ld]", L);
841 wr_equiv_init(outfile, memno, Values, iscomm)
847 struct Equivblock *eqv;
849 int curtype, dtype, filltype, filltype1, j, k, wasblank, xtype;
850 static char Blank[] = "";
851 register char *comma = Blank;
852 register chainp cp, v;
853 chainp sentinel, values, v1;
854 ftnint L, L1, dL, dloc, loc, loc0;
855 union Constant Const;
856 char imag_buf[50], real_buf[50];
857 int szshort = typesize[TYSHORT];
858 static char typepref[] = {0, 0, TYSHORT, TYLONG, TYREAL, TYDREAL,
859 TYREAL, TYDREAL, TYLOGICAL, TYCHAR};
865 L = extsymtab[memno].maxleng;
866 xtype = extsymtab[memno].extype;
869 eqv = &eqvclass[memno];
870 L = eqv->eqvtop - eqv->eqvbottom;
871 xtype = eqv->eqvtype;
874 if (halign && typealign[typepref[xtype]] < typealign[htype])
877 if (xtype != TYCHAR) {
879 /* unless the data include a value of the appropriate
880 * type, we add an extra element in an attempt
881 * to force correct alignment */
883 for(v = *Values;;v = v->nextp) {
885 dtype = typepref[xtype];
886 z = ISREAL(dtype) ? cpstring("0.") : (char *)0;
890 v = mkchain((char *)L,
891 mkchain((char *)dtype,
892 mkchain(z, CHNULL)));
893 *Values = mkchain((char *)v, *Values);
897 if ((int)((chainp)v->datap)->nextp->datap == xtype)
902 sentinel = mkchain((char *)L, mkchain((char *)TYERROR,CHNULL));
903 *Values = values = revchain(mkchain((char *)sentinel, *Values));
905 /* use doublereal fillers only if there are doublereal values */
908 for(v = values; v; v = v->nextp)
909 if (ONEOF((int)((chainp)v->datap)->nextp->datap,
910 M(TYDREAL)|M(TYDCOMPLEX))) {
916 nice_printf(outfile, "%sstruct {\n", iscomm ? "" : "static ");
920 for(v = values; v; v = v->nextp) {
921 cp = (chainp)v->datap;
922 dloc = (ftnint)cp->datap;
931 dtype = (int)cp->nextp->datap;
932 if (dtype == TYBLANK) {
938 if (curtype != dtype || L > 0) {
940 L1 = (loc - loc0)/dL;
941 nice_printf(outfile, "%s e_%d%s;\n",
942 typename[curtype], ++k,
952 filltype = L % szshort ? TYCHAR
953 : type_choice[L/szshort % 4];
954 filltype1 = loc % szshort ? TYCHAR
955 : type_choice[loc/szshort % 4];
956 if (typesize[filltype] > typesize[filltype1])
957 filltype = filltype1;
959 L1 = L / typesize[filltype];
960 nice_printf(outfile, "%s fill_%d[%ld];\n",
961 typename[filltype], ++k, L1);
965 loc += (ftnint)cp->nextp->nextp->datap;
969 dL = typesize[dtype];
973 nice_printf(outfile, "} %s = { ", iscomm
974 ? extsymtab[memno].cextname
975 : equiv_name(eqvmemno, CNULL));
977 for(v = values; ; v = v->nextp) {
978 cp = (chainp)v->datap;
981 dtype = (int)cp->nextp->datap;
982 if (dtype == TYERROR)
984 dloc = (ftnint)cp->datap;
986 nice_printf(outfile, "%s{0}", comma);
991 nice_printf(outfile, ", ");
993 if (dtype == TYCHAR || dtype == TYBLANK) {
994 v = Ansi == 1 ? Ado_string(outfile, v, &loc)
995 : do_string(outfile, v, &loc);
998 make_one_const(dtype, &Const, v);
1001 if (Const.ci < 0 || Const.ci > 1)
1003 "wr_equiv_init: unexpected logical value %ld",
1005 nice_printf(outfile,
1006 Const.ci ? "TRUE_" : "FALSE_");
1010 nice_printf(outfile, "%ld", Const.ci);
1013 nice_printf(outfile, "%s",
1014 flconst(real_buf, Const.cds[0]));
1017 nice_printf(outfile, "%s", Const.cds[0]);
1020 nice_printf(outfile, "%s, %s",
1021 flconst(real_buf, Const.cds[0]),
1022 flconst(imag_buf, Const.cds[1]));
1025 nice_printf(outfile, "%s, %s",
1026 Const.cds[0], Const.cds[1]);
1029 erri("unexpected type %d in wr_equiv_init",
1032 loc += typesize[dtype];
1034 nice_printf(outfile, " };\n\n");