|
|
1.1 root 1: /****************************************************************
2: Copyright 1990, 1992, 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:
26: int oneof_stg (name, stg, mask)
27: Namep name;
28: int stg, mask;
29: {
30: if (stg == STGCOMMON && name) {
31: if ((mask & M(STGEQUIV)))
32: return name->vcommequiv;
33: if ((mask & M(STGCOMMON)))
34: return !name->vcommequiv;
35: }
36: return ONEOF(stg, mask);
37: }
38:
39:
40: /* op_assign -- given a binary opcode, return the associated assignment
41: operator */
42:
43: int op_assign (opcode)
44: int opcode;
45: {
46: int retval = -1;
47:
48: switch (opcode) {
49: case OPPLUS: retval = OPPLUSEQ; break;
50: case OPMINUS: retval = OPMINUSEQ; break;
51: case OPSTAR: retval = OPSTAREQ; break;
52: case OPSLASH: retval = OPSLASHEQ; break;
53: case OPMOD: retval = OPMODEQ; break;
54: case OPLSHIFT: retval = OPLSHIFTEQ; break;
55: case OPRSHIFT: retval = OPRSHIFTEQ; break;
56: case OPBITAND: retval = OPBITANDEQ; break;
57: case OPBITXOR: retval = OPBITXOREQ; break;
58: case OPBITOR: retval = OPBITOREQ; break;
59: default:
60: erri ("op_assign: bad opcode '%d'", opcode);
61: break;
62: } /* switch */
63:
64: return retval;
65: } /* op_assign */
66:
67:
68: char *
69: Alloc(n) /* error-checking version of malloc */
70: /* ckalloc initializes memory to 0; Alloc does not */
71: int n;
72: {
73: char errbuf[32];
74: register char *rv;
75:
76: rv = malloc(n);
77: if (!rv) {
78: sprintf(errbuf, "malloc(%d) failure!", n);
79: Fatal(errbuf);
80: }
81: return rv;
82: }
83:
84:
85: cpn(n, a, b)
86: register int n;
87: register char *a, *b;
88: {
89: while(--n >= 0)
90: *b++ = *a++;
91: }
92:
93:
94:
95: eqn(n, a, b)
96: register int n;
97: register char *a, *b;
98: {
99: while(--n >= 0)
100: if(*a++ != *b++)
101: return(NO);
102: return(YES);
103: }
104:
105:
106:
107:
108:
109:
110:
111: cmpstr(a, b, la, lb) /* compare two strings */
112: register char *a, *b;
113: ftnint la, lb;
114: {
115: register char *aend, *bend;
116: aend = a + la;
117: bend = b + lb;
118:
119:
120: if(la <= lb)
121: {
122: while(a < aend)
123: if(*a != *b)
124: return( *a - *b );
125: else
126: {
127: ++a;
128: ++b;
129: }
130:
131: while(b < bend)
132: if(*b != ' ')
133: return(' ' - *b);
134: else
135: ++b;
136: }
137:
138: else
139: {
140: while(b < bend)
141: if(*a != *b)
142: return( *a - *b );
143: else
144: {
145: ++a;
146: ++b;
147: }
148: while(a < aend)
149: if(*a != ' ')
150: return(*a - ' ');
151: else
152: ++a;
153: }
154: return(0);
155: }
156:
157:
158: /* hookup -- Same as LISP NCONC, that is a destructive append of two lists */
159:
160: chainp hookup(x,y)
161: register chainp x, y;
162: {
163: register chainp p;
164:
165: if(x == NULL)
166: return(y);
167:
168: for(p = x ; p->nextp ; p = p->nextp)
169: ;
170: p->nextp = y;
171: return(x);
172: }
173:
174:
175:
176: struct Listblock *mklist(p)
177: chainp p;
178: {
179: register struct Listblock *q;
180:
181: q = ALLOC(Listblock);
182: q->tag = TLIST;
183: q->listp = p;
184: return(q);
185: }
186:
187:
188: chainp mkchain(p,q)
189: register char * p;
190: register chainp q;
191: {
192: register chainp r;
193:
194: if(chains)
195: {
196: r = chains;
197: chains = chains->nextp;
198: }
199: else
200: r = ALLOC(Chain);
201:
202: r->datap = p;
203: r->nextp = q;
204: return(r);
205: }
206:
207: chainp
208: revchain(next)
209: register chainp next;
210: {
211: register chainp p, prev = 0;
212:
213: while(p = next) {
214: next = p->nextp;
215: p->nextp = prev;
216: prev = p;
217: }
218: return prev;
219: }
220:
221:
222: /* addunder -- turn a cvarname into an external name */
223: /* The cvarname may already end in _ (to avoid C keywords); */
224: /* if not, it has room for appending an _. */
225:
226: char *
227: addunder(s)
228: register char *s;
229: {
230: register int c, i;
231: char *s0 = s;
232:
233: i = 0;
234: while(c = *s++)
235: if (c == '_')
236: i++;
237: else
238: i = 0;
239: if (!i) {
240: *s-- = 0;
241: *s = '_';
242: }
243: return( s0 );
244: }
245:
246:
247: /* copyn -- return a new copy of the input Fortran-string */
248:
249: char *copyn(n, s)
250: register int n;
251: register char *s;
252: {
253: register char *p, *q;
254:
255: p = q = (char *) Alloc(n);
256: while(--n >= 0)
257: *q++ = *s++;
258: return(p);
259: }
260:
261:
262:
263: /* copys -- return a new copy of the input C-string */
264:
265: char *copys(s)
266: char *s;
267: {
268: return( copyn( strlen(s)+1 , s) );
269: }
270:
271:
272:
273: /* convci -- Convert Fortran-string to integer; assumes that input is a
274: legal number, with no trailing blanks */
275:
276: ftnint convci(n, s)
277: register int n;
278: register char *s;
279: {
280: ftnint sum;
281: sum = 0;
282: while(n-- > 0)
283: sum = 10*sum + (*s++ - '0');
284: return(sum);
285: }
286:
287: /* convic - Convert Integer constant to string */
288:
289: char *convic(n)
290: ftnint n;
291: {
292: static char s[20];
293: register char *t;
294:
295: s[19] = '\0';
296: t = s+19;
297:
298: do {
299: *--t = '0' + n%10;
300: n /= 10;
301: } while(n > 0);
302:
303: return(t);
304: }
305:
306:
307:
308: /* mkname -- add a new identifier to the environment, including the closed
309: hash table. */
310:
311: Namep mkname(s)
312: register char *s;
313: {
314: struct Hashentry *hp;
315: register Namep q;
316: register int c, hash, i;
317: register char *t;
318: char *s0;
319: char errbuf[64];
320:
321: hash = i = 0;
322: s0 = s;
323: while(c = *s++) {
324: hash += c;
325: if (c == '_')
326: i = 2;
327: }
328: if (!i && in_vector(s0,c_keywords,n_keywords) >= 0)
329: i = 1;
330: hash %= maxhash;
331:
332: /* Add the name to the closed hash table */
333:
334: hp = hashtab + hash;
335:
336: while(q = hp->varp)
337: if( hash == hp->hashval && !strcmp(s0,q->fvarname) )
338: return(q);
339: else if(++hp >= lasthash)
340: hp = hashtab;
341:
342: if(++nintnames >= maxhash-1)
343: many("names", 'n', maxhash); /* Fatal error */
344: hp->varp = q = ALLOC(Nameblock);
345: hp->hashval = hash;
346: q->tag = TNAME; /* TNAME means the tag type is NAME */
347: c = s - s0;
348: if (c > 7 && noextflag) {
349: sprintf(errbuf, "\"%.35s%s\" over 6 characters long", s0,
350: c > 36 ? "..." : "");
351: errext(errbuf);
352: }
353: q->fvarname = strcpy(mem(c,0), s0);
354: t = q->cvarname = mem(c + i + 1, 0);
355: s = s0;
356: /* add __ to the end of any name containing _ and to any C keyword */
357: while(*t = *s++)
358: t++;
359: if (i) {
360: do *t++ = '_';
361: while(--i > 0);
362: *t = 0;
363: }
364: return(q);
365: }
366:
367:
368: struct Labelblock *mklabel(l)
369: ftnint l;
370: {
371: register struct Labelblock *lp;
372:
373: if(l <= 0)
374: return(NULL);
375:
376: for(lp = labeltab ; lp < highlabtab ; ++lp)
377: if(lp->stateno == l)
378: return(lp);
379:
380: if(++highlabtab > labtabend)
381: many("statement labels", 's', maxstno);
382:
383: lp->stateno = l;
384: lp->labelno = newlabel();
385: lp->blklevel = 0;
386: lp->labused = NO;
387: lp->fmtlabused = NO;
388: lp->labdefined = NO;
389: lp->labinacc = NO;
390: lp->labtype = LABUNKNOWN;
391: lp->fmtstring = 0;
392: return(lp);
393: }
394:
395:
396: newlabel()
397: {
398: return( ++lastlabno );
399: }
400:
401:
402: /* this label appears in a branch context */
403:
404: struct Labelblock *execlab(stateno)
405: ftnint stateno;
406: {
407: register struct Labelblock *lp;
408:
409: if(lp = mklabel(stateno))
410: {
411: if(lp->labinacc)
412: warn1("illegal branch to inner block, statement label %s",
413: convic(stateno) );
414: else if(lp->labdefined == NO)
415: lp->blklevel = blklevel;
416: if(lp->labtype == LABFORMAT)
417: err("may not branch to a format");
418: else
419: lp->labtype = LABEXEC;
420: }
421: else
422: execerr("illegal label %s", convic(stateno));
423:
424: return(lp);
425: }
426:
427:
428: /* find or put a name in the external symbol table */
429:
430: Extsym *mkext(f,s)
431: char *f, *s;
432: {
433: Extsym *p;
434:
435: for(p = extsymtab ; p<nextext ; ++p)
436: if(!strcmp(s,p->cextname))
437: return( p );
438:
439: if(nextext >= lastext)
440: many("external symbols", 'x', maxext);
441:
442: nextext->fextname = strcpy(gmem(strlen(f)+1,0), f);
443: nextext->cextname = f == s
444: ? nextext->fextname
445: : strcpy(gmem(strlen(s)+1,0), s);
446: nextext->extstg = STGUNKNOWN;
447: nextext->extp = 0;
448: nextext->allextp = 0;
449: nextext->extleng = 0;
450: nextext->maxleng = 0;
451: nextext->extinit = 0;
452: nextext->curno = nextext->maxno = 0;
453: return( nextext++ );
454: }
455:
456:
457: Addrp builtin(t, s, dbi)
458: int t, dbi;
459: char *s;
460: {
461: register Extsym *p;
462: register Addrp q;
463: extern chainp used_builtins;
464:
465: p = mkext(s,s);
466: if(p->extstg == STGUNKNOWN)
467: p->extstg = STGEXT;
468: else if(p->extstg != STGEXT)
469: {
470: errstr("improper use of builtin %s", s);
471: return(0);
472: }
473:
474: q = ALLOC(Addrblock);
475: q->tag = TADDR;
476: q->vtype = t;
477: q->vclass = CLPROC;
478: q->vstg = STGEXT;
479: q->memno = p - extsymtab;
480: q->dbl_builtin = dbi;
481:
482: /* A NULL pointer here tells you to use memno to check the external
483: symbol table */
484:
485: q -> uname_tag = UNAM_EXTERN;
486:
487: /* Add to the list of used builtins */
488:
489: if (dbi >= 0)
490: add_extern_to_list (q, &used_builtins);
491: return(q);
492: }
493:
494:
495:
496: add_extern_to_list (addr, list_store)
497: Addrp addr;
498: chainp *list_store;
499: {
500: chainp last = CHNULL;
501: chainp list;
502: int memno;
503:
504: if (list_store == (chainp *) NULL || addr == (Addrp) NULL)
505: return;
506:
507: list = *list_store;
508: memno = addr -> memno;
509:
510: for (;list; last = list, list = list -> nextp) {
511: Addrp this = (Addrp) (list -> datap);
512:
513: if (this -> tag == TADDR && this -> uname_tag == UNAM_EXTERN &&
514: this -> memno == memno)
515: return;
516: } /* for */
517:
518: if (*list_store == CHNULL)
519: *list_store = mkchain((char *)cpexpr((expptr)addr), CHNULL);
520: else
521: last->nextp = mkchain((char *)cpexpr((expptr)addr), CHNULL);
522:
523: } /* add_extern_to_list */
524:
525:
526: frchain(p)
527: register chainp *p;
528: {
529: register chainp q;
530:
531: if(p==0 || *p==0)
532: return;
533:
534: for(q = *p; q->nextp ; q = q->nextp)
535: ;
536: q->nextp = chains;
537: chains = *p;
538: *p = 0;
539: }
540:
541: void
542: frexchain(p)
543: register chainp *p;
544: {
545: register chainp q, r;
546:
547: if (q = *p) {
548: for(;;q = r) {
549: frexpr((expptr)q->datap);
550: if (!(r = q->nextp))
551: break;
552: }
553: q->nextp = chains;
554: chains = *p;
555: *p = 0;
556: }
557: }
558:
559:
560: tagptr cpblock(n,p)
561: register int n;
562: register char * p;
563: {
564: register ptr q;
565:
566: memcpy((char *)(q = ckalloc(n)), (char *)p, n);
567: return( (tagptr) q);
568: }
569:
570:
571:
572: ftnint lmax(a, b)
573: ftnint a, b;
574: {
575: return( a>b ? a : b);
576: }
577:
578: ftnint lmin(a, b)
579: ftnint a, b;
580: {
581: return(a < b ? a : b);
582: }
583:
584:
585:
586:
587: maxtype(t1, t2)
588: int t1, t2;
589: {
590: int t;
591:
592: t = t1 >= t2 ? t1 : t2;
593: if(t==TYCOMPLEX && (t1==TYDREAL || t2==TYDREAL) )
594: t = TYDCOMPLEX;
595: return(t);
596: }
597:
598:
599:
600: /* return log base 2 of n if n a power of 2; otherwise -1 */
601: log_2(n)
602: ftnint n;
603: {
604: int k;
605:
606: /* trick based on binary representation */
607:
608: if(n<=0 || (n & (n-1))!=0)
609: return(-1);
610:
611: for(k = 0 ; n >>= 1 ; ++k)
612: ;
613: return(k);
614: }
615:
616:
617:
618: frrpl()
619: {
620: struct Rplblock *rp;
621:
622: while(rpllist)
623: {
624: rp = rpllist->rplnextp;
625: free( (charptr) rpllist);
626: rpllist = rp;
627: }
628: }
629:
630:
631:
632: /* Call a Fortran function with an arbitrary list of arguments */
633:
634: int callk_kludge;
635:
636: expptr callk(type, name, args)
637: int type;
638: char *name;
639: chainp args;
640: {
641: register expptr p;
642:
643: p = mkexpr(OPCALL,
644: (expptr)builtin(callk_kludge ? callk_kludge : type, name, 0),
645: (expptr)args);
646: p->exprblock.vtype = type;
647: return(p);
648: }
649:
650:
651:
652: expptr call4(type, name, arg1, arg2, arg3, arg4)
653: int type;
654: char *name;
655: expptr arg1, arg2, arg3, arg4;
656: {
657: struct Listblock *args;
658: args = mklist( mkchain((char *)arg1,
659: mkchain((char *)arg2,
660: mkchain((char *)arg3,
661: mkchain((char *)arg4, CHNULL)) ) ) );
662: return( callk(type, name, (chainp)args) );
663: }
664:
665:
666:
667:
668: expptr call3(type, name, arg1, arg2, arg3)
669: int type;
670: char *name;
671: expptr arg1, arg2, arg3;
672: {
673: struct Listblock *args;
674: args = mklist( mkchain((char *)arg1,
675: mkchain((char *)arg2,
676: mkchain((char *)arg3, CHNULL) ) ) );
677: return( callk(type, name, (chainp)args) );
678: }
679:
680:
681:
682:
683:
684: expptr call2(type, name, arg1, arg2)
685: int type;
686: char *name;
687: expptr arg1, arg2;
688: {
689: struct Listblock *args;
690:
691: args = mklist( mkchain((char *)arg1, mkchain((char *)arg2, CHNULL) ) );
692: return( callk(type,name, (chainp)args) );
693: }
694:
695:
696:
697:
698: expptr call1(type, name, arg)
699: int type;
700: char *name;
701: expptr arg;
702: {
703: return( callk(type,name, (chainp)mklist(mkchain((char *)arg,CHNULL)) ));
704: }
705:
706:
707: expptr call0(type, name)
708: int type;
709: char *name;
710: {
711: return( callk(type, name, CHNULL) );
712: }
713:
714:
715:
716: struct Impldoblock *mkiodo(dospec, list)
717: chainp dospec, list;
718: {
719: register struct Impldoblock *q;
720:
721: q = ALLOC(Impldoblock);
722: q->tag = TIMPLDO;
723: q->impdospec = dospec;
724: q->datalist = list;
725: return(q);
726: }
727:
728:
729:
730:
731: /* ckalloc -- Allocate 1 memory unit of size n, checking for out of
732: memory error */
733:
734: ptr ckalloc(n)
735: register int n;
736: {
737: register ptr p;
738: p = (ptr)calloc(1, (unsigned) n);
739: if (p || !n)
740: return(p);
741: fprintf(stderr, "failing to get %d bytes\n",n);
742: Fatal("out of memory");
743: /* NOT REACHED */ return 0;
744: }
745:
746:
747:
748: isaddr(p)
749: register expptr p;
750: {
751: if(p->tag == TADDR)
752: return(YES);
753: if(p->tag == TEXPR)
754: switch(p->exprblock.opcode)
755: {
756: case OPCOMMA:
757: return( isaddr(p->exprblock.rightp) );
758:
759: case OPASSIGN:
760: case OPASSIGNI:
761: case OPPLUSEQ:
762: case OPMINUSEQ:
763: case OPSLASHEQ:
764: case OPMODEQ:
765: case OPLSHIFTEQ:
766: case OPRSHIFTEQ:
767: case OPBITANDEQ:
768: case OPBITXOREQ:
769: case OPBITOREQ:
770: return( isaddr(p->exprblock.leftp) );
771: }
772: return(NO);
773: }
774:
775:
776:
777:
778: isstatic(p)
779: register expptr p;
780: {
781: extern int useauto;
782: if(p->headblock.vleng && !ISCONST(p->headblock.vleng))
783: return(NO);
784:
785: switch(p->tag)
786: {
787: case TCONST:
788: return(YES);
789:
790: case TADDR:
791: if(ONEOF(p->addrblock.vstg,MSKSTATIC) &&
792: ISCONST(p->addrblock.memoffset) && !useauto)
793: return(YES);
794:
795: default:
796: return(NO);
797: }
798: }
799:
800:
801:
802: /* addressable -- return True iff it is a constant value, or can be
803: referenced by constant values */
804:
805: addressable(p)
806: register expptr p;
807: {
808: switch(p->tag)
809: {
810: case TCONST:
811: return(YES);
812:
813: case TADDR:
814: return( addressable(p->addrblock.memoffset) );
815:
816: default:
817: return(NO);
818: }
819: }
820:
821:
822: /* isnegative_const -- returns true if the constant is negative. Returns
823: false for imaginary and nonnumeric constants */
824:
825: int isnegative_const (cp)
826: struct Constblock *cp;
827: {
828: int retval;
829:
830: if (cp == NULL)
831: return 0;
832:
833: switch (cp -> vtype) {
834: case TYINT1:
835: case TYSHORT:
836: case TYLONG:
837: #ifdef TYQUAD
838: case TYQUAD:
839: #endif
840: retval = cp -> Const.ci < 0;
841: break;
842: case TYREAL:
843: case TYDREAL:
844: retval = cp->vstg ? *cp->Const.cds[0] == '-'
845: : cp->Const.cd[0] < 0.0;
846: break;
847: default:
848:
849: retval = 0;
850: break;
851: } /* switch */
852:
853: return retval;
854: } /* isnegative_const */
855:
856: negate_const(cp)
857: Constp cp;
858: {
859: if (cp == (struct Constblock *) NULL)
860: return;
861:
862: switch (cp -> vtype) {
863: case TYINT1:
864: case TYSHORT:
865: case TYLONG:
866: #ifdef TYQUAD
867: case TYQUAD:
868: #endif
869: cp -> Const.ci = - cp -> Const.ci;
870: break;
871: case TYCOMPLEX:
872: case TYDCOMPLEX:
873: if (cp->vstg)
874: switch(*cp->Const.cds[1]) {
875: case '-':
876: ++cp->Const.cds[1];
877: break;
878: case '0':
879: break;
880: default:
881: --cp->Const.cds[1];
882: }
883: else
884: cp->Const.cd[1] = -cp->Const.cd[1];
885: /* no break */
886: case TYREAL:
887: case TYDREAL:
888: if (cp->vstg)
889: switch(*cp->Const.cds[0]) {
890: case '-':
891: ++cp->Const.cds[0];
892: break;
893: case '0':
894: break;
895: default:
896: --cp->Const.cds[0];
897: }
898: else
899: cp->Const.cd[0] = -cp->Const.cd[0];
900: break;
901: case TYCHAR:
902: case TYLOGICAL1:
903: case TYLOGICAL2:
904: case TYLOGICAL:
905: erri ("negate_const: can't negate type '%d'", cp -> vtype);
906: break;
907: default:
908: erri ("negate_const: bad type '%d'",
909: cp -> vtype);
910: break;
911: } /* switch */
912: } /* negate_const */
913:
914: ffilecopy (infp, outfp)
915: FILE *infp, *outfp;
916: {
917: while (!feof (infp)) {
918: register c = getc (infp);
919: if (!feof (infp))
920: putc (c, outfp);
921: } /* while */
922: } /* ffilecopy */
923:
924:
925: /* in_vector -- verifies whether str is in c_keywords.
926: If so, the index is returned else -1 is returned.
927: c_keywords must be in alphabetical order (as defined by strcmp).
928: */
929:
930: int in_vector(str, keywds, n)
931: char *str; char **keywds; register int n;
932: {
933: register char **K = keywds;
934: register int n1, t;
935:
936: do {
937: n1 = n >> 1;
938: if (!(t = strcmp(str, K[n1])))
939: return K - keywds + n1;
940: if (t < 0)
941: n = n1;
942: else {
943: n -= ++n1;
944: K += n1;
945: }
946: }
947: while(n > 0);
948:
949: return -1;
950: } /* in_vector */
951:
952:
953: int is_negatable (Const)
954: Constp Const;
955: {
956: int retval = 0;
957: if (Const != (Constp) NULL)
958: switch (Const -> vtype) {
959: case TYINT1:
960: retval = Const -> Const.ci >= -BIGGEST_CHAR;
961: break;
962: case TYSHORT:
963: retval = Const -> Const.ci >= -BIGGEST_SHORT;
964: break;
965: case TYLONG:
966: #ifdef TYQUAD
967: case TYQUAD:
968: #endif
969: retval = Const -> Const.ci >= -BIGGEST_LONG;
970: break;
971: case TYREAL:
972: case TYDREAL:
973: case TYCOMPLEX:
974: case TYDCOMPLEX:
975: retval = 1;
976: break;
977: case TYLOGICAL1:
978: case TYLOGICAL2:
979: case TYLOGICAL:
980: case TYCHAR:
981: case TYSUBR:
982: default:
983: retval = 0;
984: break;
985: } /* switch */
986:
987: return retval;
988: } /* is_negatable */
989:
990: backup(fname, bname)
991: char *fname, *bname;
992: {
993: FILE *b, *f;
994: static char couldnt[] = "Couldn't open %.80s";
995:
996: if (!(f = fopen(fname, binread))) {
997: warn1(couldnt, fname);
998: return;
999: }
1000: if (!(b = fopen(bname, binwrite))) {
1001: warn1(couldnt, bname);
1002: return;
1003: }
1004: ffilecopy(f, b);
1005: fclose(f);
1006: fclose(b);
1007: }
1008:
1009:
1010: /* struct_eq -- returns YES if structures have the same field names and
1011: types, NO otherwise */
1012:
1013: int struct_eq (s1, s2)
1014: chainp s1, s2;
1015: {
1016: struct Dimblock *d1, *d2;
1017: Constp cp1, cp2;
1018:
1019: if (s1 == CHNULL && s2 == CHNULL)
1020: return YES;
1021: for(; s1 && s2; s1 = s1->nextp, s2 = s2->nextp) {
1022: register Namep v1 = (Namep) s1 -> datap;
1023: register Namep v2 = (Namep) s2 -> datap;
1024:
1025: if (v1 == (Namep) NULL || v1 -> tag != TNAME ||
1026: v2 == (Namep) NULL || v2 -> tag != TNAME)
1027: return NO;
1028:
1029: if (v1->vtype != v2->vtype || v1->vclass != v2->vclass
1030: || strcmp(v1->fvarname, v2->fvarname))
1031: return NO;
1032:
1033: /* compare dimensions (needed for comparing COMMON blocks) */
1034:
1035: if (d1 = v1->vdim) {
1036: if (!(cp1 = (Constp)d1->nelt) || cp1->tag != TCONST)
1037: return NO;
1038: if (!(d2 = v2->vdim))
1039: if (cp1->Const.ci == 1)
1040: continue;
1041: else
1042: return NO;
1043: if (!(cp2 = (Constp)d2->nelt) || cp2->tag != TCONST
1044: || cp1->Const.ci != cp2->Const.ci)
1045: return NO;
1046: }
1047: else if ((d2 = v2->vdim) && (!(cp2 = (Constp)d2->nelt)
1048: || cp2->tag != TCONST
1049: || cp2->Const.ci != 1))
1050: return NO;
1051: } /* while s1 != CHNULL && s2 != CHNULL */
1052:
1053: return s1 == CHNULL && s2 == CHNULL;
1054: } /* struct_eq */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.