1764Speter /* Copyright (c) 1979 Regents of the University of California */ 2764Speter 3*9573Speter static char sccsid[] = "@(#)pcfunc.c 1.9 12/06/82"; 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" 12764Speter #include "opcode.h" 13764Speter #include "pc.h" 14764Speter #include "pcops.h" 15764Speter 16764Speter /* 17764Speter * Funccod generates code for 18764Speter * built in function calls and calls 19764Speter * call to generate calls to user 20764Speter * defined functions and procedures. 21764Speter */ 22764Speter pcfunccod( r ) 23764Speter int *r; 24764Speter { 25764Speter struct nl *p; 26764Speter register struct nl *p1; 27764Speter register int *al; 28764Speter register op; 29764Speter int argc, *argv; 30764Speter int tr[2], tr2[4]; 31764Speter char *funcname; 323831Speter struct nl *tempnlp; 33764Speter long temptype; 34764Speter struct nl *rettype; 35764Speter 36764Speter /* 37764Speter * Verify that the given name 38764Speter * is defined and the name of 39764Speter * a function. 40764Speter */ 41764Speter p = lookup(r[2]); 42764Speter if (p == NIL) { 43764Speter rvlist(r[3]); 44764Speter return (NIL); 45764Speter } 461197Speter if (p->class != FUNC && p->class != FFUNC) { 47764Speter error("%s is not a function", p->symbol); 48764Speter rvlist(r[3]); 49764Speter return (NIL); 50764Speter } 51764Speter argv = r[3]; 52764Speter /* 53764Speter * Call handles user defined 54764Speter * procedures and functions 55764Speter */ 56764Speter if (bn != 0) 57764Speter return (call(p, argv, FUNC, bn)); 58764Speter /* 59764Speter * Count the arguments 60764Speter */ 61764Speter argc = 0; 62764Speter for (al = argv; al != NIL; al = al[2]) 63764Speter argc++; 64764Speter /* 65764Speter * Built-in functions have 66764Speter * their interpreter opcode 67764Speter * associated with them. 68764Speter */ 69764Speter op = p->value[0] &~ NSTAND; 70764Speter if (opt('s') && (p->value[0] & NSTAND)) { 71764Speter standard(); 72764Speter error("%s is a nonstandard function", p->symbol); 73764Speter } 74764Speter if ( op == O_ARGC ) { 75764Speter putleaf( P2NAME , 0 , 0 , P2INT , "__argc" ); 76764Speter return nl + T4INT; 77764Speter } 78764Speter switch (op) { 79764Speter /* 80764Speter * Parameterless functions 81764Speter */ 82764Speter case O_CLCK: 83764Speter funcname = "_CLCK"; 84764Speter goto noargs; 85764Speter case O_SCLCK: 86764Speter funcname = "_SCLCK"; 87764Speter goto noargs; 88764Speter noargs: 89764Speter if (argc != 0) { 90764Speter error("%s takes no arguments", p->symbol); 91764Speter rvlist(argv); 92764Speter return (NIL); 93764Speter } 94764Speter putleaf( P2ICON , 0 , 0 95764Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) 96764Speter , funcname ); 97764Speter putop( P2UNARY P2CALL , P2INT ); 98764Speter return (nl+T4INT); 99764Speter case O_WCLCK: 100764Speter if (argc != 0) { 101764Speter error("%s takes no arguments", p->symbol); 102764Speter rvlist(argv); 103764Speter return (NIL); 104764Speter } 105764Speter putleaf( P2ICON , 0 , 0 106764Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) 107764Speter , "_time" ); 108764Speter putleaf( P2ICON , 0 , 0 , P2INT , 0 ); 109764Speter putop( P2CALL , P2INT ); 110764Speter return (nl+T4INT); 111764Speter case O_EOF: 112764Speter case O_EOLN: 113764Speter if (argc == 0) { 114764Speter argv = tr; 115764Speter tr[1] = tr2; 116764Speter tr2[0] = T_VAR; 117764Speter tr2[2] = input->symbol; 118764Speter tr2[1] = tr2[3] = NIL; 119764Speter argc = 1; 120764Speter } else if (argc != 1) { 121764Speter error("%s takes either zero or one argument", p->symbol); 122764Speter rvlist(argv); 123764Speter return (NIL); 124764Speter } 125764Speter } 126764Speter /* 127764Speter * All other functions take 128764Speter * exactly one argument. 129764Speter */ 130764Speter if (argc != 1) { 131764Speter error("%s takes exactly one argument", p->symbol); 132764Speter rvlist(argv); 133764Speter return (NIL); 134764Speter } 135764Speter /* 136764Speter * find out the type of the argument 137764Speter */ 138764Speter codeoff(); 139764Speter p1 = stkrval((int *) argv[1], NLNIL , RREQ ); 140764Speter codeon(); 141764Speter if (p1 == NIL) 142764Speter return (NIL); 143764Speter /* 144764Speter * figure out the return type and the funtion name 145764Speter */ 146764Speter switch (op) { 147764Speter case O_EXP: 1485715Smckusic funcname = opt('t') ? "_EXP" : "_exp"; 149764Speter goto mathfunc; 150764Speter case O_SIN: 1515715Smckusic funcname = opt('t') ? "_SIN" : "_sin"; 152764Speter goto mathfunc; 153764Speter case O_COS: 1545715Smckusic funcname = opt('t') ? "_COS" : "_cos"; 155764Speter goto mathfunc; 156764Speter case O_ATAN: 1575715Smckusic funcname = opt('t') ? "_ATAN" : "_atan"; 158764Speter goto mathfunc; 159764Speter case O_LN: 160764Speter funcname = opt('t') ? "_LN" : "_log"; 161764Speter goto mathfunc; 162764Speter case O_SQRT: 163764Speter funcname = opt('t') ? "_SQRT" : "_sqrt"; 164764Speter goto mathfunc; 165764Speter case O_RANDOM: 166764Speter funcname = "_RANDOM"; 167764Speter goto mathfunc; 168764Speter mathfunc: 169764Speter if (isnta(p1, "id")) { 170764Speter error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1)); 171764Speter return (NIL); 172764Speter } 173764Speter putleaf( P2ICON , 0 , 0 174764Speter , ADDTYPE( P2FTN | P2DOUBLE , P2PTR ) , funcname ); 175764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 176764Speter if ( isa( p1 , "i" ) ) { 177764Speter putop( P2SCONV , P2DOUBLE ); 178764Speter } 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 ); 189764Speter if ( isa( p1 , "i" ) ) { 190764Speter putop( P2SCONV , P2DOUBLE ); 191764Speter } 192764Speter putop( P2CALL , P2INT ); 193764Speter return ( nl + T4INT ); 194764Speter case O_UNDEF: 195764Speter if ( isnta( p1 , "id" ) ) { 196764Speter error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1)); 197764Speter return NIL; 198764Speter } 199764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 200764Speter putleaf( P2ICON , 0 , 0 , P2INT , 0 ); 201764Speter putop( P2COMOP , P2INT ); 202764Speter return ( nl + TBOOL ); 203764Speter case O_SEED: 204764Speter if (isnta(p1, "i")) { 205764Speter error("seed's argument must be an integer, not %s", nameof(p1)); 206764Speter return (NIL); 207764Speter } 208764Speter putleaf( P2ICON , 0 , 0 209764Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_SEED" ); 210764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 211764Speter putop( P2CALL , P2INT ); 212764Speter return nl + T4INT; 213764Speter case O_ROUND: 214764Speter case O_TRUNC: 215764Speter if ( isnta( p1 , "d" ) ) { 216764Speter error("%s's argument must be a real, not %s", p->symbol, nameof(p1)); 217764Speter return (NIL); 218764Speter } 219764Speter putleaf( P2ICON , 0 , 0 220764Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) 221764Speter , op == O_ROUND ? "_ROUND" : "_TRUNC" ); 222764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 223764Speter putop( P2CALL , P2INT ); 224764Speter return nl + T4INT; 225764Speter case O_ABS2: 226764Speter if ( isa( p1 , "d" ) ) { 227764Speter putleaf( P2ICON , 0 , 0 228764Speter , ADDTYPE( P2FTN | P2DOUBLE , P2PTR ) 229764Speter , "_fabs" ); 230764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 231764Speter putop( P2CALL , P2DOUBLE ); 232764Speter return nl + TDOUBLE; 233764Speter } 234764Speter if ( isa( p1 , "i" ) ) { 235764Speter putleaf( P2ICON , 0 , 0 236764Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_abs" ); 237764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 238764Speter putop( P2CALL , P2INT ); 239764Speter return nl + T4INT; 240764Speter } 241764Speter error("%s's argument must be an integer or real, not %s", p->symbol, nameof(p1)); 242764Speter return NIL; 243764Speter case O_SQR2: 244764Speter if ( isa( p1 , "d" ) ) { 245764Speter temptype = P2DOUBLE; 246764Speter rettype = nl + TDOUBLE; 2473831Speter tempnlp = tmpalloc(sizeof(double), rettype, REGOK); 248764Speter } else if ( isa( p1 , "i" ) ) { 249764Speter temptype = P2INT; 250764Speter rettype = nl + T4INT; 2513831Speter tempnlp = tmpalloc(sizeof(long), rettype, REGOK); 252764Speter } else { 253764Speter error("%s's argument must be an integer or real, not %s", p->symbol, nameof(p1)); 254764Speter return NIL; 255764Speter } 2563831Speter putRV( 0 , cbn , tempnlp -> value[ NL_OFFS ] , 2573831Speter tempnlp -> extra_flags , temptype , 0 ); 258764Speter p1 = rvalue( (int *) argv[1] , NLNIL , RREQ ); 259764Speter putop( P2ASSIGN , temptype ); 2603831Speter putRV( 0 , cbn , tempnlp -> value[ NL_OFFS ] , 2613831Speter tempnlp -> extra_flags , temptype , 0 ); 2623831Speter putRV( 0 , cbn , tempnlp -> value[ NL_OFFS ] , 2633831Speter tempnlp -> extra_flags , temptype , 0 ); 264764Speter putop( P2MUL , temptype ); 265764Speter putop( P2COMOP , temptype ); 266764Speter return rettype; 267764Speter case O_ORD2: 268764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 269*9573Speter if (isa(p1, "bcis")) { 270764Speter return (nl+T4INT); 271764Speter } 272*9573Speter if (classify(p1) == TPTR) { 273*9573Speter if (!opt('s')) { 274*9573Speter return (nl+T4INT); 275*9573Speter } 276*9573Speter standard(); 277*9573Speter } 278*9573Speter error("ord's argument must be of scalar type, not %s", 279*9573Speter nameof(p1)); 280764Speter return (NIL); 281764Speter case O_SUCC2: 282764Speter case O_PRED2: 283764Speter if (isa(p1, "d")) { 284764Speter error("%s is forbidden for reals", p->symbol); 285764Speter return (NIL); 286764Speter } 287764Speter if ( isnta( p1 , "bcsi" ) ) { 288764Speter error("%s's argument must be of scalar type, not %s", p->symbol, nameof(p1)); 289764Speter return NIL; 290764Speter } 291764Speter if ( opt( 't' ) ) { 292764Speter putleaf( P2ICON , 0 , 0 293764Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) 294764Speter , op == O_SUCC2 ? "_SUCC" : "_PRED" ); 295764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 2966596Smckusick tempnlp = p1 -> class == TYPE ? p1 -> type : p1; 2976596Smckusick putleaf( P2ICON, tempnlp -> range[0], 0, P2INT, 0 ); 298764Speter putop( P2LISTOP , P2INT ); 2996596Smckusick putleaf( P2ICON, tempnlp -> range[1], 0, P2INT, 0 ); 300764Speter putop( P2LISTOP , P2INT ); 301764Speter putop( P2CALL , P2INT ); 302764Speter } else { 303764Speter p1 = rvalue( argv[1] , NIL , RREQ ); 304764Speter putleaf( P2ICON , 1 , 0 , P2INT , 0 ); 305764Speter putop( op == O_SUCC2 ? P2PLUS : P2MINUS , P2INT ); 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 } 317764Speter p1 = rvalue( (int *) argv[1] , NLNIL , RREQ ); 318764Speter putleaf( P2ICON , 1 , 0 , P2INT , 0 ); 319764Speter putop( P2AND , P2INT ); 320764Speter return nl + TBOOL; 321764Speter case O_CHR2: 322764Speter if (isnta(p1, "i")) { 323764Speter error("chr's argument must be an integer, not %s", nameof(p1)); 324764Speter return (NIL); 325764Speter } 326764Speter if (opt('t')) { 327764Speter putleaf( P2ICON , 0 , 0 328764Speter , ADDTYPE( P2FTN | P2CHAR , P2PTR ) , "_CHR" ); 329764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 330764Speter putop( P2CALL , P2CHAR ); 331764Speter } else { 332764Speter p1 = stkrval( (int *) argv[1] , NLNIL , RREQ ); 333764Speter } 334764Speter return nl + TCHAR; 335764Speter case O_CARD: 3361554Speter if (isnta(p1, "t")) { 3371554Speter error("Argument to card must be a set, not %s", nameof(p1)); 3381554Speter return (NIL); 339764Speter } 3401554Speter putleaf( P2ICON , 0 , 0 3411554Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_CARD" ); 3421554Speter p1 = stkrval( (int *) argv[1] , NLNIL , LREQ ); 3431554Speter putleaf( P2ICON , lwidth( p1 ) , 0 , P2INT , 0 ); 3441554Speter putop( P2LISTOP , P2INT ); 3451554Speter putop( P2CALL , P2INT ); 346764Speter return nl + T2INT; 347764Speter case O_EOLN: 348764Speter if (!text(p1)) { 349764Speter error("Argument to eoln must be a text file, not %s", nameof(p1)); 350764Speter return (NIL); 351764Speter } 352764Speter putleaf( P2ICON , 0 , 0 353764Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_TEOLN" ); 354764Speter p1 = stklval( (int *) argv[1] , NOFLAGS ); 355764Speter putop( P2CALL , P2INT ); 356764Speter return nl + TBOOL; 357764Speter case O_EOF: 358764Speter if (p1->class != FILET) { 359764Speter error("Argument to eof must be file, not %s", nameof(p1)); 360764Speter return (NIL); 361764Speter } 362764Speter putleaf( P2ICON , 0 , 0 363764Speter , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_TEOF" ); 364764Speter p1 = stklval( (int *) argv[1] , NOFLAGS ); 365764Speter putop( P2CALL , P2INT ); 366764Speter return nl + TBOOL; 367764Speter case 0: 368764Speter error("%s is an unimplemented 6000-3.4 extension", p->symbol); 369764Speter default: 370764Speter panic("func1"); 371764Speter } 372764Speter } 373764Speter #endif PC 374