1*22183Sdist /* 2*22183Sdist * Copyright (c) 1980 Regents of the University of California. 3*22183Sdist * All rights reserved. The Berkeley software License Agreement 4*22183Sdist * specifies the terms and conditions for redistribution. 5*22183Sdist */ 6764Speter 714738Sthien #ifndef lint 8*22183Sdist static char sccsid[] = "@(#)pcfunc.c 5.1 (Berkeley) 06/05/85"; 9*22183Sdist #endif not lint 10764Speter 11764Speter #include "whoami.h" 12764Speter #ifdef PC 13764Speter /* 14764Speter * and to the end of the file 15764Speter */ 16764Speter #include "0.h" 17764Speter #include "tree.h" 1810375Speter #include "objfmt.h" 19764Speter #include "opcode.h" 2010375Speter #include "pc.h" 2118464Sralph #include <pcc.h> 2211328Speter #include "tmps.h" 2314738Sthien #include "tree_ty.h" 24764Speter 25764Speter /* 26764Speter * Funccod generates code for 27764Speter * built in function calls and calls 28764Speter * call to generate calls to user 29764Speter * defined functions and procedures. 30764Speter */ 3114738Sthien struct nl * 32764Speter pcfunccod( r ) 3314738Sthien struct tnode *r; /* T_FCALL */ 34764Speter { 35764Speter struct nl *p; 36764Speter register struct nl *p1; 3714738Sthien register struct tnode *al; 38764Speter register op; 3914738Sthien int argc; 4014738Sthien struct tnode *argv; 4114738Sthien struct tnode tr, tr2; 42764Speter char *funcname; 433831Speter struct nl *tempnlp; 44764Speter long temptype; 45764Speter struct nl *rettype; 46764Speter 47764Speter /* 48764Speter * Verify that the given name 49764Speter * is defined and the name of 50764Speter * a function. 51764Speter */ 5214738Sthien p = lookup(r->pcall_node.proc_id); 5314738Sthien if (p == NLNIL) { 5414738Sthien rvlist(r->pcall_node.arg); 5514738Sthien return (NLNIL); 56764Speter } 571197Speter if (p->class != FUNC && p->class != FFUNC) { 58764Speter error("%s is not a function", p->symbol); 5914738Sthien rvlist(r->pcall_node.arg); 6014738Sthien return (NLNIL); 61764Speter } 6214738Sthien argv = r->pcall_node.arg; 63764Speter /* 64764Speter * Call handles user defined 65764Speter * procedures and functions 66764Speter */ 67764Speter if (bn != 0) 68764Speter return (call(p, argv, FUNC, bn)); 69764Speter /* 70764Speter * Count the arguments 71764Speter */ 72764Speter argc = 0; 7314738Sthien for (al = argv; al != TR_NIL; al = al->list_node.next) 74764Speter argc++; 75764Speter /* 76764Speter * Built-in functions have 77764Speter * their interpreter opcode 78764Speter * associated with them. 79764Speter */ 80764Speter op = p->value[0] &~ NSTAND; 81764Speter if (opt('s') && (p->value[0] & NSTAND)) { 82764Speter standard(); 83764Speter error("%s is a nonstandard function", p->symbol); 84764Speter } 85764Speter if ( op == O_ARGC ) { 8618464Sralph putleaf( PCC_NAME , 0 , 0 , PCCT_INT , "__argc" ); 87764Speter return nl + T4INT; 88764Speter } 89764Speter switch (op) { 90764Speter /* 91764Speter * Parameterless functions 92764Speter */ 93764Speter case O_CLCK: 94764Speter funcname = "_CLCK"; 95764Speter goto noargs; 96764Speter case O_SCLCK: 97764Speter funcname = "_SCLCK"; 98764Speter goto noargs; 99764Speter noargs: 100764Speter if (argc != 0) { 101764Speter error("%s takes no arguments", p->symbol); 102764Speter rvlist(argv); 10314738Sthien return (NLNIL); 104764Speter } 10518464Sralph putleaf( PCC_ICON , 0 , 0 10618464Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 107764Speter , funcname ); 10818464Sralph putop( PCCOM_UNARY PCC_CALL , PCCT_INT ); 109764Speter return (nl+T4INT); 110764Speter case O_WCLCK: 111764Speter if (argc != 0) { 112764Speter error("%s takes no arguments", p->symbol); 113764Speter rvlist(argv); 11414738Sthien return (NLNIL); 115764Speter } 11618464Sralph putleaf( PCC_ICON , 0 , 0 11718464Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 118764Speter , "_time" ); 11918464Sralph putleaf( PCC_ICON , 0 , 0 , PCCT_INT , (char *) 0 ); 12018464Sralph putop( PCC_CALL , PCCT_INT ); 121764Speter return (nl+T4INT); 122764Speter case O_EOF: 123764Speter case O_EOLN: 124764Speter if (argc == 0) { 12514738Sthien argv = &(tr); 12614738Sthien tr.list_node.list = &(tr2); 12714738Sthien tr2.tag = T_VAR; 12814738Sthien tr2.var_node.cptr = input->symbol; 12914738Sthien tr2.var_node.line_no = NIL; 13014738Sthien tr2.var_node.qual = TR_NIL; 131764Speter argc = 1; 132764Speter } else if (argc != 1) { 133764Speter error("%s takes either zero or one argument", p->symbol); 134764Speter rvlist(argv); 13514738Sthien return (NLNIL); 136764Speter } 137764Speter } 138764Speter /* 139764Speter * All other functions take 140764Speter * exactly one argument. 141764Speter */ 142764Speter if (argc != 1) { 143764Speter error("%s takes exactly one argument", p->symbol); 144764Speter rvlist(argv); 14514738Sthien return (NLNIL); 146764Speter } 147764Speter /* 148764Speter * find out the type of the argument 149764Speter */ 150764Speter codeoff(); 15114738Sthien p1 = stkrval( argv->list_node.list, NLNIL , (long) RREQ ); 152764Speter codeon(); 15314738Sthien if (p1 == NLNIL) 15414738Sthien return (NLNIL); 155764Speter /* 156764Speter * figure out the return type and the funtion name 157764Speter */ 158764Speter switch (op) { 15914738Sthien case 0: 16014738Sthien error("%s is an unimplemented 6000-3.4 extension", p->symbol); 16114738Sthien default: 16214738Sthien panic("func1"); 163764Speter case O_EXP: 1645715Smckusic funcname = opt('t') ? "_EXP" : "_exp"; 165764Speter goto mathfunc; 166764Speter case O_SIN: 1675715Smckusic funcname = opt('t') ? "_SIN" : "_sin"; 168764Speter goto mathfunc; 169764Speter case O_COS: 1705715Smckusic funcname = opt('t') ? "_COS" : "_cos"; 171764Speter goto mathfunc; 172764Speter case O_ATAN: 1735715Smckusic funcname = opt('t') ? "_ATAN" : "_atan"; 174764Speter goto mathfunc; 175764Speter case O_LN: 176764Speter funcname = opt('t') ? "_LN" : "_log"; 177764Speter goto mathfunc; 178764Speter case O_SQRT: 179764Speter funcname = opt('t') ? "_SQRT" : "_sqrt"; 180764Speter goto mathfunc; 181764Speter case O_RANDOM: 182764Speter funcname = "_RANDOM"; 183764Speter goto mathfunc; 184764Speter mathfunc: 185764Speter if (isnta(p1, "id")) { 186764Speter error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1)); 18714738Sthien return (NLNIL); 188764Speter } 18918464Sralph putleaf( PCC_ICON , 0 , 0 19018464Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_DOUBLE , PCCTM_PTR ) , funcname ); 19114738Sthien p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ ); 19218464Sralph sconv(p2type(p1), PCCT_DOUBLE); 19318464Sralph putop( PCC_CALL , PCCT_DOUBLE ); 194764Speter return nl + TDOUBLE; 195764Speter case O_EXPO: 196764Speter if (isnta( p1 , "id" ) ) { 197764Speter error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1)); 198764Speter return NIL; 199764Speter } 20018464Sralph putleaf( PCC_ICON , 0 , 0 20118464Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , "_EXPO" ); 20214738Sthien p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ ); 20318464Sralph sconv(p2type(p1), PCCT_DOUBLE); 20418464Sralph putop( PCC_CALL , PCCT_INT ); 205764Speter return ( nl + T4INT ); 206764Speter case O_UNDEF: 207764Speter if ( isnta( p1 , "id" ) ) { 208764Speter error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1)); 20914738Sthien return NLNIL; 210764Speter } 21114738Sthien p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ ); 21218464Sralph putleaf( PCC_ICON , 0 , 0 , PCCT_CHAR , (char *) 0 ); 21318464Sralph putop( PCC_COMOP , PCCT_CHAR ); 214764Speter return ( nl + TBOOL ); 215764Speter case O_SEED: 216764Speter if (isnta(p1, "i")) { 217764Speter error("seed's argument must be an integer, not %s", nameof(p1)); 21814738Sthien return (NLNIL); 219764Speter } 22018464Sralph putleaf( PCC_ICON , 0 , 0 22118464Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , "_SEED" ); 22214738Sthien p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ ); 22318464Sralph putop( PCC_CALL , PCCT_INT ); 224764Speter return nl + T4INT; 225764Speter case O_ROUND: 226764Speter case O_TRUNC: 227764Speter if ( isnta( p1 , "d" ) ) { 228764Speter error("%s's argument must be a real, not %s", p->symbol, nameof(p1)); 22914738Sthien return (NLNIL); 230764Speter } 23118464Sralph putleaf( PCC_ICON , 0 , 0 23218464Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 233764Speter , op == O_ROUND ? "_ROUND" : "_TRUNC" ); 23414738Sthien p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ ); 23518464Sralph putop( PCC_CALL , PCCT_INT ); 236764Speter return nl + T4INT; 237764Speter case O_ABS2: 238764Speter if ( isa( p1 , "d" ) ) { 23918464Sralph putleaf( PCC_ICON , 0 , 0 24018464Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_DOUBLE , PCCTM_PTR ) 241764Speter , "_fabs" ); 24214738Sthien p1 = stkrval( argv->list_node.list , NLNIL ,(long) RREQ ); 24318464Sralph putop( PCC_CALL , PCCT_DOUBLE ); 244764Speter return nl + TDOUBLE; 245764Speter } 246764Speter if ( isa( p1 , "i" ) ) { 24718464Sralph putleaf( PCC_ICON , 0 , 0 24818464Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , "_abs" ); 24914738Sthien p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ ); 25018464Sralph putop( PCC_CALL , PCCT_INT ); 251764Speter return nl + T4INT; 252764Speter } 253764Speter error("%s's argument must be an integer or real, not %s", p->symbol, nameof(p1)); 25414738Sthien return NLNIL; 255764Speter case O_SQR2: 256764Speter if ( isa( p1 , "d" ) ) { 25718464Sralph temptype = PCCT_DOUBLE; 258764Speter rettype = nl + TDOUBLE; 25914738Sthien tempnlp = tmpalloc((long) (sizeof(double)), rettype, REGOK); 260764Speter } else if ( isa( p1 , "i" ) ) { 26118464Sralph temptype = PCCT_INT; 262764Speter rettype = nl + T4INT; 26314738Sthien tempnlp = tmpalloc((long) (sizeof(long)), rettype, REGOK); 264764Speter } else { 265764Speter error("%s's argument must be an integer or real, not %s", p->symbol, nameof(p1)); 26614738Sthien return NLNIL; 267764Speter } 26814738Sthien putRV( (char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] , 26914738Sthien tempnlp -> extra_flags , (char) temptype ); 27014738Sthien p1 = rvalue( argv->list_node.list , NLNIL , RREQ ); 27114738Sthien sconv(p2type(p1), (int) temptype); 27218464Sralph putop( PCC_ASSIGN , (int) temptype ); 27314738Sthien putRV((char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] , 27414738Sthien tempnlp -> extra_flags , (char) temptype ); 27514738Sthien putRV((char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] , 27614738Sthien tempnlp -> extra_flags , (char) temptype ); 27718464Sralph putop( PCC_MUL , (int) temptype ); 27818464Sralph putop( PCC_COMOP , (int) temptype ); 279764Speter return rettype; 280764Speter case O_ORD2: 28114738Sthien p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ ); 2829573Speter if (isa(p1, "bcis")) { 283764Speter return (nl+T4INT); 284764Speter } 2859573Speter if (classify(p1) == TPTR) { 2869573Speter if (!opt('s')) { 2879573Speter return (nl+T4INT); 2889573Speter } 2899573Speter standard(); 2909573Speter } 2919573Speter error("ord's argument must be of scalar type, not %s", 2929573Speter nameof(p1)); 29314738Sthien return (NLNIL); 294764Speter case O_SUCC2: 295764Speter case O_PRED2: 296764Speter if (isa(p1, "d")) { 297764Speter error("%s is forbidden for reals", p->symbol); 29814738Sthien return (NLNIL); 299764Speter } 300764Speter if ( isnta( p1 , "bcsi" ) ) { 301764Speter error("%s's argument must be of scalar type, not %s", p->symbol, nameof(p1)); 30214738Sthien return NLNIL; 303764Speter } 304764Speter if ( opt( 't' ) ) { 30518464Sralph putleaf( PCC_ICON , 0 , 0 30618464Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) 307764Speter , op == O_SUCC2 ? "_SUCC" : "_PRED" ); 30814738Sthien p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ ); 3096596Smckusick tempnlp = p1 -> class == TYPE ? p1 -> type : p1; 31018464Sralph putleaf( PCC_ICON, (int) tempnlp -> range[0], 0, PCCT_INT, (char *) 0 ); 31118464Sralph putop( PCC_CM , PCCT_INT ); 31218464Sralph putleaf( PCC_ICON, (int) tempnlp -> range[1], 0, PCCT_INT, (char *) 0 ); 31318464Sralph putop( PCC_CM , PCCT_INT ); 31418464Sralph putop( PCC_CALL , PCCT_INT ); 31518464Sralph sconv(PCCT_INT, p2type(p1)); 316764Speter } else { 31714738Sthien p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ ); 31818464Sralph putleaf( PCC_ICON , 1 , 0 , PCCT_INT , (char *) 0 ); 31918464Sralph putop( op == O_SUCC2 ? PCC_PLUS : PCC_MINUS , PCCT_INT ); 32018464Sralph sconv(PCCT_INT, p2type(p1)); 321764Speter } 322764Speter if ( isa( p1 , "bcs" ) ) { 323764Speter return p1; 324764Speter } else { 325764Speter return nl + T4INT; 326764Speter } 327764Speter case O_ODD2: 328764Speter if (isnta(p1, "i")) { 329764Speter error("odd's argument must be an integer, not %s", nameof(p1)); 33014738Sthien return (NLNIL); 331764Speter } 33214738Sthien p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ ); 33310669Speter /* 33410669Speter * THIS IS MACHINE-DEPENDENT!!! 33510669Speter */ 33618464Sralph putleaf( PCC_ICON , 1 , 0 , PCCT_INT , (char *) 0 ); 33718464Sralph putop( PCC_AND , PCCT_INT ); 33818464Sralph sconv(PCCT_INT, PCCT_CHAR); 339764Speter return nl + TBOOL; 340764Speter case O_CHR2: 341764Speter if (isnta(p1, "i")) { 342764Speter error("chr's argument must be an integer, not %s", nameof(p1)); 34314738Sthien return (NLNIL); 344764Speter } 345764Speter if (opt('t')) { 34618464Sralph putleaf( PCC_ICON , 0 , 0 34718464Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_CHAR , PCCTM_PTR ) , "_CHR" ); 34814738Sthien p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ ); 34918464Sralph putop( PCC_CALL , PCCT_CHAR ); 350764Speter } else { 35114738Sthien p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ ); 35218464Sralph sconv(PCCT_INT, PCCT_CHAR); 353764Speter } 354764Speter return nl + TCHAR; 355764Speter case O_CARD: 3561554Speter if (isnta(p1, "t")) { 3571554Speter error("Argument to card must be a set, not %s", nameof(p1)); 35814738Sthien return (NLNIL); 359764Speter } 36018464Sralph putleaf( PCC_ICON , 0 , 0 36118464Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , "_CARD" ); 36214738Sthien p1 = stkrval( argv->list_node.list , NLNIL , (long) LREQ ); 36318464Sralph putleaf( PCC_ICON , (int) lwidth( p1 ) , 0 , PCCT_INT , (char *) 0 ); 36418464Sralph putop( PCC_CM , PCCT_INT ); 36518464Sralph putop( PCC_CALL , PCCT_INT ); 36610669Speter return nl + T4INT; 367764Speter case O_EOLN: 368764Speter if (!text(p1)) { 369764Speter error("Argument to eoln must be a text file, not %s", nameof(p1)); 37014738Sthien return (NLNIL); 371764Speter } 37218464Sralph putleaf( PCC_ICON , 0 , 0 37318464Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , "_TEOLN" ); 37414738Sthien p1 = stklval( argv->list_node.list , NOFLAGS ); 37518464Sralph putop( PCC_CALL , PCCT_INT ); 37618464Sralph sconv(PCCT_INT, PCCT_CHAR); 377764Speter return nl + TBOOL; 378764Speter case O_EOF: 379764Speter if (p1->class != FILET) { 380764Speter error("Argument to eof must be file, not %s", nameof(p1)); 38114738Sthien return (NLNIL); 382764Speter } 38318464Sralph putleaf( PCC_ICON , 0 , 0 38418464Sralph , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , "_TEOF" ); 38514738Sthien p1 = stklval( argv->list_node.list , NOFLAGS ); 38618464Sralph putop( PCC_CALL , PCCT_INT ); 38718464Sralph sconv(PCCT_INT, PCCT_CHAR); 388764Speter return nl + TBOOL; 389764Speter } 390764Speter } 391764Speter #endif PC 392