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