1764Speter /* Copyright (c) 1979 Regents of the University of California */ 2764Speter 314738Sthien #ifndef lint 4*18464Sralph static char sccsid[] = "@(#)pcfunc.c 2.2 03/20/85"; 514738Sthien #endif 6764Speter 7764Speter #include "whoami.h" 8764Speter #ifdef PC 9764Speter /* 10764Speter * and to the end of the file 11764Speter */ 12764Speter #include "0.h" 13764Speter #include "tree.h" 1410375Speter #include "objfmt.h" 15764Speter #include "opcode.h" 1610375Speter #include "pc.h" 17*18464Sralph #include <pcc.h> 1811328Speter #include "tmps.h" 1914738Sthien #include "tree_ty.h" 20764Speter 21764Speter /* 22764Speter * Funccod generates code for 23764Speter * built in function calls and calls 24764Speter * call to generate calls to user 25764Speter * defined functions and procedures. 26764Speter */ 2714738Sthien struct nl * 28764Speter pcfunccod( r ) 2914738Sthien struct tnode *r; /* T_FCALL */ 30764Speter { 31764Speter struct nl *p; 32764Speter register struct nl *p1; 3314738Sthien register struct tnode *al; 34764Speter register op; 3514738Sthien int argc; 3614738Sthien struct tnode *argv; 3714738Sthien struct tnode tr, tr2; 38764Speter char *funcname; 393831Speter struct nl *tempnlp; 40764Speter long temptype; 41764Speter struct nl *rettype; 42764Speter 43764Speter /* 44764Speter * Verify that the given name 45764Speter * is defined and the name of 46764Speter * a function. 47764Speter */ 4814738Sthien p = lookup(r->pcall_node.proc_id); 4914738Sthien if (p == NLNIL) { 5014738Sthien rvlist(r->pcall_node.arg); 5114738Sthien return (NLNIL); 52764Speter } 531197Speter if (p->class != FUNC && p->class != FFUNC) { 54764Speter error("%s is not a function", p->symbol); 5514738Sthien rvlist(r->pcall_node.arg); 5614738Sthien return (NLNIL); 57764Speter } 5814738Sthien argv = r->pcall_node.arg; 59764Speter /* 60764Speter * Call handles user defined 61764Speter * procedures and functions 62764Speter */ 63764Speter if (bn != 0) 64764Speter return (call(p, argv, FUNC, bn)); 65764Speter /* 66764Speter * Count the arguments 67764Speter */ 68764Speter argc = 0; 6914738Sthien for (al = argv; al != TR_NIL; al = al->list_node.next) 70764Speter argc++; 71764Speter /* 72764Speter * Built-in functions have 73764Speter * their interpreter opcode 74764Speter * associated with them. 75764Speter */ 76764Speter op = p->value[0] &~ NSTAND; 77764Speter if (opt('s') && (p->value[0] & NSTAND)) { 78764Speter standard(); 79764Speter error("%s is a nonstandard function", p->symbol); 80764Speter } 81764Speter if ( op == O_ARGC ) { 82*18464Sralph putleaf( PCC_NAME , 0 , 0 , PCCT_INT , "__argc" ); 83764Speter return nl + T4INT; 84764Speter } 85764Speter switch (op) { 86764Speter /* 87764Speter * Parameterless functions 88764Speter */ 89764Speter case O_CLCK: 90764Speter funcname = "_CLCK"; 91764Speter goto noargs; 92764Speter case O_SCLCK: 93764Speter funcname = "_SCLCK"; 94764Speter goto noargs; 95764Speter noargs: 96764Speter if (argc != 0) { 97764Speter error("%s takes no arguments", p->symbol); 98764Speter rvlist(argv); 9914738Sthien return (NLNIL); 100764Speter } 101*18464Sralph putleaf( PCC_ICON , 0 , 0 102*18464Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 103764Speter , funcname ); 104*18464Sralph putop( PCCOM_UNARY PCC_CALL , PCCT_INT ); 105764Speter return (nl+T4INT); 106764Speter case O_WCLCK: 107764Speter if (argc != 0) { 108764Speter error("%s takes no arguments", p->symbol); 109764Speter rvlist(argv); 11014738Sthien return (NLNIL); 111764Speter } 112*18464Sralph putleaf( PCC_ICON , 0 , 0 113*18464Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 114764Speter , "_time" ); 115*18464Sralph putleaf( PCC_ICON , 0 , 0 , PCCT_INT , (char *) 0 ); 116*18464Sralph putop( PCC_CALL , PCCT_INT ); 117764Speter return (nl+T4INT); 118764Speter case O_EOF: 119764Speter case O_EOLN: 120764Speter if (argc == 0) { 12114738Sthien argv = &(tr); 12214738Sthien tr.list_node.list = &(tr2); 12314738Sthien tr2.tag = T_VAR; 12414738Sthien tr2.var_node.cptr = input->symbol; 12514738Sthien tr2.var_node.line_no = NIL; 12614738Sthien tr2.var_node.qual = TR_NIL; 127764Speter argc = 1; 128764Speter } else if (argc != 1) { 129764Speter error("%s takes either zero or one argument", p->symbol); 130764Speter rvlist(argv); 13114738Sthien return (NLNIL); 132764Speter } 133764Speter } 134764Speter /* 135764Speter * All other functions take 136764Speter * exactly one argument. 137764Speter */ 138764Speter if (argc != 1) { 139764Speter error("%s takes exactly one argument", p->symbol); 140764Speter rvlist(argv); 14114738Sthien return (NLNIL); 142764Speter } 143764Speter /* 144764Speter * find out the type of the argument 145764Speter */ 146764Speter codeoff(); 14714738Sthien p1 = stkrval( argv->list_node.list, NLNIL , (long) RREQ ); 148764Speter codeon(); 14914738Sthien if (p1 == NLNIL) 15014738Sthien return (NLNIL); 151764Speter /* 152764Speter * figure out the return type and the funtion name 153764Speter */ 154764Speter switch (op) { 15514738Sthien case 0: 15614738Sthien error("%s is an unimplemented 6000-3.4 extension", p->symbol); 15714738Sthien default: 15814738Sthien panic("func1"); 159764Speter case O_EXP: 1605715Smckusic funcname = opt('t') ? "_EXP" : "_exp"; 161764Speter goto mathfunc; 162764Speter case O_SIN: 1635715Smckusic funcname = opt('t') ? "_SIN" : "_sin"; 164764Speter goto mathfunc; 165764Speter case O_COS: 1665715Smckusic funcname = opt('t') ? "_COS" : "_cos"; 167764Speter goto mathfunc; 168764Speter case O_ATAN: 1695715Smckusic funcname = opt('t') ? "_ATAN" : "_atan"; 170764Speter goto mathfunc; 171764Speter case O_LN: 172764Speter funcname = opt('t') ? "_LN" : "_log"; 173764Speter goto mathfunc; 174764Speter case O_SQRT: 175764Speter funcname = opt('t') ? "_SQRT" : "_sqrt"; 176764Speter goto mathfunc; 177764Speter case O_RANDOM: 178764Speter funcname = "_RANDOM"; 179764Speter goto mathfunc; 180764Speter mathfunc: 181764Speter if (isnta(p1, "id")) { 182764Speter error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1)); 18314738Sthien return (NLNIL); 184764Speter } 185*18464Sralph putleaf( PCC_ICON , 0 , 0 186*18464Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_DOUBLE , PCCTM_PTR ) , funcname ); 18714738Sthien p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ ); 188*18464Sralph sconv(p2type(p1), PCCT_DOUBLE); 189*18464Sralph putop( PCC_CALL , PCCT_DOUBLE ); 190764Speter return nl + TDOUBLE; 191764Speter case O_EXPO: 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 } 196*18464Sralph putleaf( PCC_ICON , 0 , 0 197*18464Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , "_EXPO" ); 19814738Sthien p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ ); 199*18464Sralph sconv(p2type(p1), PCCT_DOUBLE); 200*18464Sralph putop( PCC_CALL , PCCT_INT ); 201764Speter return ( nl + T4INT ); 202764Speter case O_UNDEF: 203764Speter if ( isnta( p1 , "id" ) ) { 204764Speter error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1)); 20514738Sthien return NLNIL; 206764Speter } 20714738Sthien p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ ); 208*18464Sralph putleaf( PCC_ICON , 0 , 0 , PCCT_CHAR , (char *) 0 ); 209*18464Sralph putop( PCC_COMOP , PCCT_CHAR ); 210764Speter return ( nl + TBOOL ); 211764Speter case O_SEED: 212764Speter if (isnta(p1, "i")) { 213764Speter error("seed's argument must be an integer, not %s", nameof(p1)); 21414738Sthien return (NLNIL); 215764Speter } 216*18464Sralph putleaf( PCC_ICON , 0 , 0 217*18464Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , "_SEED" ); 21814738Sthien p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ ); 219*18464Sralph putop( PCC_CALL , PCCT_INT ); 220764Speter return nl + T4INT; 221764Speter case O_ROUND: 222764Speter case O_TRUNC: 223764Speter if ( isnta( p1 , "d" ) ) { 224764Speter error("%s's argument must be a real, not %s", p->symbol, nameof(p1)); 22514738Sthien return (NLNIL); 226764Speter } 227*18464Sralph putleaf( PCC_ICON , 0 , 0 228*18464Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 229764Speter , op == O_ROUND ? "_ROUND" : "_TRUNC" ); 23014738Sthien p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ ); 231*18464Sralph putop( PCC_CALL , PCCT_INT ); 232764Speter return nl + T4INT; 233764Speter case O_ABS2: 234764Speter if ( isa( p1 , "d" ) ) { 235*18464Sralph putleaf( PCC_ICON , 0 , 0 236*18464Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_DOUBLE , PCCTM_PTR ) 237764Speter , "_fabs" ); 23814738Sthien p1 = stkrval( argv->list_node.list , NLNIL ,(long) RREQ ); 239*18464Sralph putop( PCC_CALL , PCCT_DOUBLE ); 240764Speter return nl + TDOUBLE; 241764Speter } 242764Speter if ( isa( p1 , "i" ) ) { 243*18464Sralph putleaf( PCC_ICON , 0 , 0 244*18464Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , "_abs" ); 24514738Sthien p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ ); 246*18464Sralph putop( PCC_CALL , PCCT_INT ); 247764Speter return nl + T4INT; 248764Speter } 249764Speter error("%s's argument must be an integer or real, not %s", p->symbol, nameof(p1)); 25014738Sthien return NLNIL; 251764Speter case O_SQR2: 252764Speter if ( isa( p1 , "d" ) ) { 253*18464Sralph temptype = PCCT_DOUBLE; 254764Speter rettype = nl + TDOUBLE; 25514738Sthien tempnlp = tmpalloc((long) (sizeof(double)), rettype, REGOK); 256764Speter } else if ( isa( p1 , "i" ) ) { 257*18464Sralph temptype = PCCT_INT; 258764Speter rettype = nl + T4INT; 25914738Sthien tempnlp = tmpalloc((long) (sizeof(long)), rettype, REGOK); 260764Speter } else { 261764Speter error("%s's argument must be an integer or real, not %s", p->symbol, nameof(p1)); 26214738Sthien return NLNIL; 263764Speter } 26414738Sthien putRV( (char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] , 26514738Sthien tempnlp -> extra_flags , (char) temptype ); 26614738Sthien p1 = rvalue( argv->list_node.list , NLNIL , RREQ ); 26714738Sthien sconv(p2type(p1), (int) temptype); 268*18464Sralph putop( PCC_ASSIGN , (int) temptype ); 26914738Sthien putRV((char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] , 27014738Sthien tempnlp -> extra_flags , (char) temptype ); 27114738Sthien putRV((char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] , 27214738Sthien tempnlp -> extra_flags , (char) temptype ); 273*18464Sralph putop( PCC_MUL , (int) temptype ); 274*18464Sralph putop( PCC_COMOP , (int) temptype ); 275764Speter return rettype; 276764Speter case O_ORD2: 27714738Sthien p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ ); 2789573Speter if (isa(p1, "bcis")) { 279764Speter return (nl+T4INT); 280764Speter } 2819573Speter if (classify(p1) == TPTR) { 2829573Speter if (!opt('s')) { 2839573Speter return (nl+T4INT); 2849573Speter } 2859573Speter standard(); 2869573Speter } 2879573Speter error("ord's argument must be of scalar type, not %s", 2889573Speter nameof(p1)); 28914738Sthien return (NLNIL); 290764Speter case O_SUCC2: 291764Speter case O_PRED2: 292764Speter if (isa(p1, "d")) { 293764Speter error("%s is forbidden for reals", p->symbol); 29414738Sthien return (NLNIL); 295764Speter } 296764Speter if ( isnta( p1 , "bcsi" ) ) { 297764Speter error("%s's argument must be of scalar type, not %s", p->symbol, nameof(p1)); 29814738Sthien return NLNIL; 299764Speter } 300764Speter if ( opt( 't' ) ) { 301*18464Sralph putleaf( PCC_ICON , 0 , 0 302*18464Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 303764Speter , op == O_SUCC2 ? "_SUCC" : "_PRED" ); 30414738Sthien p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ ); 3056596Smckusick tempnlp = p1 -> class == TYPE ? p1 -> type : p1; 306*18464Sralph putleaf( PCC_ICON, (int) tempnlp -> range[0], 0, PCCT_INT, (char *) 0 ); 307*18464Sralph putop( PCC_CM , PCCT_INT ); 308*18464Sralph putleaf( PCC_ICON, (int) tempnlp -> range[1], 0, PCCT_INT, (char *) 0 ); 309*18464Sralph putop( PCC_CM , PCCT_INT ); 310*18464Sralph putop( PCC_CALL , PCCT_INT ); 311*18464Sralph sconv(PCCT_INT, p2type(p1)); 312764Speter } else { 31314738Sthien p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ ); 314*18464Sralph putleaf( PCC_ICON , 1 , 0 , PCCT_INT , (char *) 0 ); 315*18464Sralph putop( op == O_SUCC2 ? PCC_PLUS : PCC_MINUS , PCCT_INT ); 316*18464Sralph sconv(PCCT_INT, p2type(p1)); 317764Speter } 318764Speter if ( isa( p1 , "bcs" ) ) { 319764Speter return p1; 320764Speter } else { 321764Speter return nl + T4INT; 322764Speter } 323764Speter case O_ODD2: 324764Speter if (isnta(p1, "i")) { 325764Speter error("odd's argument must be an integer, not %s", nameof(p1)); 32614738Sthien return (NLNIL); 327764Speter } 32814738Sthien p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ ); 32910669Speter /* 33010669Speter * THIS IS MACHINE-DEPENDENT!!! 33110669Speter */ 332*18464Sralph putleaf( PCC_ICON , 1 , 0 , PCCT_INT , (char *) 0 ); 333*18464Sralph putop( PCC_AND , PCCT_INT ); 334*18464Sralph sconv(PCCT_INT, PCCT_CHAR); 335764Speter return nl + TBOOL; 336764Speter case O_CHR2: 337764Speter if (isnta(p1, "i")) { 338764Speter error("chr's argument must be an integer, not %s", nameof(p1)); 33914738Sthien return (NLNIL); 340764Speter } 341764Speter if (opt('t')) { 342*18464Sralph putleaf( PCC_ICON , 0 , 0 343*18464Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_CHAR , PCCTM_PTR ) , "_CHR" ); 34414738Sthien p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ ); 345*18464Sralph putop( PCC_CALL , PCCT_CHAR ); 346764Speter } else { 34714738Sthien p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ ); 348*18464Sralph sconv(PCCT_INT, PCCT_CHAR); 349764Speter } 350764Speter return nl + TCHAR; 351764Speter case O_CARD: 3521554Speter if (isnta(p1, "t")) { 3531554Speter error("Argument to card must be a set, not %s", nameof(p1)); 35414738Sthien return (NLNIL); 355764Speter } 356*18464Sralph putleaf( PCC_ICON , 0 , 0 357*18464Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , "_CARD" ); 35814738Sthien p1 = stkrval( argv->list_node.list , NLNIL , (long) LREQ ); 359*18464Sralph putleaf( PCC_ICON , (int) lwidth( p1 ) , 0 , PCCT_INT , (char *) 0 ); 360*18464Sralph putop( PCC_CM , PCCT_INT ); 361*18464Sralph putop( PCC_CALL , PCCT_INT ); 36210669Speter return nl + T4INT; 363764Speter case O_EOLN: 364764Speter if (!text(p1)) { 365764Speter error("Argument to eoln must be a text file, not %s", nameof(p1)); 36614738Sthien return (NLNIL); 367764Speter } 368*18464Sralph putleaf( PCC_ICON , 0 , 0 369*18464Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , "_TEOLN" ); 37014738Sthien p1 = stklval( argv->list_node.list , NOFLAGS ); 371*18464Sralph putop( PCC_CALL , PCCT_INT ); 372*18464Sralph sconv(PCCT_INT, PCCT_CHAR); 373764Speter return nl + TBOOL; 374764Speter case O_EOF: 375764Speter if (p1->class != FILET) { 376764Speter error("Argument to eof must be file, not %s", nameof(p1)); 37714738Sthien return (NLNIL); 378764Speter } 379*18464Sralph putleaf( PCC_ICON , 0 , 0 380*18464Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , "_TEOF" ); 38114738Sthien p1 = stklval( argv->list_node.list , NOFLAGS ); 382*18464Sralph putop( PCC_CALL , PCCT_INT ); 383*18464Sralph sconv(PCCT_INT, PCCT_CHAR); 384764Speter return nl + TBOOL; 385764Speter } 386764Speter } 387764Speter #endif PC 388