1753Speter /* Copyright (c) 1979 Regents of the University of California */ 2753Speter 3*14733Sthien #ifndef lint 4*14733Sthien static char sccsid[] = "@(#)func.c 1.10 08/19/83"; 5*14733Sthien #endif 6753Speter 7753Speter #include "whoami.h" 8753Speter #ifdef OBJ 9753Speter /* 10753Speter * the rest of the file 11753Speter */ 12753Speter #include "0.h" 13753Speter #include "tree.h" 14753Speter #include "opcode.h" 15*14733Sthien #include "tree_ty.h" 16753Speter 17753Speter /* 18753Speter * Funccod generates code for 19753Speter * built in function calls and calls 20753Speter * call to generate calls to user 21753Speter * defined functions and procedures. 22753Speter */ 23*14733Sthien struct nl 24*14733Sthien *funccod(r) 25*14733Sthien struct tnode *r; 26753Speter { 27753Speter struct nl *p; 28753Speter register struct nl *p1; 296595Smckusick struct nl *tempnlp; 30*14733Sthien register struct tnode *al; 31753Speter register op; 32*14733Sthien int argc; 33*14733Sthien struct tnode *argv, tr, tr2; 34753Speter 35753Speter /* 36753Speter * Verify that the given name 37753Speter * is defined and the name of 38753Speter * a function. 39753Speter */ 40*14733Sthien p = lookup(r->pcall_node.proc_id); 41*14733Sthien if (p == NLNIL) { 42*14733Sthien rvlist(r->pcall_node.arg); 43*14733Sthien return (NLNIL); 44753Speter } 451197Speter if (p->class != FUNC && p->class != FFUNC) { 46753Speter error("%s is not a function", p->symbol); 47*14733Sthien rvlist(r->pcall_node.arg); 48*14733Sthien return (NLNIL); 49753Speter } 50*14733Sthien argv = r->pcall_node.arg; 51753Speter /* 52753Speter * Call handles user defined 53753Speter * procedures and functions 54753Speter */ 55753Speter if (bn != 0) 56753Speter return (call(p, argv, FUNC, bn)); 57753Speter /* 58753Speter * Count the arguments 59753Speter */ 60753Speter argc = 0; 61*14733Sthien for (al = argv; al != TR_NIL; al = al->list_node.next) 62753Speter argc++; 63753Speter /* 64753Speter * Built-in functions have 65753Speter * their interpreter opcode 66753Speter * associated with them. 67753Speter */ 68753Speter op = p->value[0] &~ NSTAND; 69753Speter if (opt('s') && (p->value[0] & NSTAND)) { 70753Speter standard(); 71753Speter error("%s is a nonstandard function", p->symbol); 72753Speter } 73753Speter switch (op) { 74753Speter /* 75753Speter * Parameterless functions 76753Speter */ 77753Speter case O_CLCK: 78753Speter case O_SCLCK: 79753Speter case O_WCLCK: 80753Speter case O_ARGC: 81753Speter if (argc != 0) { 82753Speter error("%s takes no arguments", p->symbol); 83753Speter rvlist(argv); 84*14733Sthien return (NLNIL); 85753Speter } 86*14733Sthien (void) put(1, op); 87753Speter return (nl+T4INT); 88753Speter case O_EOF: 89753Speter case O_EOLN: 90753Speter if (argc == 0) { 91*14733Sthien argv = (&tr); 92*14733Sthien tr.list_node.list = (&tr2); 93*14733Sthien tr2.tag = T_VAR; 94*14733Sthien tr2.var_node.cptr = input->symbol; 95*14733Sthien tr2.var_node.line_no = NIL; 96*14733Sthien tr2.var_node.qual = TR_NIL; 97753Speter argc = 1; 98753Speter } else if (argc != 1) { 99753Speter error("%s takes either zero or one argument", p->symbol); 100753Speter rvlist(argv); 101*14733Sthien return (NLNIL); 102753Speter } 103753Speter } 104753Speter /* 105753Speter * All other functions take 106753Speter * exactly one argument. 107753Speter */ 108753Speter if (argc != 1) { 109753Speter error("%s takes exactly one argument", p->symbol); 110753Speter rvlist(argv); 111*14733Sthien return (NLNIL); 112753Speter } 113753Speter /* 114753Speter * Evaluate the argmument 115753Speter */ 1162070Smckusic if (op == O_EOF || op == O_EOLN) 117*14733Sthien p1 = stklval(argv->list_node.list, NIL ); 1182070Smckusic else 119*14733Sthien p1 = stkrval(argv->list_node.list, NLNIL , (long) RREQ ); 120*14733Sthien if (p1 == NLNIL) 121*14733Sthien return (NLNIL); 122753Speter switch (op) { 123*14733Sthien case 0: 124*14733Sthien error("%s is an unimplemented 6000-3.4 extension", p->symbol); 125*14733Sthien default: 126*14733Sthien panic("func1"); 127753Speter case O_EXP: 128753Speter case O_SIN: 129753Speter case O_COS: 130753Speter case O_ATAN: 131753Speter case O_LN: 132753Speter case O_SQRT: 133753Speter case O_RANDOM: 134753Speter case O_EXPO: 135753Speter case O_UNDEF: 136753Speter if (isa(p1, "i")) 1372537Speter convert( nl+T4INT , nl+TDOUBLE); 138753Speter else if (isnta(p1, "d")) { 139753Speter error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1)); 140*14733Sthien return (NLNIL); 141753Speter } 142*14733Sthien (void) put(1, op); 143753Speter if (op == O_UNDEF) 144753Speter return (nl+TBOOL); 145753Speter else if (op == O_EXPO) 146753Speter return (nl+T4INT); 147753Speter else 148753Speter return (nl+TDOUBLE); 149753Speter case O_SEED: 150753Speter if (isnta(p1, "i")) { 151753Speter error("seed's argument must be an integer, not %s", nameof(p1)); 152*14733Sthien return (NLNIL); 153753Speter } 154*14733Sthien (void) put(1, op); 155753Speter return (nl+T4INT); 156753Speter case O_ROUND: 157753Speter case O_TRUNC: 158753Speter if (isnta(p1, "d")) { 159753Speter error("%s's argument must be a real, not %s", p->symbol, nameof(p1)); 160*14733Sthien return (NLNIL); 161753Speter } 162*14733Sthien (void) put(1, op); 163753Speter return (nl+T4INT); 164753Speter case O_ABS2: 165753Speter case O_SQR2: 166753Speter if (isa(p1, "d")) { 167*14733Sthien (void) put(1, op + O_ABS8-O_ABS2); 168753Speter return (nl+TDOUBLE); 169753Speter } 170753Speter if (isa(p1, "i")) { 171*14733Sthien (void) put(1, op + (width(p1) >> 2)); 172753Speter return (nl+T4INT); 173753Speter } 174753Speter error("%s's argument must be an integer or real, not %s", p->symbol, nameof(p1)); 175*14733Sthien return (NLNIL); 176753Speter case O_ORD2: 1779573Speter if (isa(p1, "bcis")) { 178753Speter return (nl+T4INT); 179753Speter } 1809573Speter if (classify(p1) == TPTR) { 1819573Speter if (!opt('s')) { 1829573Speter return (nl+T4INT); 1839573Speter } 1849573Speter standard(); 1859573Speter } 1869573Speter error("ord's argument must be of scalar type, not %s", 1879573Speter nameof(p1)); 188*14733Sthien return (NLNIL); 189753Speter case O_SUCC2: 190753Speter case O_PRED2: 1912104Smckusic if (isa(p1, "d")) { 1922104Smckusic error("%s is forbidden for reals", p->symbol); 193*14733Sthien return (NLNIL); 194753Speter } 1952104Smckusic if ( isnta( p1 , "bcsi" ) ) { 1962104Smckusic error("%s's argument must be of scalar type, not %s", p->symbol, nameof(p1)); 1972104Smckusic return NIL; 1982104Smckusic } 1996595Smckusick tempnlp = p1 -> class == TYPE ? p1 -> type : p1; 200753Speter if (isa(p1, "i")) { 2013074Smckusic if (width(p1) <= 2) { 2022104Smckusic op += O_PRED24 - O_PRED2; 203*14733Sthien (void) put(3, op, (int)tempnlp->range[0], 2046595Smckusick (int)tempnlp->range[1]); 2053074Smckusic } else { 206753Speter op++; 207*14733Sthien (void) put(3, op, tempnlp->range[0], 2086595Smckusick tempnlp->range[1]); 2093074Smckusic } 2102104Smckusic return nl + T4INT; 2112104Smckusic } else { 212*14733Sthien (void) put(3, op, (int)tempnlp->range[0], 2136595Smckusick (int)tempnlp->range[1]); 2142104Smckusic return p1; 215753Speter } 216753Speter case O_ODD2: 217753Speter if (isnta(p1, "i")) { 218753Speter error("odd's argument must be an integer, not %s", nameof(p1)); 219*14733Sthien return (NLNIL); 220753Speter } 221*14733Sthien (void) put(1, op + (width(p1) >> 2)); 222753Speter return (nl+TBOOL); 223753Speter case O_CHR2: 224753Speter if (isnta(p1, "i")) { 225753Speter error("chr's argument must be an integer, not %s", nameof(p1)); 226*14733Sthien return (NLNIL); 227753Speter } 228*14733Sthien (void) put(1, op + (width(p1) >> 2)); 229753Speter return (nl+TCHAR); 230753Speter case O_CARD: 2311553Speter if (isnta(p1, "t")) { 2321553Speter error("Argument to card must be a set, not %s", nameof(p1)); 233*14733Sthien return (NLNIL); 234753Speter } 235*14733Sthien (void) put(2, O_CARD, width(p1)); 236753Speter return (nl+T2INT); 237753Speter case O_EOLN: 238753Speter if (!text(p1)) { 239753Speter error("Argument to eoln must be a text file, not %s", nameof(p1)); 240*14733Sthien return (NLNIL); 241753Speter } 242*14733Sthien (void) put(1, op); 243753Speter return (nl+TBOOL); 244753Speter case O_EOF: 245753Speter if (p1->class != FILET) { 246753Speter error("Argument to eof must be file, not %s", nameof(p1)); 247*14733Sthien return (NLNIL); 248753Speter } 249*14733Sthien (void) put(1, op); 250753Speter return (nl+TBOOL); 251753Speter } 252753Speter } 253753Speter #endif OBJ 254