1*764Speter /* Copyright (c) 1979 Regents of the University of California */ 2*764Speter 3*764Speter static char sccsid[] = "@(#)pcfunc.c 1.1 08/27/80"; 4*764Speter 5*764Speter #include "whoami.h" 6*764Speter #ifdef PC 7*764Speter /* 8*764Speter * and to the end of the file 9*764Speter */ 10*764Speter #include "0.h" 11*764Speter #include "tree.h" 12*764Speter #include "opcode.h" 13*764Speter #include "pc.h" 14*764Speter #include "pcops.h" 15*764Speter 16*764Speter bool cardempty = FALSE; 17*764Speter 18*764Speter /* 19*764Speter * Funccod generates code for 20*764Speter * built in function calls and calls 21*764Speter * call to generate calls to user 22*764Speter * defined functions and procedures. 23*764Speter */ 24*764Speter pcfunccod( r ) 25*764Speter int *r; 26*764Speter { 27*764Speter struct nl *p; 28*764Speter register struct nl *p1; 29*764Speter register int *al; 30*764Speter register op; 31*764Speter int argc, *argv; 32*764Speter int tr[2], tr2[4]; 33*764Speter char *funcname; 34*764Speter long tempoff; 35*764Speter long temptype; 36*764Speter struct nl *rettype; 37*764Speter 38*764Speter /* 39*764Speter * Verify that the given name 40*764Speter * is defined and the name of 41*764Speter * a function. 42*764Speter */ 43*764Speter p = lookup(r[2]); 44*764Speter if (p == NIL) { 45*764Speter rvlist(r[3]); 46*764Speter return (NIL); 47*764Speter } 48*764Speter if (p->class != FUNC) { 49*764Speter error("%s is not a function", p->symbol); 50*764Speter rvlist(r[3]); 51*764Speter return (NIL); 52*764Speter } 53*764Speter argv = r[3]; 54*764Speter /* 55*764Speter * Call handles user defined 56*764Speter * procedures and functions 57*764Speter */ 58*764Speter if (bn != 0) 59*764Speter return (call(p, argv, FUNC, bn)); 60*764Speter /* 61*764Speter * Count the arguments 62*764Speter */ 63*764Speter argc = 0; 64*764Speter for (al = argv; al != NIL; al = al[2]) 65*764Speter argc++; 66*764Speter /* 67*764Speter * Built-in functions have 68*764Speter * their interpreter opcode 69*764Speter * associated with them. 70*764Speter */ 71*764Speter op = p->value[0] &~ NSTAND; 72*764Speter if (opt('s') && (p->value[0] & NSTAND)) { 73*764Speter standard(); 74*764Speter error("%s is a nonstandard function", p->symbol); 75*764Speter } 76*764Speter if ( op == O_ARGC ) { 77*764Speter putleaf( P2NAME , 0 , 0 , P2INT , "__argc" ); 78*764Speter return nl + T4INT; 79*764Speter } 80*764Speter switch (op) { 81*764Speter /* 82*764Speter * Parameterless functions 83*764Speter */ 84*764Speter case O_CLCK: 85*764Speter funcname = "_CLCK"; 86*764Speter goto noargs; 87*764Speter case O_SCLCK: 88*764Speter funcname = "_SCLCK"; 89*764Speter goto noargs; 90*764Speter noargs: 91*764Speter if (argc != 0) { 92*764Speter error("%s takes no arguments", p->symbol); 93*764Speter rvlist(argv); 94*764Speter return (NIL); 95*764Speter } 96*764Speter putleaf( P2ICON , 0 , 0 97*764Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) 98*764Speter , funcname ); 99*764Speter putop( P2UNARY P2CALL , P2INT ); 100*764Speter return (nl+T4INT); 101*764Speter case O_WCLCK: 102*764Speter if (argc != 0) { 103*764Speter error("%s takes no arguments", p->symbol); 104*764Speter rvlist(argv); 105*764Speter return (NIL); 106*764Speter } 107*764Speter putleaf( P2ICON , 0 , 0 108*764Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) 109*764Speter , "_time" ); 110*764Speter putleaf( P2ICON , 0 , 0 , P2INT , 0 ); 111*764Speter putop( P2CALL , P2INT ); 112*764Speter return (nl+T4INT); 113*764Speter case O_EOF: 114*764Speter case O_EOLN: 115*764Speter if (argc == 0) { 116*764Speter argv = tr; 117*764Speter tr[1] = tr2; 118*764Speter tr2[0] = T_VAR; 119*764Speter tr2[2] = input->symbol; 120*764Speter tr2[1] = tr2[3] = NIL; 121*764Speter argc = 1; 122*764Speter } else if (argc != 1) { 123*764Speter error("%s takes either zero or one argument", p->symbol); 124*764Speter rvlist(argv); 125*764Speter return (NIL); 126*764Speter } 127*764Speter } 128*764Speter /* 129*764Speter * All other functions take 130*764Speter * exactly one argument. 131*764Speter */ 132*764Speter if (argc != 1) { 133*764Speter error("%s takes exactly one argument", p->symbol); 134*764Speter rvlist(argv); 135*764Speter return (NIL); 136*764Speter } 137*764Speter /* 138*764Speter * find out the type of the argument 139*764Speter */ 140*764Speter codeoff(); 141*764Speter p1 = stkrval((int *) argv[1], NLNIL , RREQ ); 142*764Speter codeon(); 143*764Speter if (p1 == NIL) 144*764Speter return (NIL); 145*764Speter /* 146*764Speter * figure out the return type and the funtion name 147*764Speter */ 148*764Speter switch (op) { 149*764Speter case O_EXP: 150*764Speter funcname = "_exp"; 151*764Speter goto mathfunc; 152*764Speter case O_SIN: 153*764Speter funcname = "_sin"; 154*764Speter goto mathfunc; 155*764Speter case O_COS: 156*764Speter funcname = "_cos"; 157*764Speter goto mathfunc; 158*764Speter case O_ATAN: 159*764Speter funcname = "_atan"; 160*764Speter goto mathfunc; 161*764Speter case O_LN: 162*764Speter funcname = opt('t') ? "_LN" : "_log"; 163*764Speter goto mathfunc; 164*764Speter case O_SQRT: 165*764Speter funcname = opt('t') ? "_SQRT" : "_sqrt"; 166*764Speter goto mathfunc; 167*764Speter case O_RANDOM: 168*764Speter funcname = "_RANDOM"; 169*764Speter goto mathfunc; 170*764Speter mathfunc: 171*764Speter if (isnta(p1, "id")) { 172*764Speter error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1)); 173*764Speter return (NIL); 174*764Speter } 175*764Speter putleaf( P2ICON , 0 , 0 176*764Speter , ADDTYPE( P2FTN | P2DOUBLE , P2PTR ) , funcname ); 177*764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 178*764Speter if ( isa( p1 , "i" ) ) { 179*764Speter putop( P2SCONV , P2DOUBLE ); 180*764Speter } 181*764Speter putop( P2CALL , P2DOUBLE ); 182*764Speter return nl + TDOUBLE; 183*764Speter case O_EXPO: 184*764Speter if (isnta( p1 , "id" ) ) { 185*764Speter error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1)); 186*764Speter return NIL; 187*764Speter } 188*764Speter putleaf( P2ICON , 0 , 0 189*764Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_EXPO" ); 190*764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 191*764Speter if ( isa( p1 , "i" ) ) { 192*764Speter putop( P2SCONV , P2DOUBLE ); 193*764Speter } 194*764Speter putop( P2CALL , P2INT ); 195*764Speter return ( nl + T4INT ); 196*764Speter case O_UNDEF: 197*764Speter if ( isnta( p1 , "id" ) ) { 198*764Speter error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1)); 199*764Speter return NIL; 200*764Speter } 201*764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 202*764Speter putleaf( P2ICON , 0 , 0 , P2INT , 0 ); 203*764Speter putop( P2COMOP , P2INT ); 204*764Speter return ( nl + TBOOL ); 205*764Speter case O_SEED: 206*764Speter if (isnta(p1, "i")) { 207*764Speter error("seed's argument must be an integer, not %s", nameof(p1)); 208*764Speter return (NIL); 209*764Speter } 210*764Speter putleaf( P2ICON , 0 , 0 211*764Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_SEED" ); 212*764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 213*764Speter putop( P2CALL , P2INT ); 214*764Speter return nl + T4INT; 215*764Speter case O_ROUND: 216*764Speter case O_TRUNC: 217*764Speter if ( isnta( p1 , "d" ) ) { 218*764Speter error("%s's argument must be a real, not %s", p->symbol, nameof(p1)); 219*764Speter return (NIL); 220*764Speter } 221*764Speter putleaf( P2ICON , 0 , 0 222*764Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) 223*764Speter , op == O_ROUND ? "_ROUND" : "_TRUNC" ); 224*764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 225*764Speter putop( P2CALL , P2INT ); 226*764Speter return nl + T4INT; 227*764Speter case O_ABS2: 228*764Speter if ( isa( p1 , "d" ) ) { 229*764Speter putleaf( P2ICON , 0 , 0 230*764Speter , ADDTYPE( P2FTN | P2DOUBLE , P2PTR ) 231*764Speter , "_fabs" ); 232*764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 233*764Speter putop( P2CALL , P2DOUBLE ); 234*764Speter return nl + TDOUBLE; 235*764Speter } 236*764Speter if ( isa( p1 , "i" ) ) { 237*764Speter putleaf( P2ICON , 0 , 0 238*764Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_abs" ); 239*764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 240*764Speter putop( P2CALL , P2INT ); 241*764Speter return nl + T4INT; 242*764Speter } 243*764Speter error("%s's argument must be an integer or real, not %s", p->symbol, nameof(p1)); 244*764Speter return NIL; 245*764Speter case O_SQR2: 246*764Speter if ( isa( p1 , "d" ) ) { 247*764Speter temptype = P2DOUBLE; 248*764Speter rettype = nl + TDOUBLE; 249*764Speter sizes[ cbn ].om_off -= sizeof( double ); 250*764Speter } else if ( isa( p1 , "i" ) ) { 251*764Speter temptype = P2INT; 252*764Speter rettype = nl + T4INT; 253*764Speter sizes[ cbn ].om_off -= sizeof( long ); 254*764Speter } else { 255*764Speter error("%s's argument must be an integer or real, not %s", p->symbol, nameof(p1)); 256*764Speter return NIL; 257*764Speter } 258*764Speter tempoff = sizes[ cbn ].om_off; 259*764Speter if ( tempoff < sizes[ cbn ].om_max ) { 260*764Speter sizes[ cbn ].om_max = tempoff; 261*764Speter } 262*764Speter putlbracket( ftnno , -tempoff ); 263*764Speter putRV( 0 , cbn , tempoff , temptype , 0 ); 264*764Speter p1 = rvalue( (int *) argv[1] , NLNIL , RREQ ); 265*764Speter putop( P2ASSIGN , temptype ); 266*764Speter putRV( 0 , cbn , tempoff , temptype , 0 ); 267*764Speter putRV( 0 , cbn , tempoff , temptype , 0 ); 268*764Speter putop( P2MUL , temptype ); 269*764Speter putop( P2COMOP , temptype ); 270*764Speter return rettype; 271*764Speter case O_ORD2: 272*764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 273*764Speter if (isa(p1, "bcis") || classify(p1) == TPTR) { 274*764Speter return (nl+T4INT); 275*764Speter } 276*764Speter error("ord's argument must be of scalar type or a pointer, not %s", nameof(p1)); 277*764Speter return (NIL); 278*764Speter case O_SUCC2: 279*764Speter case O_PRED2: 280*764Speter if (isa(p1, "d")) { 281*764Speter error("%s is forbidden for reals", p->symbol); 282*764Speter return (NIL); 283*764Speter } 284*764Speter if ( isnta( p1 , "bcsi" ) ) { 285*764Speter error("%s's argument must be of scalar type, not %s", p->symbol, nameof(p1)); 286*764Speter return NIL; 287*764Speter } 288*764Speter if ( opt( 't' ) ) { 289*764Speter putleaf( P2ICON , 0 , 0 290*764Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) 291*764Speter , op == O_SUCC2 ? "_SUCC" : "_PRED" ); 292*764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 293*764Speter putleaf( P2ICON , p1 -> range[0] , 0 , P2INT , 0 ); 294*764Speter putop( P2LISTOP , P2INT ); 295*764Speter putleaf( P2ICON , p1 -> range[1] , 0 , P2INT , 0 ); 296*764Speter putop( P2LISTOP , P2INT ); 297*764Speter putop( P2CALL , P2INT ); 298*764Speter } else { 299*764Speter p1 = rvalue( argv[1] , NIL , RREQ ); 300*764Speter putleaf( P2ICON , 1 , 0 , P2INT , 0 ); 301*764Speter putop( op == O_SUCC2 ? P2PLUS : P2MINUS , P2INT ); 302*764Speter } 303*764Speter if ( isa( p1 , "bcs" ) ) { 304*764Speter return p1; 305*764Speter } else { 306*764Speter return nl + T4INT; 307*764Speter } 308*764Speter case O_ODD2: 309*764Speter if (isnta(p1, "i")) { 310*764Speter error("odd's argument must be an integer, not %s", nameof(p1)); 311*764Speter return (NIL); 312*764Speter } 313*764Speter p1 = rvalue( (int *) argv[1] , NLNIL , RREQ ); 314*764Speter putleaf( P2ICON , 1 , 0 , P2INT , 0 ); 315*764Speter putop( P2AND , P2INT ); 316*764Speter return nl + TBOOL; 317*764Speter case O_CHR2: 318*764Speter if (isnta(p1, "i")) { 319*764Speter error("chr's argument must be an integer, not %s", nameof(p1)); 320*764Speter return (NIL); 321*764Speter } 322*764Speter if (opt('t')) { 323*764Speter putleaf( P2ICON , 0 , 0 324*764Speter , ADDTYPE( P2FTN | P2CHAR , P2PTR ) , "_CHR" ); 325*764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 326*764Speter putop( P2CALL , P2CHAR ); 327*764Speter } else { 328*764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 329*764Speter } 330*764Speter return nl + TCHAR; 331*764Speter case O_CARD: 332*764Speter if ( p1 != nl + TSET ) { 333*764Speter if (isnta(p1, "t")) { 334*764Speter error("Argument to card must be a set, not %s", nameof(p1)); 335*764Speter return (NIL); 336*764Speter } 337*764Speter putleaf( P2ICON , 0 , 0 338*764Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_CARD" ); 339*764Speter p1 = stkrval( (int *) argv[1] , NLNIL , LREQ ); 340*764Speter putleaf( P2ICON , lwidth( p1 ) , 0 , P2INT , 0 ); 341*764Speter putop( P2LISTOP , P2INT ); 342*764Speter putop( P2CALL , P2INT ); 343*764Speter } else { 344*764Speter if ( !cardempty ) { 345*764Speter warning(); 346*764Speter error("Cardinality of the empty set is 0." ); 347*764Speter cardempty = TRUE; 348*764Speter } 349*764Speter putleaf( P2ICON , 0 , 0 , P2INT , 0 ); 350*764Speter } 351*764Speter return nl + T2INT; 352*764Speter case O_EOLN: 353*764Speter if (!text(p1)) { 354*764Speter error("Argument to eoln must be a text file, not %s", nameof(p1)); 355*764Speter return (NIL); 356*764Speter } 357*764Speter putleaf( P2ICON , 0 , 0 358*764Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_TEOLN" ); 359*764Speter p1 = stklval( (int *) argv[1] , NOFLAGS ); 360*764Speter putop( P2CALL , P2INT ); 361*764Speter return nl + TBOOL; 362*764Speter case O_EOF: 363*764Speter if (p1->class != FILET) { 364*764Speter error("Argument to eof must be file, not %s", nameof(p1)); 365*764Speter return (NIL); 366*764Speter } 367*764Speter putleaf( P2ICON , 0 , 0 368*764Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_TEOF" ); 369*764Speter p1 = stklval( (int *) argv[1] , NOFLAGS ); 370*764Speter putop( P2CALL , P2INT ); 371*764Speter return nl + TBOOL; 372*764Speter case 0: 373*764Speter error("%s is an unimplemented 6000-3.4 extension", p->symbol); 374*764Speter default: 375*764Speter panic("func1"); 376*764Speter } 377*764Speter } 378*764Speter #endif PC 379