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 EXNULL (union Expression *)0
31 LOCAL dobss(), docomleng(), docommon(), doentry(),
32 epicode(), nextarg(), retval();
34 static char Blank[] = BLANKCOMMON;
36 static char *postfix[] = { "h", "i", "r", "d", "c", "z", "i" };
39 int prev_proc, proc_argchanges, proc_protochanges;
54 e = &extsymtab[q->vardesc.varno];
55 if (!(at = e->arginfo)) {
59 else if (at->changes & 2 && qtype != TYUNKNOWN)
62 if (type1 == TYUNKNOWN)
64 if (qtype == TYUNKNOWN)
73 sprintf(buf, "%.90s: inconsistent declarations:\n\
74 here %s%s, previously %s%s.", q->fvarname, ftn_types[qtype],
75 qtype == TYSUBR ? "" : " function",
76 ftn_types[type1], type1 == TYSUBR ? "" : " function");
90 q->uname_tag = UNAM_IDENT;
94 q->uname_tag = UNAM_CHARP;
95 q->user.Charp = t = mem(k+1, 0);
101 fix_entry_returns() /* for multiple entry points */
105 struct Entrypoint *e;
108 e = entries = (struct Entrypoint *)revchain((chainp)entries);
109 allargs = revchain(allargs);
113 /* TYLOGICAL should have been turned into TYLONG or TYSHORT by now */
115 for(i = TYSHORT; i <= TYLOGICAL; i++)
117 sprintf(a->user.ident, "(*ret_val).%s",
133 while(e = e->entnextp);
137 putentries(outfile) /* put out wrappers for multiple entries */
140 char base[IDENT_LEN];
141 struct Entrypoint *e;
142 Namep *A, *Ae, *Ae1, **Alp, *a, **a1, np;
143 chainp args, lengths, length_comp();
144 void listargs(), list_arg_types();
145 int i, k, mt, nL, type;
146 extern char *dfltarg[], **dfltproc;
148 nL = (nallargs + nallchargs) * sizeof(Namep *);
149 A = (Namep *)ckalloc(nL + nallargs*sizeof(Namep **));
151 Alp = (Namep **)(Ae1 = Ae + nallchargs);
153 for(a1 = Alp, args = allargs; args; a1++, args = args->nextp) {
154 np = (Namep)args->datap;
155 if (np->vtype == TYCHAR && np->vclass != CLPROC)
162 sprintf(base, "%s0_", e->enamep->cvarname);
165 lengths = length_comp(e, 0);
166 proctype = type = np->vtype;
168 protowrite(protofile, type, np->cvarname, e, lengths);
169 nice_printf(outfile, "\n%s ", c_type_decl(type, 1));
170 nice_printf(outfile, "%s", np->cvarname);
172 listargs(outfile, e, 0, lengths);
173 nice_printf(outfile, "\n");
175 list_arg_types(outfile, e, lengths, 0, "\n");
176 nice_printf(outfile, "{\n");
181 "Multitype ret_val;\n%s(%d, &ret_val",
183 else if (ISCOMPLEX(type))
184 nice_printf(outfile, "%s(%d,%s", base, k,
185 xretslot[type]->user.ident); /*)*/
186 else if (type == TYCHAR)
188 "%s(%d, ret_val, ret_val_len", base, k); /*)*/
190 nice_printf(outfile, "return %s(%d", base, k); /*)*/
192 memset((char *)A, 0, nL);
193 for(args = e->arglist; args; args = args->nextp) {
194 np = (Namep)args->datap;
196 if (np->vtype == TYCHAR && np->vclass != CLPROC)
197 *Alp[np->argno] = np;
200 for(a = A; a < Ae; a++, args = args->nextp)
201 nice_printf(outfile, ", %s", (np = *a)
203 : ((Namep)args->datap)->vclass == CLPROC
204 ? dfltproc[((Namep)args->datap)->vtype]
205 : dfltarg[((Namep)args->datap)->vtype]);
208 nice_printf(outfile, ", %s_len", np->fvarname);
210 nice_printf(outfile, ", (ftnint)0");
211 nice_printf(outfile, /*(*/ ");\n");
213 if (type == TYCOMPLEX)
215 "r_v->r = ret_val.c.r; r_v->i = ret_val.c.i;\nreturn 0;\n");
216 else if (type == TYDCOMPLEX)
218 "r_v->r = ret_val.z.r; r_v->i = ret_val.z.i;\nreturn 0;\n");
219 else nice_printf(outfile, "return ret_val.%s;\n",
220 postfix[type-TYSHORT]);
222 else if (ONEOF(type, M(TYCHAR)|M(TYCOMPLEX)|M(TYDCOMPLEX)))
223 nice_printf(outfile, "return 0;\n");
224 nice_printf(outfile, "}\n");
227 while(e = e->entnextp);
235 struct Entrypoint *e = entries;
238 nice_printf(outfile, "switch(n__) {\n");
240 while(e = e->entnextp)
241 nice_printf(outfile, "case %d: goto %s;\n", ++k,
242 user_label((long)(extsymtab - e->entryname - 1)));
243 nice_printf(outfile, "}\n\n");
247 /* start a new procedure */
251 if(parstate != OUTSIDE)
253 execerr("missing end statement", CNULL);
258 procclass = CLMAIN; /* default */
265 register Argtypes *at;
267 /* arrange to get correct count of prototypes that would
268 change by running f2c again */
270 if (prev_proc && proc_argchanges)
272 prev_proc = proc_argchanges = 0;
273 for(cp = new_procs; cp; cp = cp->nextp)
274 if (at = ((Namep)cp->datap)->arginfo)
279 /* end of procedure. generate variables, epilogs, and prologs */
283 struct Labelblock *lp;
286 if(parstate < INDATA)
289 err("DO loop or BLOCK IF not closed");
290 for(lp = labeltab ; lp < labtabend ; ++lp)
291 if(lp->stateno!=0 && lp->labdefined==NO)
292 errstr("missing statement label %s",
293 convic(lp->stateno) );
295 /* Save copies of the common variables in extptr -> allextp */
297 for (ext = extsymtab; ext < nextext; ext++)
298 if (ext -> extstg == STGCOMMON && ext -> extp) {
299 extern int usedefsforcommon;
301 /* Write out the abbreviations for common block reference */
303 copy_data (ext -> extp);
304 if (usedefsforcommon) {
305 wr_abbrevs (c_file, 1, ext -> extp);
306 ext -> used_here = 1;
309 ext -> extp = CHNULL;
323 procinit(); /* clean up for next procedure */
328 /* End of declaration section of procedure. Allocate storage. */
332 register struct Entrypoint *ep;
333 struct Entrypoint *ep0;
334 extern void freetemps();
336 extern char *err_proc;
337 static char comblks[] = "common blocks";
342 /* Now the hash table entries for fields of common blocks have STGCOMMON,
343 vdcldone, voffset, and varno. And the common blocks themselves have
344 their full sizes in extleng. */
346 err_proc = "equivalences";
352 /* This implies that entry points in the declarations are buffered in
353 entries but not written out */
355 err_proc = "entries";
356 if (ep = ep0 = (struct Entrypoint *)revchain((chainp)entries)) {
357 /* entries could be 0 in case of an error */
359 while(ep = ep->entnextp);
360 entries = (struct Entrypoint *)revchain((chainp)ep0);
368 for(cp = earlylabs = revchain(earlylabs); cp; cp = cp->nextp)
369 p1_label((long)cp->datap);
374 /* ROUTINES CALLED WHEN ENCOUNTERING ENTRY POINTS */
376 /* Main program or Block data */
378 startproc(progname, class)
382 register struct Entrypoint *p;
384 p = ALLOC(Entrypoint);
385 if(class == CLMAIN) {
386 puthead(CNULL, CLMAIN);
388 strcpy (main_alias, progname->cextname);
390 puthead(CNULL, CLBLOCK);
392 newentry( mkname(" MAIN"), 0 )->extinit = 1;
393 p->entryname = progname;
397 fprintf(diagfile, " %s", (class==CLMAIN ? "MAIN" : "BLOCK DATA") );
399 fprintf(diagfile, " %s", progname->fextname);
400 procname = progname->cextname;
402 fprintf(diagfile, ":\n");
406 /* subroutine or function statement */
408 Extsym *newentry(v, substmsg)
413 char buf[128], badname[64];
415 static char already[] = "external name already used";
417 p = mkext(v->fvarname, addunder(v->cvarname));
419 if(p->extinit || ! ONEOF(p->extstg, M(STGUNKNOWN)|M(STGEXT)) )
421 sprintf(badname, "%s_bad%d", v->fvarname, ++nbad);
423 sprintf(buf,"%s\n\tsubstituting \"%s\"",
429 p = mkext(v->fvarname, badname);
432 v->vprocclass = PTHISPROC;
434 if (p->extstg == STGEXT)
439 v->vardesc.varno = p - extsymtab;
444 entrypt(class, type, length, entry, args)
451 register struct Entrypoint *p;
455 puthead( procname = entry->cextname, class);
457 fprintf(diagfile, " entry ");
458 fprintf(diagfile, " %s:\n", entry->fextname);
460 q = mkname(entry->fextname);
464 type = lengtype(type, length);
469 procleng = type == TYCHAR ? length : 0;
472 p = ALLOC(Entrypoint);
474 p->entnextp = entries;
477 p->entryname = entry;
478 p->arglist = revchain(args);
484 if(proctype == TYSUBR)
490 settype(q, type, length);
491 q->vprocclass = PTHISPROC;
492 /* hold all initial entry points till end of declarations */
493 if(parstate >= INDATA)
497 /* generate epilogs */
499 /* epicode -- write out the proper function return mechanism at the end of
500 the procedure declaration. Handles multiple return value types, as
501 well as cooercion into the proper value */
505 extern int lastwasbranch;
507 if(procclass==CLPROC)
512 /* Return a zero only when the alternate return mechanism has been
513 specified in the function header */
515 if (substars && lastwasbranch == NO)
516 p1_subr_ret (ICON(0));
518 else if (!multitype && lastwasbranch == NO)
525 /* generate code to return value of type t */
546 p = (Addrp) cpexpr((expptr)retslot);
548 p1_subr_ret (mkconv (t, fixtype((expptr)p)));
552 badtype("retval", t);
557 /* Do parameter adjustments */
562 prolog(outfile, allargs);
568 /* Finish bound computations now that all variables are declared.
569 * This used to be in setbound(), but under -u the following incurred
570 * an erroneous error message:
571 * subroutine foo(x,n)
580 register struct Dimblock *p;
583 extern expptr make_int_expr();
589 for(i = 0; i < nd; i++)
590 if (q = p->dims[i].dimexpr)
591 p->dims[i].dimexpr = make_int_expr(putx(fixtype(q)));
593 p->basexpr = make_int_expr(putx(fixtype(q)));
600 { errstr("duplicate argument %.80s", q->fvarname); }
603 manipulate argument lists (allocate argument slot positions)
604 * keep track of return types and labels
608 struct Entrypoint *ep;
616 extern char dflttype[26];
617 Extsym *entryname = ep->entryname;
620 p1_label((long)(extsymtab - entryname - 1));
622 /* The main program isn't allowed to have parameters, so any given
623 parameters are ignored */
625 if(procclass == CLMAIN || procclass == CLBLOCK)
628 /* So now we're working with something other than CLMAIN or CLBLOCK.
629 Determine the type of its return value. */
631 impldcl( np = mkname(entryname->fextname) );
633 proc_argchanges = prev_proc && type != entryname->extype;
634 entryname->extseen = 1;
635 if(proctype == TYUNKNOWN)
636 if( (proctype = type) == TYCHAR)
637 procleng = np->vleng ? np->vleng->constblock.Const.ci
640 if(proctype == TYCHAR)
643 err("noncharacter entry of character function");
645 /* Functions returning type char can only have multiple entries if all
646 entries return the same length */
648 else if( (np->vleng ? np->vleng->constblock.Const.ci :
649 (ftnint) (-1)) != procleng)
650 err("mismatched character entry lengths");
652 else if(type == TYCHAR)
653 err("character entry of noncharacter function");
654 else if(type != proctype)
656 if(rtvlabel[type] == 0)
657 rtvlabel[type] = newlabel();
658 ep->typelabel = rtvlabel[type];
664 chslot = nextarg(TYADDR);
665 chlgslot = nextarg(TYLENG);
669 /* Put a new argument in the function, one which will hold the result of
670 a character function. This will have to be named sometime, probably in
674 np->vleng = (expptr) mkarg(TYLENG, chlgslot);
675 np->vleng->addrblock.uname_tag = UNAM_IDENT;
676 strcpy (np -> vleng -> addrblock.user.ident,
679 if (!xretslot[TYCHAR]) {
680 xretslot[TYCHAR] = rs =
681 autovar(0, type, ISCONST(np->vleng)
682 ? np->vleng : ICON(0), "");
683 strcpy(rs->user.ident, "ret_val");
687 /* Handle a complex return type -- declare a new parameter (pointer to
690 else if( ISCOMPLEX(type) ) {
693 autovar(0, type, EXNULL, " ret_val");
694 /* the blank is for use in out_addr */
697 cxslot = nextarg(TYADDR);
699 else if (type != TYSUBR) {
700 if (type == TYUNKNOWN) {
701 dclerr("untyped function", np);
702 proctype = type = np->vtype =
703 dflttype[letter(np->fvarname[0])];
706 xretslot[type] = retslot =
707 autovar(1, type, EXNULL, " ret_val");
708 /* the blank is for use in out_addr */
712 for(p = ep->arglist ; p ; p = p->nextp)
713 if(! (( q = (Namep) (p->datap) )->vknownarg) ) {
715 q->vardesc.varno = nextarg(TYADDR);
716 allargs = mkchain((char *)q, allargs);
717 q->argno = nallargs++;
719 else if (nentry == 1)
721 else for(p1 = ep->arglist ; p1 != p; p1 = p1->nextp)
722 if ((Namep)p1->datap == q)
726 for(p = ep->arglist ; p ; p = p->nextp) {
727 if(! (( q = (Namep) (p->datap) )->vdcldone) )
731 if(q->vtype == TYCHAR)
734 /* If we don't know the length of a char*(*) (i.e. a string), we must add
735 in this additional length argument. */
738 if (q->vclass == CLPROC)
740 else if (q->vleng == NULL) {
743 mkarg(TYLENG, nextarg(TYLENG) );
744 unamstring((Addrp)q->vleng,
751 if (q->vtype == TYCHAR && q->vclass != CLPROC)
755 if (entryname->extype != type)
758 /* save information for checking consistency of arg lists */
761 if (entryname->exproto)
763 save_argtypes(ep->arglist, &entryname->arginfo, &np->arginfo,
764 0, np->fvarname, STGEXT, k, np->vtype, 0);
775 lastargslot += typesize[type];
783 register struct Dimblock *vdim = q->vdim;
785 if(!vdim->nelt || !ISICON(vdim->nelt))
786 dclerr("adjustable dimension on non-argument", q);
787 else if (vdim->nelt->constblock.Const.ci <= 0)
788 dclerr("nonpositive dimension", q);
793 register struct Hashentry *p;
795 int qstg, qclass, qtype;
798 for(p = hashtab ; p<lasthash ; ++p)
805 if( (qclass==CLUNKNOWN && qstg!=STGARG) ||
806 (qclass==CLVAR && qstg==STGUNKNOWN) ) {
807 if (!(q->vis_assigned | q->vimpldovar))
808 warn1("local variable %s never used",
811 else if(qclass==CLVAR && qstg==STGBSS)
814 /* Give external procedures the proper storage class */
816 else if(qclass==CLPROC && q->vprocclass==PEXTERNAL
818 e = mkext(q->fvarname,addunder(q->cvarname));
820 q->vardesc.varno = e - extsymtab;
821 if (e->extype != qtype)
825 if (qstg != STGARG && q->vdim)
827 } /* if qclass == CLVAR */
836 register struct Hashentry *p;
839 for(p=hashtab; p<lasthash; ++p)
840 if( (q = p->varp) && q->vclass==CLNAMELIST)
845 /* iarrlen -- Returns the size of the array in bytes, or -1 */
852 leng = typesize[q->vtype];
856 if( ISICON(q->vdim->nelt) )
857 leng *= q->vdim->nelt->constblock.Const.ci;
860 if( ISICON(q->vleng) )
861 leng *= q->vleng->constblock.Const.ci;
877 for(q = np->varxptr.namelist ; q ; q = q->nextp)
879 vardcl( v = (Namep) (q->datap) );
880 if( !ONEOF(v->vstg, MSKSTATIC) )
881 dclerr("may not appear in namelist", v);
892 /* docommon -- called at the end of procedure declarations, before
893 equivalences and the procedure body */
897 register Extsym *extptr;
898 register chainp q, q1;
901 register Namep comvar;
903 int i, k, pref, type;
904 extern int type_pref[];
906 for(extptr = extsymtab ; extptr<nextext ; ++extptr)
907 if (extptr->extstg == STGCOMMON && (q = extptr->extp)) {
909 /* If a common declaration also had a list of variables ... */
911 q = extptr->extp = revchain(q);
913 for(k = TYCHAR; q ; q = q->nextp)
915 comvar = (Namep) (q->datap);
917 if(comvar->vdcldone == NO)
919 type = comvar->vtype;
920 if (pref < type_pref[type])
921 pref = type_pref[k = type];
922 if(extptr->extleng % typealign[type] != 0) {
923 dclerr("common alignment", comvar);
924 --nerr; /* don't give bad return code for this */
926 extptr->extleng = roundup(extptr->extleng, typealign[type]);
928 } /* if extptr -> extleng % */
930 /* Set the offset into the common block */
932 comvar->voffset = extptr->extleng;
933 comvar->vardesc.varno = extptr - extsymtab;
935 size = comvar->vleng->constblock.Const.ci;
937 size = typesize[type];
939 if( (neltp = t->nelt) && ISCONST(neltp) )
940 size *= neltp->constblock.Const.ci;
942 dclerr("adjustable array in common", comvar);
944 /* Adjust the length of the common block so far */
946 extptr->extleng += size;
951 /* Determine curno and, if new, save this identifier chain */
954 for (q = extptr->allextp, i = 0; q; i++, q = q->nextp)
955 if (struct_eq((chainp)q->datap, q1))
958 extptr->curno = extptr->maxno - i;
960 extptr->curno = ++extptr->maxno;
961 extptr->allextp = mkchain((char *)extptr->extp,
964 } /* if extptr -> extstg == STGCOMMON */
966 /* Now the hash table entries have STGCOMMON, vdcldone, voffset, and
967 varno. And the common block itself has its full size in extleng. */
972 /* copy_data -- copy the Namep entries so they are available even after
973 the hash table is empty */
978 for (; list; list = list -> nextp) {
979 Namep namep = ALLOC (Nameblock);
983 cpn(sizeof(struct Nameblock), list->datap, (char *)namep);
984 namep->fvarname = strcpy(gmem(strlen(namep->fvarname)+1,0),
986 namep->cvarname = strcmp(namep->fvarname, namep->cvarname)
987 ? strcpy(gmem(strlen(namep->cvarname)+1,0), namep->cvarname)
990 namep -> vleng = (expptr) cpexpr (namep -> vleng);
992 nd = namep -> vdim -> ndim;
993 size = sizeof(int) + (3 + 2 * nd) * sizeof (expptr);
994 dp = (struct Dimblock *) ckalloc (size);
995 cpn(size, (char *)namep->vdim, (char *)dp);
997 dp->nelt = (expptr)cpexpr(dp->nelt);
998 for (i = 0; i < nd; i++) {
999 dp -> dims[i].dimsize = (expptr) cpexpr (dp -> dims[i].dimsize);
1002 list -> datap = (char *) namep;
1012 for(p = extsymtab ; p < nextext ; ++p)
1013 if(p->extstg == STGCOMMON)
1015 if(p->maxleng!=0 && p->extleng!=0 && p->maxleng!=p->extleng
1016 && strcmp(Blank, p->cextname) )
1017 warn1("incompatible lengths for common block %.60s",
1019 if(p->maxleng < p->extleng)
1020 p->maxleng = p->extleng;
1026 /* ROUTINES DEALING WITH AUTOMATIC AND TEMPORARY STORAGE */
1031 /* put block on chain of temps to be reclaimed */
1032 holdtemps = mkchain((char *)p, holdtemps);
1038 register chainp p, p1;
1044 q = (Addrp)p->datap;
1046 if (t == TYCHAR && q->varleng != 0) {
1047 /* restore clobbered character string lengths */
1049 q->vleng = ICON(q->varleng);
1052 p->nextp = templist[t];
1058 /* allocate an automatic variable slot for each of nelt variables */
1060 Addrp autovar(nelt0, t, lengp, name)
1061 register int nelt0, t;
1068 register int nelt = nelt0 > 0 ? nelt0 : 1;
1069 extern char *av_pfix[];
1073 leng = lengp->constblock.Const.ci;
1075 Fatal("automatic variable of nonconstant length");
1080 q = ALLOC(Addrblock);
1085 q->vleng = ICON(leng);
1090 q->isarray = (nelt > 1);
1091 q->memoffset = ICON(0);
1093 /* kludge for nls so we can have ret_val rather than ret_val_4 */
1095 unamstring(q, name);
1097 q->uname_tag = UNAM_IDENT;
1098 temp_name(av_pfix[t], ++autonum[t], q->user.ident);
1101 declare_new_addr (q);
1106 /* Returns a temporary of the appropriate type. Will reuse existing
1107 temporaries when possible */
1109 Addrp mktmpn(nelt, type, lengp)
1118 if(type==TYUNKNOWN || type==TYERROR)
1119 badtype("mktmpn", type);
1123 leng = lengp->constblock.Const.ci;
1125 err("adjustable length");
1126 return( (Addrp) errnode() );
1128 else if (type > TYCHAR || type < TYADDR) {
1129 erri("mktmpn: unexpected type %d", type);
1133 * if a temporary of appropriate shape is on the templist,
1134 * remove it from the list and return it
1136 for(oldp=CHNULL, p=templist[type]; p ; oldp=p, p=p->nextp)
1138 q = (Addrp) (p->datap);
1139 if(q->ntempelt==nelt &&
1140 (type!=TYCHAR || q->vleng->constblock.Const.ci==leng) )
1143 oldp->nextp = p->nextp;
1145 templist[type] = p->nextp;
1150 q = autovar(nelt, type, lengp, "");
1157 /* mktmp -- create new local variable; call it something like name
1158 lengp is taken directly, not copied */
1160 Addrp mktmp(type, lengp)
1165 /* arrange for temporaries to be recycled */
1166 /* at the end of this statement... */
1167 rv = mktmpn(1,type,lengp);
1168 frtemp((Addrp)cpexpr((expptr)rv));
1172 /* mktmp0 omits frtemp() */
1173 Addrp mktmp0(type, lengp)
1178 /* arrange for temporaries to be recycled */
1179 /* when this Addrp is freed */
1180 rv = mktmpn(1,type,lengp);
1185 /* VARIOUS ROUTINES FOR PROCESSING DECLARATIONS */
1187 /* comblock -- Declare a new common block. Input parameters name the block;
1188 s will be NULL if the block is unnamed */
1196 char cbuf[256], *s0;
1198 /* Give the unnamed common block a unique name */
1201 p = mkext(Blank,Blank);
1205 for(i = 0; c = *t = *s++; t++)
1214 if(p->extstg == STGUNKNOWN)
1215 p->extstg = STGCOMMON;
1216 else if(p->extstg != STGCOMMON)
1218 errstr("%.68s cannot be a common block name", s);
1226 /* incomm -- add a new variable to a common declaration */
1234 if(v->vstg != STGUNKNOWN && !v->vimplstg)
1235 dclerr(v->vstg == STGARG
1236 ? "dummy arguments cannot be in common"
1237 : "incompatible common declaration", v);
1240 v->vstg = STGCOMMON;
1241 c->extp = mkchain((char *)v, c->extp);
1248 /* settype -- set the type or storage class of a Namep object. If
1249 v -> vstg == STGUNKNOWN && type < 0, attempt to reset vstg to be
1250 -type. This function will not change any earlier definitions in v,
1251 in will only attempt to fill out more information give the other params */
1253 settype(v, type, length)
1256 register ftnint length;
1260 if(type == TYUNKNOWN)
1263 if(type==TYSUBR && v->vtype!=TYUNKNOWN && v->vstg==STGARG)
1270 else if(type < 0) /* storage class set */
1272 if(v->vstg == STGUNKNOWN)
1274 else if(v->vstg != -type)
1275 dclerr("incompatible storage declarations", v);
1277 else if(v->vtype == TYUNKNOWN || v->vimpltype && v->vtype != type)
1279 if( (v->vtype = lengtype(type, length))==TYCHAR )
1281 v->vleng = ICON(length);
1282 else if (parstate >= INDATA)
1283 v->vleng = ICON(1); /* avoid a memory fault */
1286 if (v->vclass == CLPROC) {
1287 if (v->vstg == STGEXT
1288 && (type1 = extsymtab[v->vardesc.varno].extype)
1289 && type1 != v->vtype)
1291 else if (v->vprocclass == PTHISPROC
1292 && parstate >= INDATA
1294 xretslot[type] = autovar(ONEOF(type,
1295 MSKCOMPLEX|MSKCHAR) ? 0 : 1, type,
1296 v->vleng, " ret_val");
1297 /* not completely right, but enough to */
1298 /* avoid memory faults; we won't */
1299 /* emit any C as we have illegal Fortran */
1302 else if(v->vtype!=type) {
1304 dclerr("incompatible type declarations", v);
1306 else if (type==TYCHAR)
1307 if (v->vleng && v->vleng->constblock.Const.ci != length)
1309 else if (parstate >= INDATA)
1310 v->vleng = ICON(1); /* avoid a memory fault */
1317 /* lengtype -- returns the proper compiler type, given input of Fortran
1318 type and length specifier */
1324 register int length = (int)len;
1328 if(length == typesize[TYDREAL])
1330 if(length == typesize[TYREAL])
1335 if(length == typesize[TYDCOMPLEX])
1337 if(length == typesize[TYCOMPLEX])
1351 if(length == typesize[TYLOGICAL])
1353 if(length == 1 || length == 2) {
1354 erri("treating LOGICAL*%d as LOGICAL", length);
1355 --nerr; /* allow generation of .c file */
1363 if(length == typesize[TYSHORT])
1365 if(length == typesize[TYLONG])
1369 badtype("lengtype", type);
1373 err("incompatible type-length combination");
1383 /* setintr -- Set Intrinsic function */
1390 if(v->vstg == STGUNKNOWN)
1392 else if(v->vstg!=STGINTR)
1393 dclerr("incompatible use of intrinsic function", v);
1394 if(v->vclass==CLUNKNOWN)
1396 if(v->vprocclass == PUNKNOWN)
1397 v->vprocclass = PINTRINSIC;
1398 else if(v->vprocclass != PINTRINSIC)
1399 dclerr("invalid intrinsic declaration", v);
1400 if(k = intrfunct(v->fvarname)) {
1401 if ((*(struct Intrpacked *)&k).f4)
1406 v->vardesc.varno = k;
1410 dclerr("unknown intrinsic function", v);
1416 /* setext -- Set External declaration -- assume that unknowns will become
1422 if(v->vclass == CLUNKNOWN)
1424 else if(v->vclass != CLPROC)
1425 dclerr("invalid external declaration", v);
1427 if(v->vprocclass == PUNKNOWN)
1428 v->vprocclass = PEXTERNAL;
1429 else if(v->vprocclass != PEXTERNAL)
1430 dclerr("invalid external declaration", v);
1436 /* create dimensions block for array variable */
1438 setbound(v, nd, dims)
1441 struct Dims dims[ ];
1443 register expptr q, t;
1444 register struct Dimblock *p;
1446 extern chainp new_vars;
1449 if(v->vclass == CLUNKNOWN)
1451 else if(v->vclass != CLVAR)
1453 dclerr("only variables may be arrays", v);
1457 v->vdim = p = (struct Dimblock *)
1458 ckalloc( sizeof(int) + (3+2*nd)*sizeof(expptr) );
1463 for(i = 0; i <= nd; ++i)
1465 if( (q = dims[i].ub) == NULL)
1473 err("only last bound may be asterisk");
1474 p->dims[i].dimsize = ICON(1);
1476 p->dims[i].dimexpr = NULL;
1483 q = mkexpr(OPMINUS, q, cpexpr(dims[i].lb));
1484 q = mkexpr(OPPLUS, q, ICON(1) );
1488 p->dims[i].dimsize = q;
1489 p->dims[i].dimexpr = (expptr) PNULL;
1492 sprintf(buf, " %s_dim%d", v->fvarname, i+1);
1493 p->dims[i].dimsize = (expptr)
1494 autovar(1, tyint, EXNULL, buf);
1495 p->dims[i].dimexpr = q;
1497 v->vlastdim = new_vars;
1501 p->nelt = mkexpr(OPSTAR, p->nelt,
1502 cpexpr(p->dims[i].dimsize) );
1510 for(i = nd-1 ; i>=0 ; --i)
1515 if(p->dims[i].dimsize)
1516 q = mkexpr(OPPLUS, t, mkexpr(OPSTAR, cpexpr(p->dims[i].dimsize), q) );
1526 sprintf(buf, " %s_offset", v->fvarname);
1527 p->baseoffset = (expptr) autovar(1, tyint, EXNULL, buf);
1536 wr_abbrevs (outfile, function_head, vars)
1541 for (; vars; vars = vars -> nextp) {
1542 Namep name = (Namep) vars -> datap;
1547 nice_printf (outfile, "#define ");
1549 nice_printf (outfile, "#undef ");
1550 out_name (outfile, name);
1552 if (function_head) {
1553 Extsym *comm = &extsymtab[name -> vardesc.varno];
1555 nice_printf (outfile, " (");
1556 extern_out (outfile, comm);
1557 nice_printf (outfile, "%d.", comm->curno);
1558 nice_printf (outfile, "%s)", name->cvarname);
1559 } /* if function_head */
1560 nice_printf (outfile, "\n");