|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1980 Regents of the University of California. ! 3: * All rights reserved. The Berkeley software License Agreement ! 4: * specifies the terms and conditions for redistribution. ! 5: */ ! 6: ! 7: #ifndef lint ! 8: static char sccsid[] = "@(#)call.c 5.3 (Berkeley) 11/12/86"; ! 9: #endif not lint ! 10: ! 11: #include "whoami.h" ! 12: #include "0.h" ! 13: #include "tree.h" ! 14: #include "opcode.h" ! 15: #include "objfmt.h" ! 16: #include "align.h" ! 17: #ifdef PC ! 18: # include "pc.h" ! 19: # include <pcc.h> ! 20: #endif PC ! 21: #include "tmps.h" ! 22: #include "tree_ty.h" ! 23: ! 24: /* ! 25: * Call generates code for calls to ! 26: * user defined procedures and functions ! 27: * and is called by proc and funccod. ! 28: * P is the result of the lookup ! 29: * of the procedure/function symbol, ! 30: * and porf is PROC or FUNC. ! 31: * Psbn is the block number of p. ! 32: * ! 33: * the idea here is that regular scalar functions are just called, ! 34: * while structure functions and formal functions have their results ! 35: * stored in a temporary after the call. ! 36: * structure functions do this because they return pointers ! 37: * to static results, so we copy the static ! 38: * and return a pointer to the copy. ! 39: * formal functions do this because we have to save the result ! 40: * around a call to the runtime routine which restores the display, ! 41: * so we can't just leave the result lying around in registers. ! 42: * formal calls save the address of the descriptor in a local ! 43: * temporary, so it can be addressed for the call which restores ! 44: * the display (FRTN). ! 45: * calls to formal parameters pass the formal as a hidden argument ! 46: * to a special entry point for the formal call. ! 47: * [this is somewhat dependent on the way arguments are addressed.] ! 48: * so PROCs and scalar FUNCs look like ! 49: * p(...args...) ! 50: * structure FUNCs look like ! 51: * (temp = p(...args...),&temp) ! 52: * formal FPROCs look like ! 53: * ( t=p,( t -> entryaddr )(...args...,t,s),FRTN(t,s)) ! 54: * formal scalar FFUNCs look like ! 55: * ( t=p,temp=( t -> entryaddr )(...args...,t,s),FRTN(t,s),temp) ! 56: * formal structure FFUNCs look like ! 57: * (t=p,temp = ( t -> entryaddr )(...args...,t,s),FRTN(t,s),&temp) ! 58: */ ! 59: struct nl * ! 60: call(p, argv_node, porf, psbn) ! 61: struct nl *p; ! 62: struct tnode *argv_node; /* list node */ ! 63: int porf, psbn; ! 64: { ! 65: register struct nl *p1, *q, *p2; ! 66: register struct nl *ptype, *ctype; ! 67: struct tnode *rnode; ! 68: int i, j, d; ! 69: bool chk = TRUE; ! 70: struct nl *savedispnp; /* temporary to hold saved display */ ! 71: # ifdef PC ! 72: int p_type_class = classify( p -> type ); ! 73: long p_type_p2type = p2type( p -> type ); ! 74: bool noarguments; ! 75: /* ! 76: * these get used if temporaries and structures are used ! 77: */ ! 78: struct nl *tempnlp; ! 79: long temptype; /* type of the temporary */ ! 80: long p_type_width; ! 81: long p_type_align; ! 82: char extname[ BUFSIZ ]; ! 83: struct nl *tempdescrp; ! 84: # endif PC ! 85: ! 86: if (p->class == FFUNC || p->class == FPROC) { ! 87: /* ! 88: * allocate space to save the display for formal calls ! 89: */ ! 90: savedispnp = tmpalloc( (long) sizeof display , NLNIL , NOREG ); ! 91: } ! 92: # ifdef OBJ ! 93: if (p->class == FFUNC || p->class == FPROC) { ! 94: (void) put(2, O_LV | cbn << 8 + INDX , ! 95: (int) savedispnp -> value[ NL_OFFS ] ); ! 96: (void) put(2, PTR_RV | psbn << 8+INDX, (int)p->value[NL_OFFS]); ! 97: } ! 98: if (porf == FUNC) { ! 99: /* ! 100: * Push some space ! 101: * for the function return type ! 102: */ ! 103: (void) put(2, O_PUSH, ! 104: -roundup(lwidth(p->type), (long) A_STACK)); ! 105: } ! 106: # endif OBJ ! 107: # ifdef PC ! 108: /* ! 109: * if this is a formal call, ! 110: * stash the address of the descriptor ! 111: * in a temporary so we can find it ! 112: * after the FCALL for the call to FRTN ! 113: */ ! 114: if ( p -> class == FFUNC || p -> class == FPROC ) { ! 115: tempdescrp = tmpalloc((long) (sizeof( struct formalrtn *)), ! 116: NLNIL, REGOK ); ! 117: putRV((char *) 0 , cbn , tempdescrp -> value[ NL_OFFS ] , ! 118: tempdescrp -> extra_flags , PCCTM_PTR|PCCT_STRTY ); ! 119: putRV((char *) 0 , psbn , p -> value[ NL_OFFS ] , ! 120: p -> extra_flags , PCCTM_PTR|PCCT_STRTY ); ! 121: putop( PCC_ASSIGN , PCCTM_PTR | PCCT_STRTY ); ! 122: } ! 123: /* ! 124: * if we have to store a temporary, ! 125: * temptype will be its type, ! 126: * otherwise, it's PCCT_UNDEF. ! 127: */ ! 128: temptype = PCCT_UNDEF; ! 129: if ( porf == FUNC ) { ! 130: p_type_width = width( p -> type ); ! 131: switch( p_type_class ) { ! 132: case TSTR: ! 133: case TSET: ! 134: case TREC: ! 135: case TFILE: ! 136: case TARY: ! 137: temptype = PCCT_STRTY; ! 138: p_type_align = align( p -> type ); ! 139: break; ! 140: default: ! 141: if ( p -> class == FFUNC ) { ! 142: temptype = p2type( p -> type ); ! 143: } ! 144: break; ! 145: } ! 146: if ( temptype != PCCT_UNDEF ) { ! 147: tempnlp = tmpalloc(p_type_width, p -> type, NOREG); ! 148: /* ! 149: * temp ! 150: * for (temp = ... ! 151: */ ! 152: putRV((char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] , ! 153: tempnlp -> extra_flags , (int) temptype ); ! 154: } ! 155: } ! 156: switch ( p -> class ) { ! 157: case FUNC: ! 158: case PROC: ! 159: /* ! 160: * ... p( ... ! 161: */ ! 162: sextname( extname , p -> symbol , BLOCKNO(p -> nl_block) ); ! 163: putleaf( PCC_ICON , 0 , 0 , p2type( p ) , extname ); ! 164: break; ! 165: case FFUNC: ! 166: case FPROC: ! 167: ! 168: /* ! 169: * ... ( t -> entryaddr )( ... ! 170: */ ! 171: /* the descriptor */ ! 172: putRV((char *) 0 , cbn , tempdescrp -> value[ NL_OFFS ] , ! 173: tempdescrp -> extra_flags , PCCTM_PTR | PCCT_STRTY ); ! 174: /* the entry address within the descriptor */ ! 175: if ( FENTRYOFFSET != 0 ) { ! 176: putleaf( PCC_ICON , FENTRYOFFSET , 0 , PCCT_INT , ! 177: (char *) 0 ); ! 178: putop( PCC_PLUS , ! 179: PCCM_ADDTYPE( ! 180: PCCM_ADDTYPE( PCCM_ADDTYPE( p2type( p ) , PCCTM_FTN ) , ! 181: PCCTM_PTR ) , ! 182: PCCTM_PTR ) ); ! 183: } ! 184: /* ! 185: * indirect to fetch the formal entry address ! 186: * with the result type of the routine. ! 187: */ ! 188: if (p -> class == FFUNC) { ! 189: putop( PCCOM_UNARY PCC_MUL , ! 190: PCCM_ADDTYPE(PCCM_ADDTYPE(p2type(p -> type), PCCTM_FTN), ! 191: PCCTM_PTR)); ! 192: } else { ! 193: /* procedures are int returning functions */ ! 194: putop( PCCOM_UNARY PCC_MUL , ! 195: PCCM_ADDTYPE(PCCM_ADDTYPE(PCCT_INT, PCCTM_FTN), PCCTM_PTR)); ! 196: } ! 197: break; ! 198: default: ! 199: panic("call class"); ! 200: } ! 201: noarguments = TRUE; ! 202: # endif PC ! 203: /* ! 204: * Loop and process each of ! 205: * arguments to the proc/func. ! 206: * ... ( ... args ... ) ... ! 207: */ ! 208: ptype = NIL; ! 209: for (p1 = plist(p); p1 != NLNIL; p1 = p1->chain) { ! 210: if (argv_node == TR_NIL) { ! 211: error("Not enough arguments to %s", p->symbol); ! 212: return (NLNIL); ! 213: } ! 214: switch (p1->class) { ! 215: case REF: ! 216: /* ! 217: * Var parameter ! 218: */ ! 219: rnode = argv_node->list_node.list; ! 220: if (rnode != TR_NIL && rnode->tag != T_VAR) { ! 221: error("Expression given (variable required) for var parameter %s of %s", p1->symbol, p->symbol); ! 222: chk = FALSE; ! 223: break; ! 224: } ! 225: q = lvalue( argv_node->list_node.list, ! 226: MOD | ASGN , LREQ ); ! 227: if (q == NIL) { ! 228: chk = FALSE; ! 229: break; ! 230: } ! 231: p2 = p1->type; ! 232: if (p2 == NLNIL || p2->chain == NLNIL || p2->chain->class != CRANGE) { ! 233: if (q != p2) { ! 234: error("Parameter type not identical to type of var parameter %s of %s", p1->symbol, p->symbol); ! 235: chk = FALSE; ! 236: } ! 237: break; ! 238: } else { ! 239: /* conformant array */ ! 240: if (p1 == ptype) { ! 241: if (q != ctype) { ! 242: error("Conformant array parameters in the same specification must be the same type."); ! 243: goto conf_err; ! 244: } ! 245: } else { ! 246: if (classify(q) != TARY && classify(q) != TSTR) { ! 247: error("Array type required for var parameter %s of %s",p1->symbol,p->symbol); ! 248: goto conf_err; ! 249: } ! 250: /* check base type of array */ ! 251: if (p2->type != q->type) { ! 252: error("Base type of array not identical to that of conformant array parameter %s of %s", p1->symbol, p->symbol); ! 253: goto conf_err; ! 254: } ! 255: if (p2->value[0] != q->value[0]) { ! 256: error("Subscript number mismatch on conformant array parameter %s of %s", p1->symbol, p->symbol); ! 257: /* Don't process array bounds & width */ ! 258: conf_err: if (p1->chain->type->class == CRANGE) { ! 259: d = p1->value[0]; ! 260: for (i = 1; i <= d; i++) { ! 261: /* for each subscript, pass by ! 262: * bounds and width ! 263: */ ! 264: p1 = p1->chain->chain->chain; ! 265: } ! 266: } ! 267: ptype = ctype = NLNIL; ! 268: chk = FALSE; ! 269: break; ! 270: } ! 271: /* ! 272: * Save array type for all parameters with same ! 273: * specification. ! 274: */ ! 275: ctype = q; ! 276: ptype = p2; ! 277: /* ! 278: * If at end of conformant array list, ! 279: * get bounds. ! 280: */ ! 281: if (p1->chain->type->class == CRANGE) { ! 282: /* check each subscript, put on stack */ ! 283: d = ptype->value[0]; ! 284: q = ctype; ! 285: for (i = 1; i <= d; i++) { ! 286: p1 = p1->chain; ! 287: q = q->chain; ! 288: if (incompat(q, p1->type, TR_NIL)){ ! 289: error("Subscript type not conformable with parameter %s of %s", p1->symbol, p->symbol); ! 290: chk = FALSE; ! 291: break; ! 292: } ! 293: /* Put lower and upper bound & width */ ! 294: # ifdef OBJ ! 295: if (q->type->class == CRANGE) { ! 296: putcbnds(q->type); ! 297: } else { ! 298: put(2, width(p1->type) <= 2 ? O_CON2 ! 299: : O_CON4, q->range[0]); ! 300: put(2, width(p1->type) <= 2 ? O_CON2 ! 301: : O_CON4, q->range[1]); ! 302: put(2, width(p1->type) <= 2 ? O_CON2 ! 303: : O_CON4, aryconst(ctype,i)); ! 304: } ! 305: # endif OBJ ! 306: # ifdef PC ! 307: if (q->type->class == CRANGE) { ! 308: for (j = 1; j <= 3; j++) { ! 309: p2 = p->nptr[j]; ! 310: putRV(p2->symbol, (p2->nl_block ! 311: & 037), p2->value[0], ! 312: p2->extra_flags,p2type(p2)); ! 313: putop(PCC_CM, PCCT_INT); ! 314: } ! 315: } else { ! 316: putleaf(PCC_ICON, q->range[0], 0,PCCT_INT,0); ! 317: putop( PCC_CM , PCCT_INT ); ! 318: putleaf(PCC_ICON, q->range[1], 0,PCCT_INT,0); ! 319: putop( PCC_CM , PCCT_INT ); ! 320: putleaf(PCC_ICON,aryconst(ctype,i),0,PCCT_INT,0); ! 321: putop( PCC_CM , PCCT_INT ); ! 322: } ! 323: # endif PC ! 324: p1 = p1->chain->chain; ! 325: } ! 326: } ! 327: } ! 328: } ! 329: break; ! 330: case VAR: ! 331: /* ! 332: * Value parameter ! 333: */ ! 334: # ifdef OBJ ! 335: q = rvalue(argv_node->list_node.list, ! 336: p1->type , RREQ ); ! 337: # endif OBJ ! 338: # ifdef PC ! 339: /* ! 340: * structure arguments require lvalues, ! 341: * scalars use rvalue. ! 342: */ ! 343: switch( classify( p1 -> type ) ) { ! 344: case TFILE: ! 345: case TARY: ! 346: case TREC: ! 347: case TSET: ! 348: case TSTR: ! 349: q = stkrval(argv_node->list_node.list, ! 350: p1 -> type , (long) LREQ ); ! 351: break; ! 352: case TINT: ! 353: case TSCAL: ! 354: case TBOOL: ! 355: case TCHAR: ! 356: precheck( p1 -> type , "_RANG4" , "_RSNG4" ); ! 357: q = stkrval(argv_node->list_node.list, ! 358: p1 -> type , (long) RREQ ); ! 359: postcheck(p1 -> type, nl+T4INT); ! 360: break; ! 361: case TDOUBLE: ! 362: q = stkrval(argv_node->list_node.list, ! 363: p1 -> type , (long) RREQ ); ! 364: sconv(p2type(q), PCCT_DOUBLE); ! 365: break; ! 366: default: ! 367: q = rvalue(argv_node->list_node.list, ! 368: p1 -> type , RREQ ); ! 369: break; ! 370: } ! 371: # endif PC ! 372: if (q == NIL) { ! 373: chk = FALSE; ! 374: break; ! 375: } ! 376: if (incompat(q, p1->type, ! 377: argv_node->list_node.list)) { ! 378: cerror("Expression type clashed with type of value parameter %s of %s", p1->symbol, p->symbol); ! 379: chk = FALSE; ! 380: break; ! 381: } ! 382: # ifdef OBJ ! 383: if (isa(p1->type, "bcsi")) ! 384: rangechk(p1->type, q); ! 385: if (q->class != STR) ! 386: convert(q, p1->type); ! 387: # endif OBJ ! 388: # ifdef PC ! 389: switch( classify( p1 -> type ) ) { ! 390: case TFILE: ! 391: case TARY: ! 392: case TREC: ! 393: case TSET: ! 394: case TSTR: ! 395: putstrop( PCC_STARG ! 396: , p2type( p1 -> type ) ! 397: , (int) lwidth( p1 -> type ) ! 398: , align( p1 -> type ) ); ! 399: } ! 400: # endif PC ! 401: break; ! 402: case FFUNC: ! 403: /* ! 404: * function parameter ! 405: */ ! 406: q = flvalue(argv_node->list_node.list, p1 ); ! 407: /*chk = (chk && fcompat(q, p1));*/ ! 408: if ((chk) && (fcompat(q, p1))) ! 409: chk = TRUE; ! 410: else ! 411: chk = FALSE; ! 412: break; ! 413: case FPROC: ! 414: /* ! 415: * procedure parameter ! 416: */ ! 417: q = flvalue(argv_node->list_node.list, p1 ); ! 418: /* chk = (chk && fcompat(q, p1)); */ ! 419: if ((chk) && (fcompat(q, p1))) ! 420: chk = TRUE; ! 421: else chk = FALSE; ! 422: break; ! 423: default: ! 424: panic("call"); ! 425: } ! 426: # ifdef PC ! 427: /* ! 428: * if this is the nth (>1) argument, ! 429: * hang it on the left linear list of arguments ! 430: */ ! 431: if ( noarguments ) { ! 432: noarguments = FALSE; ! 433: } else { ! 434: putop( PCC_CM , PCCT_INT ); ! 435: } ! 436: # endif PC ! 437: argv_node = argv_node->list_node.next; ! 438: } ! 439: if (argv_node != TR_NIL) { ! 440: error("Too many arguments to %s", p->symbol); ! 441: rvlist(argv_node); ! 442: return (NLNIL); ! 443: } ! 444: if (chk == FALSE) ! 445: return NLNIL; ! 446: # ifdef OBJ ! 447: if ( p -> class == FFUNC || p -> class == FPROC ) { ! 448: (void) put(2, PTR_RV | psbn << 8+INDX, (int)p->value[NL_OFFS]); ! 449: (void) put(2, O_LV | cbn << 8 + INDX , ! 450: (int) savedispnp -> value[ NL_OFFS ] ); ! 451: (void) put(1, O_FCALL); ! 452: (void) put(2, O_FRTN, roundup(width(p->type), (long) A_STACK)); ! 453: } else { ! 454: (void) put(2, O_CALL | psbn << 8, (long)p->value[NL_ENTLOC]); ! 455: } ! 456: # endif OBJ ! 457: # ifdef PC ! 458: /* ! 459: * for formal calls: add the hidden argument ! 460: * which is the formal struct describing the ! 461: * environment of the routine. ! 462: * and the argument which is the address of the ! 463: * space into which to save the display. ! 464: */ ! 465: if ( p -> class == FFUNC || p -> class == FPROC ) { ! 466: putRV((char *) 0 , cbn , tempdescrp -> value[ NL_OFFS ] , ! 467: tempdescrp -> extra_flags , PCCTM_PTR|PCCT_STRTY ); ! 468: if ( !noarguments ) { ! 469: putop( PCC_CM , PCCT_INT ); ! 470: } ! 471: noarguments = FALSE; ! 472: putLV((char *) 0 , cbn , savedispnp -> value[ NL_OFFS ] , ! 473: savedispnp -> extra_flags , PCCTM_PTR | PCCT_STRTY ); ! 474: putop( PCC_CM , PCCT_INT ); ! 475: } ! 476: /* ! 477: * do the actual call: ! 478: * either ... p( ... ) ... ! 479: * or ... ( t -> entryaddr )( ... ) ... ! 480: * and maybe an assignment. ! 481: */ ! 482: if ( porf == FUNC ) { ! 483: switch ( p_type_class ) { ! 484: case TBOOL: ! 485: case TCHAR: ! 486: case TINT: ! 487: case TSCAL: ! 488: case TDOUBLE: ! 489: case TPTR: ! 490: putop( ( noarguments ? PCCOM_UNARY PCC_CALL : PCC_CALL ) , ! 491: (int) p_type_p2type ); ! 492: if ( p -> class == FFUNC ) { ! 493: putop( PCC_ASSIGN , (int) p_type_p2type ); ! 494: } ! 495: break; ! 496: default: ! 497: putstrop( ( noarguments ? PCCOM_UNARY PCC_STCALL : PCC_STCALL ), ! 498: (int) PCCM_ADDTYPE( p_type_p2type , PCCTM_PTR ) , ! 499: (int) p_type_width ,(int) p_type_align ); ! 500: putstrop(PCC_STASG, (int) PCCM_ADDTYPE(p_type_p2type, PCCTM_PTR), ! 501: (int) lwidth(p -> type), align(p -> type)); ! 502: break; ! 503: } ! 504: } else { ! 505: putop( ( noarguments ? PCCOM_UNARY PCC_CALL : PCC_CALL ) , PCCT_INT ); ! 506: } ! 507: /* ! 508: * ( t=p , ... , FRTN( t ) ... ! 509: */ ! 510: if ( p -> class == FFUNC || p -> class == FPROC ) { ! 511: putop( PCC_COMOP , PCCT_INT ); ! 512: putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , ! 513: "_FRTN" ); ! 514: putRV((char *) 0 , cbn , tempdescrp -> value[ NL_OFFS ] , ! 515: tempdescrp -> extra_flags , PCCTM_PTR | PCCT_STRTY ); ! 516: putLV((char *) 0 , cbn , savedispnp -> value[ NL_OFFS ] , ! 517: savedispnp -> extra_flags , PCCTM_PTR | PCCT_STRTY ); ! 518: putop( PCC_CM , PCCT_INT ); ! 519: putop( PCC_CALL , PCCT_INT ); ! 520: putop( PCC_COMOP , PCCT_INT ); ! 521: } ! 522: /* ! 523: * if required: ! 524: * either ... , temp ) ! 525: * or ... , &temp ) ! 526: */ ! 527: if ( porf == FUNC && temptype != PCCT_UNDEF ) { ! 528: if ( temptype != PCCT_STRTY ) { ! 529: putRV((char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] , ! 530: tempnlp -> extra_flags , (int) p_type_p2type ); ! 531: } else { ! 532: putLV((char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] , ! 533: tempnlp -> extra_flags , (int) p_type_p2type ); ! 534: } ! 535: putop( PCC_COMOP , PCCT_INT ); ! 536: } ! 537: if ( porf == PROC ) { ! 538: putdot( filename , line ); ! 539: } ! 540: # endif PC ! 541: return (p->type); ! 542: } ! 543: ! 544: rvlist(al) ! 545: register struct tnode *al; ! 546: { ! 547: ! 548: for (; al != TR_NIL; al = al->list_node.next) ! 549: (void) rvalue( al->list_node.list, NLNIL , RREQ ); ! 550: } ! 551: ! 552: /* ! 553: * check that two function/procedure namelist entries are compatible ! 554: */ ! 555: bool ! 556: fcompat( formal , actual ) ! 557: struct nl *formal; ! 558: struct nl *actual; ! 559: { ! 560: register struct nl *f_chain; ! 561: register struct nl *a_chain; ! 562: extern struct nl *plist(); ! 563: bool compat = TRUE; ! 564: ! 565: if ( formal == NLNIL || actual == NLNIL ) { ! 566: return FALSE; ! 567: } ! 568: for (a_chain = plist(actual), f_chain = plist(formal); ! 569: f_chain != NLNIL; ! 570: f_chain = f_chain->chain, a_chain = a_chain->chain) { ! 571: if (a_chain == NIL) { ! 572: error("%s %s declared on line %d has more arguments than", ! 573: parnam(formal->class), formal->symbol, ! 574: (char *) linenum(formal)); ! 575: cerror("%s %s declared on line %d", ! 576: parnam(actual->class), actual->symbol, ! 577: (char *) linenum(actual)); ! 578: return FALSE; ! 579: } ! 580: if ( a_chain -> class != f_chain -> class ) { ! 581: error("%s parameter %s of %s declared on line %d is not identical", ! 582: parnam(f_chain->class), f_chain->symbol, ! 583: formal->symbol, (char *) linenum(formal)); ! 584: cerror("with %s parameter %s of %s declared on line %d", ! 585: parnam(a_chain->class), a_chain->symbol, ! 586: actual->symbol, (char *) linenum(actual)); ! 587: compat = FALSE; ! 588: } else if (a_chain->class == FFUNC || a_chain->class == FPROC) { ! 589: /*compat = (compat && fcompat(f_chain, a_chain));*/ ! 590: if ((compat) && (fcompat(f_chain, a_chain))) ! 591: compat = TRUE; ! 592: else compat = FALSE; ! 593: } ! 594: if ((a_chain->class != FPROC && f_chain->class != FPROC) && ! 595: (a_chain->type != f_chain->type)) { ! 596: error("Type of %s parameter %s of %s declared on line %d is not identical", ! 597: parnam(f_chain->class), f_chain->symbol, ! 598: formal->symbol, (char *) linenum(formal)); ! 599: cerror("to type of %s parameter %s of %s declared on line %d", ! 600: parnam(a_chain->class), a_chain->symbol, ! 601: actual->symbol, (char *) linenum(actual)); ! 602: compat = FALSE; ! 603: } ! 604: } ! 605: if (a_chain != NIL) { ! 606: error("%s %s declared on line %d has fewer arguments than", ! 607: parnam(formal->class), formal->symbol, ! 608: (char *) linenum(formal)); ! 609: cerror("%s %s declared on line %d", ! 610: parnam(actual->class), actual->symbol, ! 611: (char *) linenum(actual)); ! 612: return FALSE; ! 613: } ! 614: return compat; ! 615: } ! 616: ! 617: char * ! 618: parnam(nltype) ! 619: int nltype; ! 620: { ! 621: switch(nltype) { ! 622: case REF: ! 623: return "var"; ! 624: case VAR: ! 625: return "value"; ! 626: case FUNC: ! 627: case FFUNC: ! 628: return "function"; ! 629: case PROC: ! 630: case FPROC: ! 631: return "procedure"; ! 632: default: ! 633: return "SNARK"; ! 634: } ! 635: } ! 636: ! 637: struct nl *plist(p) ! 638: struct nl *p; ! 639: { ! 640: switch (p->class) { ! 641: case FFUNC: ! 642: case FPROC: ! 643: return p->ptr[ NL_FCHAIN ]; ! 644: case PROC: ! 645: case FUNC: ! 646: return p->chain; ! 647: default: ! 648: { ! 649: panic("plist"); ! 650: return(NLNIL); /* this is here only so lint won't complain ! 651: panic actually aborts */ ! 652: } ! 653: ! 654: } ! 655: } ! 656: ! 657: linenum(p) ! 658: struct nl *p; ! 659: { ! 660: if (p->class == FUNC) ! 661: return p->ptr[NL_FVAR]->value[NL_LINENO]; ! 662: return p->value[NL_LINENO]; ! 663: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.