1764Speter /* Copyright (c) 1979 Regents of the University of California */ 2764Speter 3*10669Speter static char sccsid[] = "@(#)pcfunc.c 1.12 02/01/83"; 4764Speter 5764Speter #include "whoami.h" 6764Speter #ifdef PC 7764Speter /* 8764Speter * and to the end of the file 9764Speter */ 10764Speter #include "0.h" 11764Speter #include "tree.h" 1210375Speter #include "objfmt.h" 13764Speter #include "opcode.h" 1410375Speter #include "pc.h" 1510375Speter #include "pcops.h" 16764Speter 17764Speter /* 18764Speter * Funccod generates code for 19764Speter * built in function calls and calls 20764Speter * call to generate calls to user 21764Speter * defined functions and procedures. 22764Speter */ 23764Speter pcfunccod( r ) 24764Speter int *r; 25764Speter { 26764Speter struct nl *p; 27764Speter register struct nl *p1; 28764Speter register int *al; 29764Speter register op; 30764Speter int argc, *argv; 31764Speter int tr[2], tr2[4]; 32764Speter char *funcname; 333831Speter struct nl *tempnlp; 34764Speter long temptype; 35764Speter struct nl *rettype; 36764Speter 37764Speter /* 38764Speter * Verify that the given name 39764Speter * is defined and the name of 40764Speter * a function. 41764Speter */ 42764Speter p = lookup(r[2]); 43764Speter if (p == NIL) { 44764Speter rvlist(r[3]); 45764Speter return (NIL); 46764Speter } 471197Speter if (p->class != FUNC && p->class != FFUNC) { 48764Speter error("%s is not a function", p->symbol); 49764Speter rvlist(r[3]); 50764Speter return (NIL); 51764Speter } 52764Speter argv = r[3]; 53764Speter /* 54764Speter * Call handles user defined 55764Speter * procedures and functions 56764Speter */ 57764Speter if (bn != 0) 58764Speter return (call(p, argv, FUNC, bn)); 59764Speter /* 60764Speter * Count the arguments 61764Speter */ 62764Speter argc = 0; 63764Speter for (al = argv; al != NIL; al = al[2]) 64764Speter argc++; 65764Speter /* 66764Speter * Built-in functions have 67764Speter * their interpreter opcode 68764Speter * associated with them. 69764Speter */ 70764Speter op = p->value[0] &~ NSTAND; 71764Speter if (opt('s') && (p->value[0] & NSTAND)) { 72764Speter standard(); 73764Speter error("%s is a nonstandard function", p->symbol); 74764Speter } 75764Speter if ( op == O_ARGC ) { 76764Speter putleaf( P2NAME , 0 , 0 , P2INT , "__argc" ); 77764Speter return nl + T4INT; 78764Speter } 79764Speter switch (op) { 80764Speter /* 81764Speter * Parameterless functions 82764Speter */ 83764Speter case O_CLCK: 84764Speter funcname = "_CLCK"; 85764Speter goto noargs; 86764Speter case O_SCLCK: 87764Speter funcname = "_SCLCK"; 88764Speter goto noargs; 89764Speter noargs: 90764Speter if (argc != 0) { 91764Speter error("%s takes no arguments", p->symbol); 92764Speter rvlist(argv); 93764Speter return (NIL); 94764Speter } 95764Speter putleaf( P2ICON , 0 , 0 96764Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) 97764Speter , funcname ); 98764Speter putop( P2UNARY P2CALL , P2INT ); 99764Speter return (nl+T4INT); 100764Speter case O_WCLCK: 101764Speter if (argc != 0) { 102764Speter error("%s takes no arguments", p->symbol); 103764Speter rvlist(argv); 104764Speter return (NIL); 105764Speter } 106764Speter putleaf( P2ICON , 0 , 0 107764Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) 108764Speter , "_time" ); 109764Speter putleaf( P2ICON , 0 , 0 , P2INT , 0 ); 110764Speter putop( P2CALL , P2INT ); 111764Speter return (nl+T4INT); 112764Speter case O_EOF: 113764Speter case O_EOLN: 114764Speter if (argc == 0) { 115764Speter argv = tr; 116764Speter tr[1] = tr2; 117764Speter tr2[0] = T_VAR; 118764Speter tr2[2] = input->symbol; 119764Speter tr2[1] = tr2[3] = NIL; 120764Speter argc = 1; 121764Speter } else if (argc != 1) { 122764Speter error("%s takes either zero or one argument", p->symbol); 123764Speter rvlist(argv); 124764Speter return (NIL); 125764Speter } 126764Speter } 127764Speter /* 128764Speter * All other functions take 129764Speter * exactly one argument. 130764Speter */ 131764Speter if (argc != 1) { 132764Speter error("%s takes exactly one argument", p->symbol); 133764Speter rvlist(argv); 134764Speter return (NIL); 135764Speter } 136764Speter /* 137764Speter * find out the type of the argument 138764Speter */ 139764Speter codeoff(); 140764Speter p1 = stkrval((int *) argv[1], NLNIL , RREQ ); 141764Speter codeon(); 142764Speter if (p1 == NIL) 143764Speter return (NIL); 144764Speter /* 145764Speter * figure out the return type and the funtion name 146764Speter */ 147764Speter switch (op) { 148764Speter case O_EXP: 1495715Smckusic funcname = opt('t') ? "_EXP" : "_exp"; 150764Speter goto mathfunc; 151764Speter case O_SIN: 1525715Smckusic funcname = opt('t') ? "_SIN" : "_sin"; 153764Speter goto mathfunc; 154764Speter case O_COS: 1555715Smckusic funcname = opt('t') ? "_COS" : "_cos"; 156764Speter goto mathfunc; 157764Speter case O_ATAN: 1585715Smckusic funcname = opt('t') ? "_ATAN" : "_atan"; 159764Speter goto mathfunc; 160764Speter case O_LN: 161764Speter funcname = opt('t') ? "_LN" : "_log"; 162764Speter goto mathfunc; 163764Speter case O_SQRT: 164764Speter funcname = opt('t') ? "_SQRT" : "_sqrt"; 165764Speter goto mathfunc; 166764Speter case O_RANDOM: 167764Speter funcname = "_RANDOM"; 168764Speter goto mathfunc; 169764Speter mathfunc: 170764Speter if (isnta(p1, "id")) { 171764Speter error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1)); 172764Speter return (NIL); 173764Speter } 174764Speter putleaf( P2ICON , 0 , 0 175764Speter , ADDTYPE( P2FTN | P2DOUBLE , P2PTR ) , funcname ); 176764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 17710376Speter sconv(p2type(p1), P2DOUBLE); 178764Speter putop( P2CALL , P2DOUBLE ); 179764Speter return nl + TDOUBLE; 180764Speter case O_EXPO: 181764Speter if (isnta( p1 , "id" ) ) { 182764Speter error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1)); 183764Speter return NIL; 184764Speter } 185764Speter putleaf( P2ICON , 0 , 0 186764Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_EXPO" ); 187764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 18810376Speter sconv(p2type(p1), P2DOUBLE); 189764Speter putop( P2CALL , P2INT ); 190764Speter return ( nl + T4INT ); 191764Speter case O_UNDEF: 192764Speter if ( isnta( p1 , "id" ) ) { 193764Speter error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1)); 194764Speter return NIL; 195764Speter } 196764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 197*10669Speter putleaf( P2ICON , 0 , 0 , P2CHAR , 0 ); 198*10669Speter putop( P2COMOP , P2CHAR ); 199764Speter return ( nl + TBOOL ); 200764Speter case O_SEED: 201764Speter if (isnta(p1, "i")) { 202764Speter error("seed's argument must be an integer, not %s", nameof(p1)); 203764Speter return (NIL); 204764Speter } 205764Speter putleaf( P2ICON , 0 , 0 206764Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_SEED" ); 207764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 208764Speter putop( P2CALL , P2INT ); 209764Speter return nl + T4INT; 210764Speter case O_ROUND: 211764Speter case O_TRUNC: 212764Speter if ( isnta( p1 , "d" ) ) { 213764Speter error("%s's argument must be a real, not %s", p->symbol, nameof(p1)); 214764Speter return (NIL); 215764Speter } 216764Speter putleaf( P2ICON , 0 , 0 217764Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) 218764Speter , op == O_ROUND ? "_ROUND" : "_TRUNC" ); 219764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 220764Speter putop( P2CALL , P2INT ); 221764Speter return nl + T4INT; 222764Speter case O_ABS2: 223764Speter if ( isa( p1 , "d" ) ) { 224764Speter putleaf( P2ICON , 0 , 0 225764Speter , ADDTYPE( P2FTN | P2DOUBLE , P2PTR ) 226764Speter , "_fabs" ); 227764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 228764Speter putop( P2CALL , P2DOUBLE ); 229764Speter return nl + TDOUBLE; 230764Speter } 231764Speter if ( isa( p1 , "i" ) ) { 232764Speter putleaf( P2ICON , 0 , 0 233764Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_abs" ); 234764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 235764Speter putop( P2CALL , P2INT ); 236764Speter return nl + T4INT; 237764Speter } 238764Speter error("%s's argument must be an integer or real, not %s", p->symbol, nameof(p1)); 239764Speter return NIL; 240764Speter case O_SQR2: 241764Speter if ( isa( p1 , "d" ) ) { 242764Speter temptype = P2DOUBLE; 243764Speter rettype = nl + TDOUBLE; 2443831Speter tempnlp = tmpalloc(sizeof(double), rettype, REGOK); 245764Speter } else if ( isa( p1 , "i" ) ) { 246764Speter temptype = P2INT; 247764Speter rettype = nl + T4INT; 2483831Speter tempnlp = tmpalloc(sizeof(long), rettype, REGOK); 249764Speter } else { 250764Speter error("%s's argument must be an integer or real, not %s", p->symbol, nameof(p1)); 251764Speter return NIL; 252764Speter } 2533831Speter putRV( 0 , cbn , tempnlp -> value[ NL_OFFS ] , 2543831Speter tempnlp -> extra_flags , temptype , 0 ); 255764Speter p1 = rvalue( (int *) argv[1] , NLNIL , RREQ ); 25610376Speter sconv(p2type(p1), temptype); 257764Speter putop( P2ASSIGN , temptype ); 2583831Speter putRV( 0 , cbn , tempnlp -> value[ NL_OFFS ] , 2593831Speter tempnlp -> extra_flags , temptype , 0 ); 2603831Speter putRV( 0 , cbn , tempnlp -> value[ NL_OFFS ] , 2613831Speter tempnlp -> extra_flags , temptype , 0 ); 262764Speter putop( P2MUL , temptype ); 263764Speter putop( P2COMOP , temptype ); 264764Speter return rettype; 265764Speter case O_ORD2: 266764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 2679573Speter if (isa(p1, "bcis")) { 268764Speter return (nl+T4INT); 269764Speter } 2709573Speter if (classify(p1) == TPTR) { 2719573Speter if (!opt('s')) { 2729573Speter return (nl+T4INT); 2739573Speter } 2749573Speter standard(); 2759573Speter } 2769573Speter error("ord's argument must be of scalar type, not %s", 2779573Speter nameof(p1)); 278764Speter return (NIL); 279764Speter case O_SUCC2: 280764Speter case O_PRED2: 281764Speter if (isa(p1, "d")) { 282764Speter error("%s is forbidden for reals", p->symbol); 283764Speter return (NIL); 284764Speter } 285764Speter if ( isnta( p1 , "bcsi" ) ) { 286764Speter error("%s's argument must be of scalar type, not %s", p->symbol, nameof(p1)); 287764Speter return NIL; 288764Speter } 289764Speter if ( opt( 't' ) ) { 290764Speter putleaf( P2ICON , 0 , 0 291764Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) 292764Speter , op == O_SUCC2 ? "_SUCC" : "_PRED" ); 293764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 2946596Smckusick tempnlp = p1 -> class == TYPE ? p1 -> type : p1; 2956596Smckusick putleaf( P2ICON, tempnlp -> range[0], 0, P2INT, 0 ); 296764Speter putop( P2LISTOP , P2INT ); 2976596Smckusick putleaf( P2ICON, tempnlp -> range[1], 0, P2INT, 0 ); 298764Speter putop( P2LISTOP , P2INT ); 299764Speter putop( P2CALL , P2INT ); 300*10669Speter sconv(P2INT, p2type(p1)); 301764Speter } else { 302*10669Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 303764Speter putleaf( P2ICON , 1 , 0 , P2INT , 0 ); 304764Speter putop( op == O_SUCC2 ? P2PLUS : P2MINUS , P2INT ); 305*10669Speter sconv(P2INT, p2type(p1)); 306764Speter } 307764Speter if ( isa( p1 , "bcs" ) ) { 308764Speter return p1; 309764Speter } else { 310764Speter return nl + T4INT; 311764Speter } 312764Speter case O_ODD2: 313764Speter if (isnta(p1, "i")) { 314764Speter error("odd's argument must be an integer, not %s", nameof(p1)); 315764Speter return (NIL); 316764Speter } 317*10669Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 318*10669Speter /* 319*10669Speter * THIS IS MACHINE-DEPENDENT!!! 320*10669Speter */ 321764Speter putleaf( P2ICON , 1 , 0 , P2INT , 0 ); 322764Speter putop( P2AND , P2INT ); 323*10669Speter sconv(P2INT, P2CHAR); 324764Speter return nl + TBOOL; 325764Speter case O_CHR2: 326764Speter if (isnta(p1, "i")) { 327764Speter error("chr's argument must be an integer, not %s", nameof(p1)); 328764Speter return (NIL); 329764Speter } 330764Speter if (opt('t')) { 331764Speter putleaf( P2ICON , 0 , 0 332764Speter , ADDTYPE( P2FTN | P2CHAR , P2PTR ) , "_CHR" ); 333764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 334764Speter putop( P2CALL , P2CHAR ); 335764Speter } else { 336764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 337*10669Speter sconv(P2INT, P2CHAR); 338764Speter } 339764Speter return nl + TCHAR; 340764Speter case O_CARD: 3411554Speter if (isnta(p1, "t")) { 3421554Speter error("Argument to card must be a set, not %s", nameof(p1)); 3431554Speter return (NIL); 344764Speter } 3451554Speter putleaf( P2ICON , 0 , 0 3461554Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_CARD" ); 3471554Speter p1 = stkrval( (int *) argv[1] , NLNIL , LREQ ); 3481554Speter putleaf( P2ICON , lwidth( p1 ) , 0 , P2INT , 0 ); 3491554Speter putop( P2LISTOP , P2INT ); 3501554Speter putop( P2CALL , P2INT ); 351*10669Speter return nl + T4INT; 352764Speter case O_EOLN: 353764Speter if (!text(p1)) { 354764Speter error("Argument to eoln must be a text file, not %s", nameof(p1)); 355764Speter return (NIL); 356764Speter } 357764Speter putleaf( P2ICON , 0 , 0 358764Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_TEOLN" ); 359764Speter p1 = stklval( (int *) argv[1] , NOFLAGS ); 360764Speter putop( P2CALL , P2INT ); 361*10669Speter sconv(P2INT, P2CHAR); 362764Speter return nl + TBOOL; 363764Speter case O_EOF: 364764Speter if (p1->class != FILET) { 365764Speter error("Argument to eof must be file, not %s", nameof(p1)); 366764Speter return (NIL); 367764Speter } 368764Speter putleaf( P2ICON , 0 , 0 369764Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_TEOF" ); 370764Speter p1 = stklval( (int *) argv[1] , NOFLAGS ); 371764Speter putop( P2CALL , P2INT ); 372*10669Speter sconv(P2INT, P2CHAR); 373764Speter return nl + TBOOL; 374764Speter case 0: 375764Speter error("%s is an unimplemented 6000-3.4 extension", p->symbol); 376764Speter default: 377764Speter panic("func1"); 378764Speter } 379764Speter } 380764Speter #endif PC 381