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