1 /* Copyright (c) 1979 Regents of the University of California */ 2 3 static char sccsid[] = "@(#)fdec.c 1.23 02/28/83"; 4 5 #include "whoami.h" 6 #include "0.h" 7 #include "tree.h" 8 #include "opcode.h" 9 #include "objfmt.h" 10 #include "align.h" 11 #include "tmps.h" 12 13 /* 14 * this array keeps the pxp counters associated with 15 * functions and procedures, so that they can be output 16 * when their bodies are encountered 17 */ 18 int bodycnts[ DSPLYSZ ]; 19 20 #ifdef PC 21 # include "pc.h" 22 # include "pcops.h" 23 #endif PC 24 25 #ifdef OBJ 26 int cntpatch; 27 int nfppatch; 28 #endif OBJ 29 30 funcfwd(fp) 31 struct nl *fp; 32 { 33 34 /* 35 * save the counter for this function 36 */ 37 if ( monflg ) { 38 fp -> value[ NL_CNTR ] = bodycnts[ cbn ]; 39 } 40 return (fp); 41 } 42 43 /* 44 * Funcext marks the procedure or 45 * function external in the symbol 46 * table. Funcext should only be 47 * called if PC, and is an error 48 * otherwise. 49 */ 50 51 funcext(fp) 52 struct nl *fp; 53 { 54 55 #ifdef OBJ 56 error("Procedures or functions cannot be declared external."); 57 #endif OBJ 58 59 #ifdef PC 60 /* 61 * save the counter for this function 62 */ 63 if ( monflg ) { 64 fp -> value[ NL_CNTR ] = bodycnts[ cbn ]; 65 } 66 if (opt('s')) { 67 standard(); 68 error("External procedures and functions are not standard"); 69 } else { 70 if (cbn == 1) { 71 fp->extra_flags |= NEXTERN; 72 stabefunc( fp -> symbol , fp -> class , line ); 73 } 74 else 75 error("External procedures and functions can only be declared at the outermost level."); 76 } 77 #endif PC 78 79 return(fp); 80 } 81 82 /* 83 * Funcbody is called 84 * when the actual (resolved) 85 * declaration of a procedure is 86 * encountered. It puts the names 87 * of the (function) and parameters 88 * into the symbol table. 89 */ 90 funcbody(fp) 91 struct nl *fp; 92 { 93 register struct nl *q, *p; 94 95 cbn++; 96 if (cbn >= DSPLYSZ) { 97 error("Too many levels of function/procedure nesting"); 98 pexit(ERRS); 99 } 100 tmpinit(cbn); 101 gotos[cbn] = NIL; 102 errcnt[cbn] = syneflg; 103 parts[ cbn ] = NIL; 104 dfiles[ cbn ] = FALSE; 105 if (fp == NIL) 106 return (NIL); 107 /* 108 * Save the virtual name 109 * list stack pointer so 110 * the space can be freed 111 * later (funcend). 112 */ 113 fp->ptr[2] = nlp; 114 if (fp->class != PROG) { 115 for (q = fp->chain; q != NIL; q = q->chain) { 116 enter(q); 117 # ifdef PC 118 q -> extra_flags |= NPARAM; 119 # endif PC 120 } 121 } 122 if (fp->class == FUNC) { 123 /* 124 * For functions, enter the fvar 125 */ 126 enter(fp->ptr[NL_FVAR]); 127 # ifdef PC 128 q = fp -> ptr[ NL_FVAR ]; 129 if (q -> type != NIL ) { 130 sizes[cbn].curtmps.om_off = q -> value[NL_OFFS]; 131 sizes[cbn].om_max = q -> value[NL_OFFS]; 132 } 133 # endif PC 134 } 135 # ifdef PTREE 136 /* 137 * pick up the pointer to porf declaration 138 */ 139 PorFHeader[ ++nesting ] = fp -> inTree; 140 # endif PTREE 141 return (fp); 142 } 143 144 /* 145 * Segend is called to check for 146 * unresolved variables, funcs and 147 * procs, and deliver unresolved and 148 * baduse error diagnostics at the 149 * end of a routine segment (a separately 150 * compiled segment that is not the 151 * main program) for PC. This 152 * routine should only be called 153 * by PC (not standard). 154 */ 155 segend() 156 { 157 register struct nl *p; 158 register int i,b; 159 char *cp; 160 161 #ifdef PC 162 if ( monflg ) { 163 error("Only the module containing the \"program\" statement"); 164 cerror("can be profiled with ``pxp''.\n"); 165 } 166 if (opt('s')) { 167 standard(); 168 error("Separately compiled routine segments are not standard."); 169 } else { 170 b = cbn; 171 for (i=0; i<077; i++) { 172 for (p = disptab[i]; p != NIL && (p->nl_block & 037) == b; p = p->nl_next) { 173 switch (p->class) { 174 case BADUSE: 175 cp = 's'; 176 if (p->chain->ud_next == NIL) 177 cp++; 178 eholdnl(); 179 if (p->value[NL_KINDS] & ISUNDEF) 180 nerror("%s undefined on line%s", p->symbol, cp); 181 else 182 nerror("%s improperly used on line%s", p->symbol, cp); 183 pnumcnt = 10; 184 pnums(p->chain); 185 pchr('\n'); 186 break; 187 188 case FUNC: 189 case PROC: 190 if ((p->nl_flags & NFORWD) && 191 ((p->extra_flags & NEXTERN) == 0)) 192 nerror("Unresolved forward declaration of %s %s", classes[p->class], p->symbol); 193 break; 194 195 case FVAR: 196 if (((p->nl_flags & NMOD) == 0) && 197 ((p->chain->extra_flags & NEXTERN) == 0)) 198 nerror("No assignment to the function variable"); 199 break; 200 } 201 } 202 disptab[i] = p; 203 } 204 } 205 #endif PC 206 #ifdef OBJ 207 error("Missing program statement and program body"); 208 #endif OBJ 209 210 } 211 212 213 /* 214 * Level1 does level one processing for 215 * separately compiled routine segments 216 */ 217 level1() 218 { 219 220 # ifdef OBJ 221 error("Missing program statement"); 222 # endif OBJ 223 # ifdef PC 224 if (opt('s')) { 225 standard(); 226 error("Missing program statement"); 227 } 228 # endif PC 229 230 cbn++; 231 tmpinit(cbn); 232 gotos[cbn] = NIL; 233 errcnt[cbn] = syneflg; 234 parts[ cbn ] = NIL; 235 dfiles[ cbn ] = FALSE; 236 progseen = TRUE; 237 } 238 239 240 241 pnums(p) 242 struct udinfo *p; 243 { 244 245 if (p->ud_next != NIL) 246 pnums(p->ud_next); 247 if (pnumcnt == 0) { 248 printf("\n\t"); 249 pnumcnt = 20; 250 } 251 pnumcnt--; 252 printf(" %d", p->ud_line); 253 } 254 255 nerror(a1, a2, a3) 256 { 257 258 if (Fp != NIL) { 259 yySsync(); 260 #ifndef PI1 261 if (opt('l')) 262 yyoutline(); 263 #endif 264 yysetfile(filename); 265 printf("In %s %s:\n", classes[Fp->class], Fp->symbol); 266 Fp = NIL; 267 elineoff(); 268 } 269 error(a1, a2, a3); 270 } 271