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