Commit | Line | Data |
---|---|---|
f1525c23 WH |
1 | /**************************************************************** |
2 | Copyright 1990, 1991, 1993 by AT&T Bell Laboratories and Bellcore. | |
3 | ||
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. | |
13 | ||
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 | |
21 | this software. | |
22 | ****************************************************************/ | |
23 | ||
24 | #include "defs.h" | |
25 | #include "output.h" | |
26 | #include "names.h" | |
27 | #include "format.h" | |
28 | ||
29 | #define MAX_INIT_LINE 100 | |
30 | #define NAME_MAX 64 | |
31 | ||
32 | static int memno2info(); | |
33 | ||
34 | extern char *initbname; | |
35 | extern void def_start(); | |
36 | ||
37 | void list_init_data(Infile, Inname, outfile) | |
38 | FILE **Infile, *outfile; | |
39 | char *Inname; | |
40 | { | |
41 | FILE *sortfp; | |
42 | int status; | |
43 | ||
44 | fclose(*Infile); | |
45 | *Infile = 0; | |
46 | ||
47 | if (status = dsort(Inname, sortfname)) | |
48 | fatali ("sort failed, status %d", status); | |
49 | ||
50 | scrub(Inname); /* optionally unlink Inname */ | |
51 | ||
52 | if ((sortfp = fopen(sortfname, textread)) == NULL) | |
53 | Fatal("Couldn't open sorted initialization data"); | |
54 | ||
55 | do_init_data(outfile, sortfp); | |
56 | fclose(sortfp); | |
57 | scrub(sortfname); | |
58 | ||
59 | /* Insert a blank line after any initialized data */ | |
60 | ||
61 | nice_printf (outfile, "\n"); | |
62 | ||
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 */ | |
67 | ||
68 | ||
69 | ||
70 | /* do_init_data -- returns YES when at least one declaration has been | |
71 | written */ | |
72 | ||
73 | int do_init_data(outfile, infile) | |
74 | FILE *outfile, *infile; | |
75 | { | |
76 | char varname[NAME_MAX], ovarname[NAME_MAX]; | |
77 | ftnint offset; | |
78 | ftnint type; | |
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 */ | |
82 | int keepit = 0; | |
83 | Namep np; | |
84 | ||
85 | ovarname[0] = '\0'; | |
86 | ||
87 | while (rdname (infile, &vargroup, varname) && rdlong (infile, &offset) | |
88 | && rdlong (infile, &type)) { | |
89 | if (strcmp (varname, ovarname)) { | |
90 | ||
91 | /* If this is a new variable name, the old initialization has been | |
92 | completed */ | |
93 | ||
94 | wr_one_init(outfile, ovarname, &values, keepit); | |
95 | ||
96 | strcpy (ovarname, varname); | |
97 | values = CHNULL; | |
98 | if (vargroup == 0) { | |
99 | if (memno2info(atoi(varname+2), &np)) { | |
100 | if (((Addrp)np)->uname_tag != UNAM_NAME) { | |
101 | err("do_init_data: expected NAME"); | |
102 | goto Keep; | |
103 | } | |
104 | np = ((Addrp)np)->user.name; | |
105 | } | |
106 | if (!(keepit = np->visused) && !np->vimpldovar) | |
107 | warn1("local variable %s never used", | |
108 | np->fvarname); | |
109 | } | |
110 | else { | |
111 | Keep: | |
112 | keepit = 1; | |
113 | } | |
114 | if (keepit && !did_one) { | |
115 | nice_printf (outfile, "/* Initialized data */\n\n"); | |
116 | did_one = YES; | |
117 | } | |
118 | } /* if strcmp */ | |
119 | ||
120 | values = mkchain((char *)data_value(infile, offset, (int)type), values); | |
121 | } /* while */ | |
122 | ||
123 | /* Write out the last declaration */ | |
124 | ||
125 | wr_one_init (outfile, ovarname, &values, keepit); | |
126 | ||
127 | return did_one; | |
128 | } /* do_init_data */ | |
129 | ||
130 | ||
131 | ftnint | |
132 | wr_char_len(outfile, dimp, n, extra1) | |
133 | FILE *outfile; | |
134 | int n; | |
135 | struct Dimblock *dimp; | |
136 | int extra1; | |
137 | { | |
138 | int i, nd; | |
139 | expptr e; | |
140 | ftnint rv; | |
141 | ||
142 | if (!dimp) { | |
143 | nice_printf (outfile, extra1 ? "[%d+1]" : "[%d]", n); | |
144 | return n + extra1; | |
145 | } | |
146 | nice_printf(outfile, "[%d", n); | |
147 | nd = dimp->ndim; | |
148 | rv = n; | |
149 | for(i = 0; i < nd; i++) { | |
150 | e = dimp->dims[i].dimsize; | |
151 | if (!ISICON (e)) | |
152 | err ("wr_char_len: nonconstant array size"); | |
153 | else { | |
154 | nice_printf(outfile, "*%ld", e->constblock.Const.ci); | |
155 | rv *= e->constblock.Const.ci; | |
156 | } | |
157 | } | |
158 | /* extra1 allows for stupid C compilers that complain about | |
159 | * too many initializers in | |
160 | * char x[2] = "ab"; | |
161 | */ | |
162 | nice_printf(outfile, extra1 ? "+1]" : "]"); | |
163 | return extra1 ? rv+1 : rv; | |
164 | } | |
165 | ||
166 | static int ch_ar_dim = -1; /* length of each element of char string array */ | |
167 | static int eqvmemno; /* kludge */ | |
168 | ||
169 | static void | |
170 | write_char_init(outfile, Values, namep) | |
171 | FILE *outfile; | |
172 | chainp *Values; | |
173 | Namep namep; | |
174 | { | |
175 | struct Equivblock *eqv; | |
176 | long size; | |
177 | struct Dimblock *dimp; | |
178 | int i, nd, type; | |
179 | expptr ds; | |
180 | ||
181 | if (!namep) | |
182 | return; | |
183 | if(nequiv >= maxequiv) | |
184 | many("equivalences", 'q', maxequiv); | |
185 | eqv = &eqvclass[nequiv]; | |
186 | eqv->eqvbottom = 0; | |
187 | type = namep->vtype; | |
188 | size = type == TYCHAR | |
189 | ? namep->vleng->constblock.Const.ci | |
190 | : typesize[type]; | |
191 | if (dimp = namep->vdim) | |
192 | for(i = 0, nd = dimp->ndim; i < nd; i++) { | |
193 | ds = dimp->dims[i].dimsize; | |
194 | if (!ISICON(ds)) | |
195 | err("write_char_values: nonconstant array size"); | |
196 | else | |
197 | size *= ds->constblock.Const.ci; | |
198 | } | |
199 | *Values = revchain(*Values); | |
200 | eqv->eqvtop = size; | |
201 | eqvmemno = ++lastvarno; | |
202 | eqv->eqvtype = type; | |
203 | wr_equiv_init(outfile, nequiv, Values, 0); | |
204 | def_start(outfile, namep->cvarname, CNULL, ""); | |
205 | if (type == TYCHAR) | |
206 | ind_printf(0, outfile, "((char *)&equiv_%d)\n\n", eqvmemno); | |
207 | else | |
208 | ind_printf(0, outfile, dimp | |
209 | ? "((%s *)&equiv_%d)\n\n" : "(*(%s *)&equiv_%d)\n\n", | |
210 | c_type_decl(type,0), eqvmemno); | |
211 | } | |
212 | ||
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 */ | |
216 | ||
217 | void wr_one_init (outfile, varname, Values, keepit) | |
218 | FILE *outfile; | |
219 | char *varname; | |
220 | chainp *Values; | |
221 | int keepit; | |
222 | { | |
223 | static int memno; | |
224 | static union { | |
225 | Namep name; | |
226 | Addrp addr; | |
227 | } info; | |
228 | Namep namep; | |
229 | int is_addr, size, type; | |
230 | ftnint last, loc; | |
231 | int is_scalar = 0; | |
232 | char *array_comment = NULL, *name; | |
233 | chainp cp, values; | |
234 | extern char datachar[]; | |
235 | static int e1[3] = {1, 0, 1}; | |
236 | ftnint x; | |
237 | extern int hsize; | |
238 | ||
239 | if (!keepit) | |
240 | goto done; | |
241 | if (varname == NULL || varname[1] != '.') | |
242 | goto badvar; | |
243 | ||
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 */ | |
247 | ||
248 | memno = atoi(varname + 2); | |
249 | switch(varname[0]) { | |
250 | case 'q': | |
251 | /* Must subtract eqvstart when the source file | |
252 | * contains more than one procedure. | |
253 | */ | |
254 | wr_equiv_init(outfile, eqvmemno = memno - eqvstart, Values, 0); | |
255 | goto done; | |
256 | case 'Q': | |
257 | /* COMMON initialization (BLOCK DATA) */ | |
258 | wr_equiv_init(outfile, memno, Values, 1); | |
259 | goto done; | |
260 | case 'v': | |
261 | break; | |
262 | default: | |
263 | badvar: | |
264 | errstr("wr_one_init: unknown variable name '%s'", varname); | |
265 | goto done; | |
266 | } | |
267 | ||
268 | is_addr = memno2info (memno, &info.name); | |
269 | if (info.name == (Namep) NULL) { | |
270 | err ("wr_one_init -- unknown variable"); | |
271 | return; | |
272 | } | |
273 | if (is_addr) { | |
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 */"); | |
279 | } else | |
280 | namep = info.addr -> user.name; | |
281 | } else | |
282 | namep = info.name; | |
283 | ||
284 | /* check for character initialization */ | |
285 | ||
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; | |
292 | if (loc > last) { | |
293 | write_char_init(outfile, Values, namep); | |
294 | goto done; | |
295 | } | |
296 | last = (int)cp->nextp->datap == TYBLANK | |
297 | ? loc + (int)cp->nextp->nextp->datap | |
298 | : loc + 1; | |
299 | } | |
300 | if (halign && info.name->tag == TNAME) { | |
301 | nice_printf(outfile, "static struct { %s fill; char val", | |
302 | halign); | |
303 | x = wr_char_len(outfile, namep->vdim, ch_ar_dim = | |
304 | info.name -> vleng -> constblock.Const.ci, 1); | |
305 | if (x %= hsize) | |
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"); | |
311 | ch_ar_dim = -1; | |
312 | def_start(outfile, name, CNULL, name); | |
313 | ind_printf(0, outfile, "_st.val\n"); | |
314 | goto done; | |
315 | } | |
316 | } | |
317 | else { | |
318 | size = typesize[type]; | |
319 | loc = 0; | |
320 | for(; values; values = values->nextp) { | |
321 | if ((int)((chainp)values->datap)->nextp->datap == TYCHAR) { | |
322 | write_char_init(outfile, Values, namep); | |
323 | goto done; | |
324 | } | |
325 | last = ((long) ((chainp) values->datap)->datap) / size; | |
326 | if (last - loc > 4) { | |
327 | write_char_init(outfile, Values, namep); | |
328 | goto done; | |
329 | } | |
330 | loc = last; | |
331 | } | |
332 | } | |
333 | values = *Values; | |
334 | ||
335 | nice_printf (outfile, "static %s ", c_type_decl (type, 0)); | |
336 | ||
337 | if (is_addr) | |
338 | write_nv_ident (outfile, info.addr); | |
339 | else | |
340 | out_name (outfile, info.name); | |
341 | ||
342 | if (namep) | |
343 | is_scalar = namep -> vdim == (struct Dimblock *) NULL; | |
344 | ||
345 | if (namep && !is_scalar) | |
346 | array_comment = type == TYCHAR | |
347 | ? 0 : wr_ardecls(outfile, namep->vdim, 1L); | |
348 | ||
349 | if (type == TYCHAR) | |
350 | if (ISICON (info.name -> vleng)) | |
351 | ||
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 | |
354 | end of the string */ | |
355 | wr_char_len(outfile, namep->vdim, ch_ar_dim = | |
356 | info.name -> vleng -> constblock.Const.ci, e1[Ansi]); | |
357 | else | |
358 | err ("variable length character initialization"); | |
359 | ||
360 | if (array_comment) | |
361 | nice_printf (outfile, "%s", array_comment); | |
362 | ||
363 | nice_printf (outfile, " = "); | |
364 | wr_output_values (outfile, namep, values); | |
365 | ch_ar_dim = -1; | |
366 | nice_printf (outfile, ";\n"); | |
367 | done: | |
368 | frchain(Values); | |
369 | } /* wr_one_init */ | |
370 | ||
371 | ||
372 | ||
373 | ||
374 | chainp data_value (infile, offset, type) | |
375 | FILE *infile; | |
376 | ftnint offset; | |
377 | int type; | |
378 | { | |
379 | char line[MAX_INIT_LINE + 1], *pointer; | |
380 | chainp vals, prev_val; | |
381 | #ifndef atol | |
382 | long atol(); | |
383 | #endif | |
384 | char *newval; | |
385 | ||
386 | if (fgets (line, MAX_INIT_LINE, infile) == NULL) { | |
387 | err ("data_value: error reading from intermediate file"); | |
388 | return CHNULL; | |
389 | } /* if fgets */ | |
390 | ||
391 | /* Get rid of the trailing newline */ | |
392 | ||
393 | if (line[0]) | |
394 | line[strlen (line) - 1] = '\0'; | |
395 | ||
396 | #define iswhite(x) (isspace (x) || (x) == ',') | |
397 | ||
398 | pointer = line; | |
399 | prev_val = vals = CHNULL; | |
400 | ||
401 | while (*pointer) { | |
402 | register char *end_ptr, old_val; | |
403 | ||
404 | /* Move pointer to the start of the next word */ | |
405 | ||
406 | while (*pointer && iswhite (*pointer)) | |
407 | pointer++; | |
408 | if (*pointer == '\0') | |
409 | break; | |
410 | ||
411 | /* Move end_ptr to the end of the current word */ | |
412 | ||
413 | for (end_ptr = pointer + 1; *end_ptr && !iswhite (*end_ptr); | |
414 | end_ptr++) | |
415 | ; | |
416 | ||
417 | old_val = *end_ptr; | |
418 | *end_ptr = '\0'; | |
419 | ||
420 | /* Add this value to the end of the list */ | |
421 | ||
422 | if (ONEOF(type, MSKREAL|MSKCOMPLEX)) | |
423 | newval = cpstring(pointer); | |
424 | else | |
425 | newval = (char *)atol(pointer); | |
426 | if (vals) { | |
427 | prev_val->nextp = mkchain(newval, CHNULL); | |
428 | prev_val = prev_val -> nextp; | |
429 | } else | |
430 | prev_val = vals = mkchain(newval, CHNULL); | |
431 | *end_ptr = old_val; | |
432 | pointer = end_ptr; | |
433 | } /* while *pointer */ | |
434 | ||
435 | return mkchain((char *)offset, mkchain((char *)LONG_CAST type, vals)); | |
436 | } /* data_value */ | |
437 | ||
438 | static void | |
439 | overlapping() | |
440 | { | |
441 | extern char *filename0; | |
442 | static int warned = 0; | |
443 | ||
444 | if (warned) | |
445 | return; | |
446 | warned = 1; | |
447 | ||
448 | fprintf(stderr, "Error"); | |
449 | if (filename0) | |
450 | fprintf(stderr, " in file %s", filename0); | |
451 | fprintf(stderr, ": overlapping initializations\n"); | |
452 | nerr++; | |
453 | } | |
454 | ||
455 | static void make_one_const(); | |
456 | static long charlen; | |
457 | ||
458 | void wr_output_values (outfile, namep, values) | |
459 | FILE *outfile; | |
460 | Namep namep; | |
461 | chainp values; | |
462 | { | |
463 | int type = TYUNKNOWN; | |
464 | struct Constblock Const; | |
465 | static expptr Vlen; | |
466 | ||
467 | if (namep) | |
468 | type = namep -> vtype; | |
469 | ||
470 | /* Handle array initializations away from scalars */ | |
471 | ||
472 | if (namep && namep -> vdim) | |
473 | wr_array_init (outfile, namep -> vtype, values); | |
474 | ||
475 | else if (values->nextp && type != TYCHAR) | |
476 | overlapping(); | |
477 | ||
478 | else { | |
479 | make_one_const(type, &Const.Const, values); | |
480 | Const.vtype = type; | |
481 | Const.vstg = ONEOF(type, MSKREAL|MSKCOMPLEX) != 0; | |
482 | if (type== TYCHAR) { | |
483 | if (!Vlen) | |
484 | Vlen = ICON(0); | |
485 | Const.vleng = Vlen; | |
486 | Vlen->constblock.Const.ci = charlen; | |
487 | out_const (outfile, &Const); | |
488 | free (Const.Const.ccp); | |
489 | } | |
490 | else | |
491 | out_const (outfile, &Const); | |
492 | } | |
493 | } | |
494 | ||
495 | ||
496 | wr_array_init (outfile, type, values) | |
497 | FILE *outfile; | |
498 | int type; | |
499 | chainp values; | |
500 | { | |
501 | int size = typesize[type]; | |
502 | long index, main_index = 0; | |
503 | int k; | |
504 | ||
505 | if (type == TYCHAR) { | |
506 | nice_printf(outfile, "\""); | |
507 | k = 0; | |
508 | if (Ansi != 1) | |
509 | ch_ar_dim = -1; | |
510 | } | |
511 | else | |
512 | nice_printf (outfile, "{ "); | |
513 | while (values) { | |
514 | struct Constblock Const; | |
515 | ||
516 | index = ((long) ((chainp) values->datap)->datap) / size; | |
517 | while (index > main_index) { | |
518 | ||
519 | /* Fill with zeros. The structure shorthand works because the compiler | |
520 | will expand the "0" in braces to fill the size of the entire structure | |
521 | */ | |
522 | ||
523 | switch (type) { | |
524 | case TYREAL: | |
525 | case TYDREAL: | |
526 | nice_printf (outfile, "0.0,"); | |
527 | break; | |
528 | case TYCOMPLEX: | |
529 | case TYDCOMPLEX: | |
530 | nice_printf (outfile, "{0},"); | |
531 | break; | |
532 | case TYCHAR: | |
533 | nice_printf(outfile, " "); | |
534 | break; | |
535 | default: | |
536 | nice_printf (outfile, "0,"); | |
537 | break; | |
538 | } /* switch */ | |
539 | main_index++; | |
540 | } /* while index > main_index */ | |
541 | ||
542 | if (index < main_index) | |
543 | overlapping(); | |
544 | else switch (type) { | |
545 | case TYCHAR: | |
546 | { int this_char; | |
547 | ||
548 | if (k == ch_ar_dim) { | |
549 | nice_printf(outfile, "\" \""); | |
550 | k = 0; | |
551 | } | |
552 | this_char = (int) ((chainp) values->datap)-> | |
553 | nextp->nextp->datap; | |
554 | if ((int)((chainp)values->datap)->nextp->datap == TYBLANK) { | |
555 | main_index += this_char; | |
556 | k += this_char; | |
557 | while(--this_char >= 0) | |
558 | nice_printf(outfile, " "); | |
559 | values = values -> nextp; | |
560 | continue; | |
561 | } | |
562 | nice_printf(outfile, str_fmt[this_char], this_char); | |
563 | k++; | |
564 | } /* case TYCHAR */ | |
565 | break; | |
566 | ||
567 | case TYINT1: | |
568 | case TYSHORT: | |
569 | case TYLONG: | |
570 | #ifdef TYQUAD | |
571 | case TYQUAD: | |
572 | #endif | |
573 | case TYREAL: | |
574 | case TYDREAL: | |
575 | case TYLOGICAL: | |
576 | case TYLOGICAL1: | |
577 | case TYLOGICAL2: | |
578 | case TYCOMPLEX: | |
579 | case TYDCOMPLEX: | |
580 | make_one_const(type, &Const.Const, values); | |
581 | Const.vtype = type; | |
582 | Const.vstg = ONEOF(type, MSKREAL|MSKCOMPLEX) != 0; | |
583 | out_const(outfile, &Const); | |
584 | break; | |
585 | default: | |
586 | erri("wr_array_init: bad type '%d'", type); | |
587 | break; | |
588 | } /* switch */ | |
589 | values = values->nextp; | |
590 | ||
591 | main_index++; | |
592 | if (values && type != TYCHAR) | |
593 | nice_printf (outfile, ","); | |
594 | } /* while values */ | |
595 | ||
596 | if (type == TYCHAR) { | |
597 | nice_printf(outfile, "\""); | |
598 | } | |
599 | else | |
600 | nice_printf (outfile, " }"); | |
601 | } /* wr_array_init */ | |
602 | ||
603 | ||
604 | static void | |
605 | make_one_const(type, storage, values) | |
606 | int type; | |
607 | union Constant *storage; | |
608 | chainp values; | |
609 | { | |
610 | union Constant *Const; | |
611 | register char **L; | |
612 | ||
613 | if (type == TYCHAR) { | |
614 | char *str, *str_ptr; | |
615 | chainp v, prev; | |
616 | int b = 0, k, main_index = 0; | |
617 | ||
618 | /* Find the max length of init string, by finding the highest offset | |
619 | value stored in the list of initial values */ | |
620 | ||
621 | for(k = 1, prev = CHNULL, v = values; v; prev = v, v = v->nextp) | |
622 | ; | |
623 | if (prev != CHNULL) | |
624 | k = ((int) (((chainp) prev->datap)->datap)) + 2; | |
625 | /* + 2 above for null char at end */ | |
626 | str = Alloc (k); | |
627 | for (str_ptr = str; values; str_ptr++) { | |
628 | int index = (int) (((chainp) values->datap)->datap); | |
629 | ||
630 | if (index < main_index) | |
631 | overlapping(); | |
632 | while (index > main_index++) | |
633 | *str_ptr++ = ' '; | |
634 | ||
635 | k = (int) (((chainp) values->datap)->nextp->nextp->datap); | |
636 | if ((int)((chainp)values->datap)->nextp->datap == TYBLANK) { | |
637 | b = k; | |
638 | break; | |
639 | } | |
640 | *str_ptr = k; | |
641 | values = values -> nextp; | |
642 | } /* for str_ptr */ | |
643 | *str_ptr = '\0'; | |
644 | Const = storage; | |
645 | Const -> ccp = str; | |
646 | Const -> ccp1.blanks = b; | |
647 | charlen = str_ptr - str; | |
648 | } else { | |
649 | int i = 0; | |
650 | chainp vals; | |
651 | ||
652 | vals = ((chainp)values->datap)->nextp->nextp; | |
653 | if (vals) { | |
654 | L = (char **)storage; | |
655 | do L[i++] = vals->datap; | |
656 | while(vals = vals->nextp); | |
657 | } | |
658 | ||
659 | } /* else */ | |
660 | ||
661 | } /* make_one_const */ | |
662 | ||
663 | ||
664 | ||
665 | rdname (infile, vargroupp, name) | |
666 | FILE *infile; | |
667 | int *vargroupp; | |
668 | char *name; | |
669 | { | |
670 | register int i, c; | |
671 | ||
672 | c = getc (infile); | |
673 | ||
674 | if (feof (infile)) | |
675 | return NO; | |
676 | ||
677 | *vargroupp = c - '0'; | |
678 | for (i = 1;; i++) { | |
679 | if (i >= NAME_MAX) | |
680 | Fatal("rdname: oversize name"); | |
681 | c = getc (infile); | |
682 | if (feof (infile)) | |
683 | return NO; | |
684 | if (c == '\t') | |
685 | break; | |
686 | *name++ = c; | |
687 | } | |
688 | *name = 0; | |
689 | return YES; | |
690 | } /* rdname */ | |
691 | ||
692 | rdlong (infile, n) | |
693 | FILE *infile; | |
694 | ftnint *n; | |
695 | { | |
696 | register int c; | |
697 | ||
698 | for (c = getc (infile); !feof (infile) && isspace (c); c = getc (infile)) | |
699 | ; | |
700 | ||
701 | if (feof (infile)) | |
702 | return NO; | |
703 | ||
704 | for (*n = 0; isdigit (c); c = getc (infile)) | |
705 | *n = 10 * (*n) + c - '0'; | |
706 | return YES; | |
707 | } /* rdlong */ | |
708 | ||
709 | ||
710 | static int | |
711 | memno2info (memno, info) | |
712 | int memno; | |
713 | Namep *info; | |
714 | { | |
715 | chainp this_var; | |
716 | extern chainp new_vars; | |
717 | extern struct Hashentry *hashtab, *lasthash; | |
718 | struct Hashentry *entry; | |
719 | ||
720 | for (this_var = new_vars; this_var; this_var = this_var -> nextp) { | |
721 | Addrp var = (Addrp) this_var->datap; | |
722 | ||
723 | if (var == (Addrp) NULL) | |
724 | Fatal("memno2info: null variable"); | |
725 | else if (var -> tag != TADDR) | |
726 | Fatal("memno2info: bad tag"); | |
727 | if (memno == var -> memno) { | |
728 | *info = (Namep) var; | |
729 | return 1; | |
730 | } /* if memno == var -> memno */ | |
731 | } /* for this_var = new_vars */ | |
732 | ||
733 | for (entry = hashtab; entry < lasthash; ++entry) { | |
734 | Namep var = entry -> varp; | |
735 | ||
736 | if (var && var -> vardesc.varno == memno && var -> vstg == STGINIT) { | |
737 | *info = (Namep) var; | |
738 | return 0; | |
739 | } /* if entry -> vardesc.varno == memno */ | |
740 | } /* for entry = hashtab */ | |
741 | ||
742 | Fatal("memno2info: couldn't find memno"); | |
743 | return 0; | |
744 | } /* memno2info */ | |
745 | ||
746 | static chainp | |
747 | do_string(outfile, v, nloc) | |
748 | FILEP outfile; | |
749 | register chainp v; | |
750 | ftnint *nloc; | |
751 | { | |
752 | register chainp cp, v0; | |
753 | ftnint dloc, k, loc; | |
754 | unsigned long uk; | |
755 | char buf[8], *comma; | |
756 | ||
757 | nice_printf(outfile, "{"); | |
758 | cp = (chainp)v->datap; | |
759 | loc = (ftnint)cp->datap; | |
760 | comma = ""; | |
761 | for(v0 = v;;) { | |
762 | switch((int)cp->nextp->datap) { | |
763 | case TYBLANK: | |
764 | k = (ftnint)cp->nextp->nextp->datap; | |
765 | loc += k; | |
766 | while(--k >= 0) { | |
767 | nice_printf(outfile, "%s' '", comma); | |
768 | comma = ", "; | |
769 | } | |
770 | break; | |
771 | case TYCHAR: | |
772 | uk = (ftnint)cp->nextp->nextp->datap; | |
773 | sprintf(buf, chr_fmt[uk], uk); | |
774 | nice_printf(outfile, "%s'%s'", comma, buf); | |
775 | comma = ", "; | |
776 | loc++; | |
777 | break; | |
778 | default: | |
779 | goto done; | |
780 | } | |
781 | v0 = v; | |
782 | if (!(v = v->nextp)) | |
783 | break; | |
784 | cp = (chainp)v->datap; | |
785 | dloc = (ftnint)cp->datap; | |
786 | if (loc != dloc) | |
787 | break; | |
788 | } | |
789 | done: | |
790 | nice_printf(outfile, "}"); | |
791 | *nloc = loc; | |
792 | return v0; | |
793 | } | |
794 | ||
795 | static chainp | |
796 | Ado_string(outfile, v, nloc) | |
797 | FILEP outfile; | |
798 | register chainp v; | |
799 | ftnint *nloc; | |
800 | { | |
801 | register chainp cp, v0; | |
802 | ftnint dloc, k, loc; | |
803 | ||
804 | nice_printf(outfile, "\""); | |
805 | cp = (chainp)v->datap; | |
806 | loc = (ftnint)cp->datap; | |
807 | for(v0 = v;;) { | |
808 | switch((int)cp->nextp->datap) { | |
809 | case TYBLANK: | |
810 | k = (ftnint)cp->nextp->nextp->datap; | |
811 | loc += k; | |
812 | while(--k >= 0) | |
813 | nice_printf(outfile, " "); | |
814 | break; | |
815 | case TYCHAR: | |
816 | k = (ftnint)cp->nextp->nextp->datap; | |
817 | nice_printf(outfile, str_fmt[k], k); | |
818 | loc++; | |
819 | break; | |
820 | default: | |
821 | goto done; | |
822 | } | |
823 | v0 = v; | |
824 | if (!(v = v->nextp)) | |
825 | break; | |
826 | cp = (chainp)v->datap; | |
827 | dloc = (ftnint)cp->datap; | |
828 | if (loc != dloc) | |
829 | break; | |
830 | } | |
831 | done: | |
832 | nice_printf(outfile, "\""); | |
833 | *nloc = loc; | |
834 | return v0; | |
835 | } | |
836 | ||
837 | static char * | |
838 | Len(L,type) | |
839 | long L; | |
840 | int type; | |
841 | { | |
842 | static char buf[24]; | |
843 | if (L == 1 && type != TYCHAR) | |
844 | return ""; | |
845 | sprintf(buf, "[%ld]", L); | |
846 | return buf; | |
847 | } | |
848 | ||
849 | wr_equiv_init(outfile, memno, Values, iscomm) | |
850 | FILE *outfile; | |
851 | int memno; | |
852 | chainp *Values; | |
853 | int iscomm; | |
854 | { | |
855 | struct Equivblock *eqv; | |
856 | char *equiv_name (); | |
857 | int btype, curtype, dtype, filltype, filltype1, j, k, wasblank, xtype; | |
858 | static char Blank[] = ""; | |
859 | register char *comma = Blank; | |
860 | register chainp cp, v; | |
861 | chainp sentinel, values, v1, vlast; | |
862 | ftnint L, L1, dL, dloc, loc, loc0; | |
863 | union Constant Const; | |
864 | char imag_buf[50], real_buf[50]; | |
865 | int szshort = typesize[TYSHORT]; | |
866 | static char typepref[] = {0, 0, TYINT1, TYSHORT, TYLONG, | |
867 | #ifdef TYQUAD | |
868 | TYQUAD, | |
869 | #endif | |
870 | TYREAL, TYDREAL, TYREAL, TYDREAL, | |
871 | TYLOGICAL1, TYLOGICAL2, | |
872 | TYLOGICAL, TYCHAR}; | |
873 | static char basetype[] = {0, 0, TYCHAR, TYSHORT, TYLONG, | |
874 | #ifdef TYQUAD | |
875 | TYDREAL, | |
876 | #endif | |
877 | TYLONG, TYDREAL, TYLONG, TYDREAL, | |
878 | TYCHAR, TYSHORT, | |
879 | TYLONG, TYCHAR}; | |
880 | extern int htype; | |
881 | char *z; | |
882 | ||
883 | /* add sentinel */ | |
884 | if (iscomm) { | |
885 | L = extsymtab[memno].maxleng; | |
886 | xtype = extsymtab[memno].extype; | |
887 | } | |
888 | else { | |
889 | eqv = &eqvclass[memno]; | |
890 | L = eqv->eqvtop - eqv->eqvbottom; | |
891 | xtype = eqv->eqvtype; | |
892 | } | |
893 | ||
894 | if (halign && typealign[typepref[xtype]] < typealign[htype]) | |
895 | xtype = htype; | |
896 | *Values = values = revchain(vlast = *Values); | |
897 | ||
898 | if (xtype != TYCHAR) { | |
899 | ||
900 | /* unless the data include a value of the appropriate | |
901 | * type, we add an extra element in an attempt | |
902 | * to force correct alignment */ | |
903 | ||
904 | btype = basetype[xtype]; | |
905 | loc = 0; | |
906 | for(v = *Values;;v = v->nextp) { | |
907 | if (!v) { | |
908 | dtype = typepref[xtype]; | |
909 | z = ISREAL(dtype) ? cpstring("0.") : (char *)0; | |
910 | k = typesize[dtype]; | |
911 | if (j = L % k) | |
912 | L += k - j; | |
913 | v = mkchain((char *)L, | |
914 | mkchain((char *)LONG_CAST dtype, | |
915 | mkchain(z, CHNULL))); | |
916 | vlast = vlast->nextp = | |
917 | mkchain((char *)v, CHNULL); | |
918 | L += k; | |
919 | break; | |
920 | } | |
921 | cp = (chainp)v->datap; | |
922 | if (basetype[(int)cp->nextp->datap] == btype) | |
923 | break; | |
924 | dloc = (ftnint)cp->datap; | |
925 | L1 = dloc - loc; | |
926 | if (L1 > 0 | |
927 | && !(L1 % szshort) | |
928 | && !(loc % szshort) | |
929 | && btype <= type_choice[L1/szshort % 4] | |
930 | && btype <= type_choice[loc/szshort % 4]) | |
931 | break; | |
932 | dtype = (int)cp->nextp->datap; | |
933 | loc = dloc + dtype == TYBLANK | |
934 | ? (ftnint)cp->nextp->nextp->datap | |
935 | : typesize[dtype]; | |
936 | } | |
937 | } | |
938 | sentinel = mkchain((char *)L, mkchain((char *)TYERROR,CHNULL)); | |
939 | vlast->nextp = mkchain((char *)sentinel, CHNULL); | |
940 | ||
941 | /* use doublereal fillers only if there are doublereal values */ | |
942 | ||
943 | k = TYLONG; | |
944 | for(v = values; v; v = v->nextp) | |
945 | if (ONEOF((int)((chainp)v->datap)->nextp->datap, | |
946 | M(TYDREAL)|M(TYDCOMPLEX))) { | |
947 | k = TYDREAL; | |
948 | break; | |
949 | } | |
950 | type_choice[0] = k; | |
951 | ||
952 | nice_printf(outfile, "%sstruct {\n", iscomm ? "" : "static "); | |
953 | next_tab(outfile); | |
954 | loc = loc0 = k = 0; | |
955 | curtype = -1; | |
956 | for(v = values; v; v = v->nextp) { | |
957 | cp = (chainp)v->datap; | |
958 | dloc = (ftnint)cp->datap; | |
959 | L = dloc - loc; | |
960 | if (L < 0) { | |
961 | overlapping(); | |
962 | if ((int)cp->nextp->datap != TYERROR) { | |
963 | v1 = cp; | |
964 | frchain(&v1); | |
965 | v->datap = 0; | |
966 | } | |
967 | continue; | |
968 | } | |
969 | dtype = (int)cp->nextp->datap; | |
970 | if (dtype == TYBLANK) { | |
971 | dtype = TYCHAR; | |
972 | wasblank = 1; | |
973 | } | |
974 | else | |
975 | wasblank = 0; | |
976 | if (curtype != dtype || L > 0) { | |
977 | if (curtype != -1) { | |
978 | L1 = (loc - loc0)/dL; | |
979 | nice_printf(outfile, "%s e_%d%s;\n", | |
980 | typename[curtype], ++k, | |
981 | Len(L1,curtype)); | |
982 | } | |
983 | curtype = dtype; | |
984 | loc0 = dloc; | |
985 | } | |
986 | if (L > 0) { | |
987 | if (xtype == TYCHAR) | |
988 | filltype = TYCHAR; | |
989 | else { | |
990 | filltype = L % szshort ? TYCHAR | |
991 | : type_choice[L/szshort % 4]; | |
992 | filltype1 = loc % szshort ? TYCHAR | |
993 | : type_choice[loc/szshort % 4]; | |
994 | if (typesize[filltype] > typesize[filltype1]) | |
995 | filltype = filltype1; | |
996 | } | |
997 | L1 = L / typesize[filltype]; | |
998 | nice_printf(outfile, "%s fill_%d[%ld];\n", | |
999 | typename[filltype], ++k, L1); | |
1000 | loc = dloc; | |
1001 | } | |
1002 | if (wasblank) { | |
1003 | loc += (ftnint)cp->nextp->nextp->datap; | |
1004 | dL = 1; | |
1005 | } | |
1006 | else { | |
1007 | dL = typesize[dtype]; | |
1008 | loc += dL; | |
1009 | } | |
1010 | } | |
1011 | nice_printf(outfile, "} %s = { ", iscomm | |
1012 | ? extsymtab[memno].cextname | |
1013 | : equiv_name(eqvmemno, CNULL)); | |
1014 | loc = 0; | |
1015 | for(v = values; ; v = v->nextp) { | |
1016 | cp = (chainp)v->datap; | |
1017 | if (!cp) | |
1018 | continue; | |
1019 | dtype = (int)cp->nextp->datap; | |
1020 | if (dtype == TYERROR) | |
1021 | break; | |
1022 | dloc = (ftnint)cp->datap; | |
1023 | if (dloc > loc) { | |
1024 | nice_printf(outfile, "%s{0}", comma); | |
1025 | comma = ", "; | |
1026 | loc = dloc; | |
1027 | } | |
1028 | if (comma != Blank) | |
1029 | nice_printf(outfile, ", "); | |
1030 | comma = ", "; | |
1031 | if (dtype == TYCHAR || dtype == TYBLANK) { | |
1032 | v = Ansi == 1 ? Ado_string(outfile, v, &loc) | |
1033 | : do_string(outfile, v, &loc); | |
1034 | continue; | |
1035 | } | |
1036 | make_one_const(dtype, &Const, v); | |
1037 | switch(dtype) { | |
1038 | case TYLOGICAL: | |
1039 | case TYLOGICAL2: | |
1040 | case TYLOGICAL1: | |
1041 | if (Const.ci < 0 || Const.ci > 1) | |
1042 | errl( | |
1043 | "wr_equiv_init: unexpected logical value %ld", | |
1044 | Const.ci); | |
1045 | nice_printf(outfile, | |
1046 | Const.ci ? "TRUE_" : "FALSE_"); | |
1047 | break; | |
1048 | case TYINT1: | |
1049 | case TYSHORT: | |
1050 | case TYLONG: | |
1051 | #ifdef TYQUAD | |
1052 | case TYQUAD: | |
1053 | #endif | |
1054 | nice_printf(outfile, "%ld", Const.ci); | |
1055 | break; | |
1056 | case TYREAL: | |
1057 | nice_printf(outfile, "%s", | |
1058 | flconst(real_buf, Const.cds[0])); | |
1059 | break; | |
1060 | case TYDREAL: | |
1061 | nice_printf(outfile, "%s", Const.cds[0]); | |
1062 | break; | |
1063 | case TYCOMPLEX: | |
1064 | nice_printf(outfile, "%s, %s", | |
1065 | flconst(real_buf, Const.cds[0]), | |
1066 | flconst(imag_buf, Const.cds[1])); | |
1067 | break; | |
1068 | case TYDCOMPLEX: | |
1069 | nice_printf(outfile, "%s, %s", | |
1070 | Const.cds[0], Const.cds[1]); | |
1071 | break; | |
1072 | default: | |
1073 | erri("unexpected type %d in wr_equiv_init", | |
1074 | dtype); | |
1075 | } | |
1076 | loc += typesize[dtype]; | |
1077 | } | |
1078 | nice_printf(outfile, " };\n\n"); | |
1079 | prev_tab(outfile); | |
1080 | frchain(&sentinel); | |
1081 | } |