1753Speter /* Copyright (c) 1979 Regents of the University of California */ 2753Speter 3*9573Speter static char sccsid[] = "@(#)func.c 1.9 12/06/82"; 4753Speter 5753Speter #include "whoami.h" 6753Speter #ifdef OBJ 7753Speter /* 8753Speter * the rest of the file 9753Speter */ 10753Speter #include "0.h" 11753Speter #include "tree.h" 12753Speter #include "opcode.h" 13753Speter 14753Speter /* 15753Speter * Funccod generates code for 16753Speter * built in function calls and calls 17753Speter * call to generate calls to user 18753Speter * defined functions and procedures. 19753Speter */ 20753Speter funccod(r) 21753Speter int *r; 22753Speter { 23753Speter struct nl *p; 24753Speter register struct nl *p1; 256595Smckusick struct nl *tempnlp; 26753Speter register int *al; 27753Speter register op; 28753Speter int argc, *argv; 29753Speter int tr[2], tr2[4]; 30753Speter 31753Speter /* 32753Speter * Verify that the given name 33753Speter * is defined and the name of 34753Speter * a function. 35753Speter */ 36753Speter p = lookup(r[2]); 37753Speter if (p == NIL) { 38753Speter rvlist(r[3]); 39753Speter return (NIL); 40753Speter } 411197Speter if (p->class != FUNC && p->class != FFUNC) { 42753Speter error("%s is not a function", p->symbol); 43753Speter rvlist(r[3]); 44753Speter return (NIL); 45753Speter } 46753Speter argv = r[3]; 47753Speter /* 48753Speter * Call handles user defined 49753Speter * procedures and functions 50753Speter */ 51753Speter if (bn != 0) 52753Speter return (call(p, argv, FUNC, bn)); 53753Speter /* 54753Speter * Count the arguments 55753Speter */ 56753Speter argc = 0; 57753Speter for (al = argv; al != NIL; al = al[2]) 58753Speter argc++; 59753Speter /* 60753Speter * Built-in functions have 61753Speter * their interpreter opcode 62753Speter * associated with them. 63753Speter */ 64753Speter op = p->value[0] &~ NSTAND; 65753Speter if (opt('s') && (p->value[0] & NSTAND)) { 66753Speter standard(); 67753Speter error("%s is a nonstandard function", p->symbol); 68753Speter } 69753Speter switch (op) { 70753Speter /* 71753Speter * Parameterless functions 72753Speter */ 73753Speter case O_CLCK: 74753Speter case O_SCLCK: 75753Speter case O_WCLCK: 76753Speter case O_ARGC: 77753Speter if (argc != 0) { 78753Speter error("%s takes no arguments", p->symbol); 79753Speter rvlist(argv); 80753Speter return (NIL); 81753Speter } 823074Smckusic put(1, op); 83753Speter return (nl+T4INT); 84753Speter case O_EOF: 85753Speter case O_EOLN: 86753Speter if (argc == 0) { 87753Speter argv = tr; 88753Speter tr[1] = tr2; 89753Speter tr2[0] = T_VAR; 90753Speter tr2[2] = input->symbol; 91753Speter tr2[1] = tr2[3] = NIL; 92753Speter argc = 1; 93753Speter } else if (argc != 1) { 94753Speter error("%s takes either zero or one argument", p->symbol); 95753Speter rvlist(argv); 96753Speter return (NIL); 97753Speter } 98753Speter } 99753Speter /* 100753Speter * All other functions take 101753Speter * exactly one argument. 102753Speter */ 103753Speter if (argc != 1) { 104753Speter error("%s takes exactly one argument", p->symbol); 105753Speter rvlist(argv); 106753Speter return (NIL); 107753Speter } 108753Speter /* 109753Speter * Evaluate the argmument 110753Speter */ 1112070Smckusic if (op == O_EOF || op == O_EOLN) 1122070Smckusic p1 = stklval((int *) argv[1], NLNIL , LREQ ); 1132070Smckusic else 1142070Smckusic p1 = stkrval((int *) argv[1], NLNIL , RREQ ); 115753Speter if (p1 == NIL) 116753Speter return (NIL); 117753Speter switch (op) { 118753Speter case O_EXP: 119753Speter case O_SIN: 120753Speter case O_COS: 121753Speter case O_ATAN: 122753Speter case O_LN: 123753Speter case O_SQRT: 124753Speter case O_RANDOM: 125753Speter case O_EXPO: 126753Speter case O_UNDEF: 127753Speter if (isa(p1, "i")) 1282537Speter convert( nl+T4INT , nl+TDOUBLE); 129753Speter else if (isnta(p1, "d")) { 130753Speter error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1)); 131753Speter return (NIL); 132753Speter } 1333074Smckusic put(1, op); 134753Speter if (op == O_UNDEF) 135753Speter return (nl+TBOOL); 136753Speter else if (op == O_EXPO) 137753Speter return (nl+T4INT); 138753Speter else 139753Speter return (nl+TDOUBLE); 140753Speter case O_SEED: 141753Speter if (isnta(p1, "i")) { 142753Speter error("seed's argument must be an integer, not %s", nameof(p1)); 143753Speter return (NIL); 144753Speter } 1453074Smckusic put(1, op); 146753Speter return (nl+T4INT); 147753Speter case O_ROUND: 148753Speter case O_TRUNC: 149753Speter if (isnta(p1, "d")) { 150753Speter error("%s's argument must be a real, not %s", p->symbol, nameof(p1)); 151753Speter return (NIL); 152753Speter } 1533074Smckusic put(1, op); 154753Speter return (nl+T4INT); 155753Speter case O_ABS2: 156753Speter case O_SQR2: 157753Speter if (isa(p1, "d")) { 1583074Smckusic put(1, op + O_ABS8-O_ABS2); 159753Speter return (nl+TDOUBLE); 160753Speter } 161753Speter if (isa(p1, "i")) { 1623074Smckusic put(1, op + (width(p1) >> 2)); 163753Speter return (nl+T4INT); 164753Speter } 165753Speter error("%s's argument must be an integer or real, not %s", p->symbol, nameof(p1)); 166753Speter return (NIL); 167753Speter case O_ORD2: 168*9573Speter if (isa(p1, "bcis")) { 169753Speter return (nl+T4INT); 170753Speter } 171*9573Speter if (classify(p1) == TPTR) { 172*9573Speter if (!opt('s')) { 173*9573Speter return (nl+T4INT); 174*9573Speter } 175*9573Speter standard(); 176*9573Speter } 177*9573Speter error("ord's argument must be of scalar type, not %s", 178*9573Speter nameof(p1)); 179753Speter return (NIL); 180753Speter case O_SUCC2: 181753Speter case O_PRED2: 1822104Smckusic if (isa(p1, "d")) { 1832104Smckusic error("%s is forbidden for reals", p->symbol); 1842104Smckusic return (NIL); 185753Speter } 1862104Smckusic if ( isnta( p1 , "bcsi" ) ) { 1872104Smckusic error("%s's argument must be of scalar type, not %s", p->symbol, nameof(p1)); 1882104Smckusic return NIL; 1892104Smckusic } 1906595Smckusick tempnlp = p1 -> class == TYPE ? p1 -> type : p1; 191753Speter if (isa(p1, "i")) { 1923074Smckusic if (width(p1) <= 2) { 1932104Smckusic op += O_PRED24 - O_PRED2; 1946595Smckusick put(3, op, (int)tempnlp->range[0], 1956595Smckusick (int)tempnlp->range[1]); 1963074Smckusic } else { 197753Speter op++; 1986595Smckusick put(3, op, tempnlp->range[0], 1996595Smckusick tempnlp->range[1]); 2003074Smckusic } 2012104Smckusic return nl + T4INT; 2022104Smckusic } else { 2036595Smckusick put(3, op, (int)tempnlp->range[0], 2046595Smckusick (int)tempnlp->range[1]); 2052104Smckusic return p1; 206753Speter } 207753Speter case O_ODD2: 208753Speter if (isnta(p1, "i")) { 209753Speter error("odd's argument must be an integer, not %s", nameof(p1)); 210753Speter return (NIL); 211753Speter } 2123074Smckusic put(1, op + (width(p1) >> 2)); 213753Speter return (nl+TBOOL); 214753Speter case O_CHR2: 215753Speter if (isnta(p1, "i")) { 216753Speter error("chr's argument must be an integer, not %s", nameof(p1)); 217753Speter return (NIL); 218753Speter } 2193074Smckusic put(1, op + (width(p1) >> 2)); 220753Speter return (nl+TCHAR); 221753Speter case O_CARD: 2221553Speter if (isnta(p1, "t")) { 2231553Speter error("Argument to card must be a set, not %s", nameof(p1)); 2241553Speter return (NIL); 225753Speter } 2263074Smckusic put(2, O_CARD, width(p1)); 227753Speter return (nl+T2INT); 228753Speter case O_EOLN: 229753Speter if (!text(p1)) { 230753Speter error("Argument to eoln must be a text file, not %s", nameof(p1)); 231753Speter return (NIL); 232753Speter } 2333074Smckusic put(1, op); 234753Speter return (nl+TBOOL); 235753Speter case O_EOF: 236753Speter if (p1->class != FILET) { 237753Speter error("Argument to eof must be file, not %s", nameof(p1)); 238753Speter return (NIL); 239753Speter } 2403074Smckusic put(1, op); 241753Speter return (nl+TBOOL); 242753Speter case 0: 243753Speter error("%s is an unimplemented 6000-3.4 extension", p->symbol); 244753Speter default: 245753Speter panic("func1"); 246753Speter } 247753Speter } 248753Speter #endif OBJ 249