1764Speter /* Copyright (c) 1979 Regents of the University of California */ 2764Speter 3*11328Speter static char sccsid[] = "@(#)pcfunc.c 1.13 02/28/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" 16*11328Speter #include "tmps.h" 17764Speter 18764Speter /* 19764Speter * Funccod generates code for 20764Speter * built in function calls and calls 21764Speter * call to generate calls to user 22764Speter * defined functions and procedures. 23764Speter */ 24764Speter pcfunccod( r ) 25764Speter int *r; 26764Speter { 27764Speter struct nl *p; 28764Speter register struct nl *p1; 29764Speter register int *al; 30764Speter register op; 31764Speter int argc, *argv; 32764Speter int tr[2], tr2[4]; 33764Speter char *funcname; 343831Speter struct nl *tempnlp; 35764Speter long temptype; 36764Speter struct nl *rettype; 37764Speter 38764Speter /* 39764Speter * Verify that the given name 40764Speter * is defined and the name of 41764Speter * a function. 42764Speter */ 43764Speter p = lookup(r[2]); 44764Speter if (p == NIL) { 45764Speter rvlist(r[3]); 46764Speter return (NIL); 47764Speter } 481197Speter if (p->class != FUNC && p->class != FFUNC) { 49764Speter error("%s is not a function", p->symbol); 50764Speter rvlist(r[3]); 51764Speter return (NIL); 52764Speter } 53764Speter argv = r[3]; 54764Speter /* 55764Speter * Call handles user defined 56764Speter * procedures and functions 57764Speter */ 58764Speter if (bn != 0) 59764Speter return (call(p, argv, FUNC, bn)); 60764Speter /* 61764Speter * Count the arguments 62764Speter */ 63764Speter argc = 0; 64764Speter for (al = argv; al != NIL; al = al[2]) 65764Speter argc++; 66764Speter /* 67764Speter * Built-in functions have 68764Speter * their interpreter opcode 69764Speter * associated with them. 70764Speter */ 71764Speter op = p->value[0] &~ NSTAND; 72764Speter if (opt('s') && (p->value[0] & NSTAND)) { 73764Speter standard(); 74764Speter error("%s is a nonstandard function", p->symbol); 75764Speter } 76764Speter if ( op == O_ARGC ) { 77764Speter putleaf( P2NAME , 0 , 0 , P2INT , "__argc" ); 78764Speter return nl + T4INT; 79764Speter } 80764Speter switch (op) { 81764Speter /* 82764Speter * Parameterless functions 83764Speter */ 84764Speter case O_CLCK: 85764Speter funcname = "_CLCK"; 86764Speter goto noargs; 87764Speter case O_SCLCK: 88764Speter funcname = "_SCLCK"; 89764Speter goto noargs; 90764Speter noargs: 91764Speter if (argc != 0) { 92764Speter error("%s takes no arguments", p->symbol); 93764Speter rvlist(argv); 94764Speter return (NIL); 95764Speter } 96764Speter putleaf( P2ICON , 0 , 0 97764Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) 98764Speter , funcname ); 99764Speter putop( P2UNARY P2CALL , P2INT ); 100764Speter return (nl+T4INT); 101764Speter case O_WCLCK: 102764Speter if (argc != 0) { 103764Speter error("%s takes no arguments", p->symbol); 104764Speter rvlist(argv); 105764Speter return (NIL); 106764Speter } 107764Speter putleaf( P2ICON , 0 , 0 108764Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) 109764Speter , "_time" ); 110764Speter putleaf( P2ICON , 0 , 0 , P2INT , 0 ); 111764Speter putop( P2CALL , P2INT ); 112764Speter return (nl+T4INT); 113764Speter case O_EOF: 114764Speter case O_EOLN: 115764Speter if (argc == 0) { 116764Speter argv = tr; 117764Speter tr[1] = tr2; 118764Speter tr2[0] = T_VAR; 119764Speter tr2[2] = input->symbol; 120764Speter tr2[1] = tr2[3] = NIL; 121764Speter argc = 1; 122764Speter } else if (argc != 1) { 123764Speter error("%s takes either zero or one argument", p->symbol); 124764Speter rvlist(argv); 125764Speter return (NIL); 126764Speter } 127764Speter } 128764Speter /* 129764Speter * All other functions take 130764Speter * exactly one argument. 131764Speter */ 132764Speter if (argc != 1) { 133764Speter error("%s takes exactly one argument", p->symbol); 134764Speter rvlist(argv); 135764Speter return (NIL); 136764Speter } 137764Speter /* 138764Speter * find out the type of the argument 139764Speter */ 140764Speter codeoff(); 141764Speter p1 = stkrval((int *) argv[1], NLNIL , RREQ ); 142764Speter codeon(); 143764Speter if (p1 == NIL) 144764Speter return (NIL); 145764Speter /* 146764Speter * figure out the return type and the funtion name 147764Speter */ 148764Speter switch (op) { 149764Speter case O_EXP: 1505715Smckusic funcname = opt('t') ? "_EXP" : "_exp"; 151764Speter goto mathfunc; 152764Speter case O_SIN: 1535715Smckusic funcname = opt('t') ? "_SIN" : "_sin"; 154764Speter goto mathfunc; 155764Speter case O_COS: 1565715Smckusic funcname = opt('t') ? "_COS" : "_cos"; 157764Speter goto mathfunc; 158764Speter case O_ATAN: 1595715Smckusic funcname = opt('t') ? "_ATAN" : "_atan"; 160764Speter goto mathfunc; 161764Speter case O_LN: 162764Speter funcname = opt('t') ? "_LN" : "_log"; 163764Speter goto mathfunc; 164764Speter case O_SQRT: 165764Speter funcname = opt('t') ? "_SQRT" : "_sqrt"; 166764Speter goto mathfunc; 167764Speter case O_RANDOM: 168764Speter funcname = "_RANDOM"; 169764Speter goto mathfunc; 170764Speter mathfunc: 171764Speter if (isnta(p1, "id")) { 172764Speter error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1)); 173764Speter return (NIL); 174764Speter } 175764Speter putleaf( P2ICON , 0 , 0 176764Speter , ADDTYPE( P2FTN | P2DOUBLE , P2PTR ) , funcname ); 177764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 17810376Speter sconv(p2type(p1), P2DOUBLE); 179764Speter putop( P2CALL , P2DOUBLE ); 180764Speter return nl + TDOUBLE; 181764Speter case O_EXPO: 182764Speter if (isnta( p1 , "id" ) ) { 183764Speter error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1)); 184764Speter return NIL; 185764Speter } 186764Speter putleaf( P2ICON , 0 , 0 187764Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_EXPO" ); 188764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 18910376Speter sconv(p2type(p1), P2DOUBLE); 190764Speter putop( P2CALL , P2INT ); 191764Speter return ( nl + T4INT ); 192764Speter case O_UNDEF: 193764Speter if ( isnta( p1 , "id" ) ) { 194764Speter error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1)); 195764Speter return NIL; 196764Speter } 197764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 19810669Speter putleaf( P2ICON , 0 , 0 , P2CHAR , 0 ); 19910669Speter putop( P2COMOP , P2CHAR ); 200764Speter return ( nl + TBOOL ); 201764Speter case O_SEED: 202764Speter if (isnta(p1, "i")) { 203764Speter error("seed's argument must be an integer, not %s", nameof(p1)); 204764Speter return (NIL); 205764Speter } 206764Speter putleaf( P2ICON , 0 , 0 207764Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_SEED" ); 208764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 209764Speter putop( P2CALL , P2INT ); 210764Speter return nl + T4INT; 211764Speter case O_ROUND: 212764Speter case O_TRUNC: 213764Speter if ( isnta( p1 , "d" ) ) { 214764Speter error("%s's argument must be a real, not %s", p->symbol, nameof(p1)); 215764Speter return (NIL); 216764Speter } 217764Speter putleaf( P2ICON , 0 , 0 218764Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) 219764Speter , op == O_ROUND ? "_ROUND" : "_TRUNC" ); 220764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 221764Speter putop( P2CALL , P2INT ); 222764Speter return nl + T4INT; 223764Speter case O_ABS2: 224764Speter if ( isa( p1 , "d" ) ) { 225764Speter putleaf( P2ICON , 0 , 0 226764Speter , ADDTYPE( P2FTN | P2DOUBLE , P2PTR ) 227764Speter , "_fabs" ); 228764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 229764Speter putop( P2CALL , P2DOUBLE ); 230764Speter return nl + TDOUBLE; 231764Speter } 232764Speter if ( isa( p1 , "i" ) ) { 233764Speter putleaf( P2ICON , 0 , 0 234764Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_abs" ); 235764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 236764Speter putop( P2CALL , P2INT ); 237764Speter return nl + T4INT; 238764Speter } 239764Speter error("%s's argument must be an integer or real, not %s", p->symbol, nameof(p1)); 240764Speter return NIL; 241764Speter case O_SQR2: 242764Speter if ( isa( p1 , "d" ) ) { 243764Speter temptype = P2DOUBLE; 244764Speter rettype = nl + TDOUBLE; 2453831Speter tempnlp = tmpalloc(sizeof(double), rettype, REGOK); 246764Speter } else if ( isa( p1 , "i" ) ) { 247764Speter temptype = P2INT; 248764Speter rettype = nl + T4INT; 2493831Speter tempnlp = tmpalloc(sizeof(long), rettype, REGOK); 250764Speter } else { 251764Speter error("%s's argument must be an integer or real, not %s", p->symbol, nameof(p1)); 252764Speter return NIL; 253764Speter } 2543831Speter putRV( 0 , cbn , tempnlp -> value[ NL_OFFS ] , 2553831Speter tempnlp -> extra_flags , temptype , 0 ); 256764Speter p1 = rvalue( (int *) argv[1] , NLNIL , RREQ ); 25710376Speter sconv(p2type(p1), temptype); 258764Speter putop( P2ASSIGN , temptype ); 2593831Speter putRV( 0 , cbn , tempnlp -> value[ NL_OFFS ] , 2603831Speter tempnlp -> extra_flags , temptype , 0 ); 2613831Speter putRV( 0 , cbn , tempnlp -> value[ NL_OFFS ] , 2623831Speter tempnlp -> extra_flags , temptype , 0 ); 263764Speter putop( P2MUL , temptype ); 264764Speter putop( P2COMOP , temptype ); 265764Speter return rettype; 266764Speter case O_ORD2: 267764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 2689573Speter if (isa(p1, "bcis")) { 269764Speter return (nl+T4INT); 270764Speter } 2719573Speter if (classify(p1) == TPTR) { 2729573Speter if (!opt('s')) { 2739573Speter return (nl+T4INT); 2749573Speter } 2759573Speter standard(); 2769573Speter } 2779573Speter error("ord's argument must be of scalar type, not %s", 2789573Speter nameof(p1)); 279764Speter return (NIL); 280764Speter case O_SUCC2: 281764Speter case O_PRED2: 282764Speter if (isa(p1, "d")) { 283764Speter error("%s is forbidden for reals", p->symbol); 284764Speter return (NIL); 285764Speter } 286764Speter if ( isnta( p1 , "bcsi" ) ) { 287764Speter error("%s's argument must be of scalar type, not %s", p->symbol, nameof(p1)); 288764Speter return NIL; 289764Speter } 290764Speter if ( opt( 't' ) ) { 291764Speter putleaf( P2ICON , 0 , 0 292764Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) 293764Speter , op == O_SUCC2 ? "_SUCC" : "_PRED" ); 294764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 2956596Smckusick tempnlp = p1 -> class == TYPE ? p1 -> type : p1; 2966596Smckusick putleaf( P2ICON, tempnlp -> range[0], 0, P2INT, 0 ); 297764Speter putop( P2LISTOP , P2INT ); 2986596Smckusick putleaf( P2ICON, tempnlp -> range[1], 0, P2INT, 0 ); 299764Speter putop( P2LISTOP , P2INT ); 300764Speter putop( P2CALL , P2INT ); 30110669Speter sconv(P2INT, p2type(p1)); 302764Speter } else { 30310669Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 304764Speter putleaf( P2ICON , 1 , 0 , P2INT , 0 ); 305764Speter putop( op == O_SUCC2 ? P2PLUS : P2MINUS , P2INT ); 30610669Speter sconv(P2INT, p2type(p1)); 307764Speter } 308764Speter if ( isa( p1 , "bcs" ) ) { 309764Speter return p1; 310764Speter } else { 311764Speter return nl + T4INT; 312764Speter } 313764Speter case O_ODD2: 314764Speter if (isnta(p1, "i")) { 315764Speter error("odd's argument must be an integer, not %s", nameof(p1)); 316764Speter return (NIL); 317764Speter } 31810669Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 31910669Speter /* 32010669Speter * THIS IS MACHINE-DEPENDENT!!! 32110669Speter */ 322764Speter putleaf( P2ICON , 1 , 0 , P2INT , 0 ); 323764Speter putop( P2AND , P2INT ); 32410669Speter sconv(P2INT, P2CHAR); 325764Speter return nl + TBOOL; 326764Speter case O_CHR2: 327764Speter if (isnta(p1, "i")) { 328764Speter error("chr's argument must be an integer, not %s", nameof(p1)); 329764Speter return (NIL); 330764Speter } 331764Speter if (opt('t')) { 332764Speter putleaf( P2ICON , 0 , 0 333764Speter , ADDTYPE( P2FTN | P2CHAR , P2PTR ) , "_CHR" ); 334764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 335764Speter putop( P2CALL , P2CHAR ); 336764Speter } else { 337764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 33810669Speter sconv(P2INT, P2CHAR); 339764Speter } 340764Speter return nl + TCHAR; 341764Speter case O_CARD: 3421554Speter if (isnta(p1, "t")) { 3431554Speter error("Argument to card must be a set, not %s", nameof(p1)); 3441554Speter return (NIL); 345764Speter } 3461554Speter putleaf( P2ICON , 0 , 0 3471554Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_CARD" ); 3481554Speter p1 = stkrval( (int *) argv[1] , NLNIL , LREQ ); 3491554Speter putleaf( P2ICON , lwidth( p1 ) , 0 , P2INT , 0 ); 3501554Speter putop( P2LISTOP , P2INT ); 3511554Speter putop( P2CALL , P2INT ); 35210669Speter return nl + T4INT; 353764Speter case O_EOLN: 354764Speter if (!text(p1)) { 355764Speter error("Argument to eoln must be a text file, not %s", nameof(p1)); 356764Speter return (NIL); 357764Speter } 358764Speter putleaf( P2ICON , 0 , 0 359764Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_TEOLN" ); 360764Speter p1 = stklval( (int *) argv[1] , NOFLAGS ); 361764Speter putop( P2CALL , P2INT ); 36210669Speter sconv(P2INT, P2CHAR); 363764Speter return nl + TBOOL; 364764Speter case O_EOF: 365764Speter if (p1->class != FILET) { 366764Speter error("Argument to eof must be file, not %s", nameof(p1)); 367764Speter return (NIL); 368764Speter } 369764Speter putleaf( P2ICON , 0 , 0 370764Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_TEOF" ); 371764Speter p1 = stklval( (int *) argv[1] , NOFLAGS ); 372764Speter putop( P2CALL , P2INT ); 37310669Speter sconv(P2INT, P2CHAR); 374764Speter return nl + TBOOL; 375764Speter case 0: 376764Speter error("%s is an unimplemented 6000-3.4 extension", p->symbol); 377764Speter default: 378764Speter panic("func1"); 379764Speter } 380764Speter } 381764Speter #endif PC 382