1753Speter /* Copyright (c) 1979 Regents of the University of California */ 2753Speter 3*2537Speter static char sccsid[] = "@(#)func.c 1.6 02/19/81"; 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; 25753Speter register int *al; 26753Speter register op; 27753Speter int argc, *argv; 28753Speter int tr[2], tr2[4]; 29753Speter 30753Speter /* 31753Speter * Verify that the given name 32753Speter * is defined and the name of 33753Speter * a function. 34753Speter */ 35753Speter p = lookup(r[2]); 36753Speter if (p == NIL) { 37753Speter rvlist(r[3]); 38753Speter return (NIL); 39753Speter } 401197Speter if (p->class != FUNC && p->class != FFUNC) { 41753Speter error("%s is not a function", p->symbol); 42753Speter rvlist(r[3]); 43753Speter return (NIL); 44753Speter } 45753Speter argv = r[3]; 46753Speter /* 47753Speter * Call handles user defined 48753Speter * procedures and functions 49753Speter */ 50753Speter if (bn != 0) 51753Speter return (call(p, argv, FUNC, bn)); 52753Speter /* 53753Speter * Count the arguments 54753Speter */ 55753Speter argc = 0; 56753Speter for (al = argv; al != NIL; al = al[2]) 57753Speter argc++; 58753Speter /* 59753Speter * Built-in functions have 60753Speter * their interpreter opcode 61753Speter * associated with them. 62753Speter */ 63753Speter op = p->value[0] &~ NSTAND; 64753Speter if (opt('s') && (p->value[0] & NSTAND)) { 65753Speter standard(); 66753Speter error("%s is a nonstandard function", p->symbol); 67753Speter } 68753Speter switch (op) { 69753Speter /* 70753Speter * Parameterless functions 71753Speter */ 72753Speter case O_CLCK: 73753Speter case O_SCLCK: 74753Speter case O_WCLCK: 75753Speter case O_ARGC: 76753Speter if (argc != 0) { 77753Speter error("%s takes no arguments", p->symbol); 78753Speter rvlist(argv); 79753Speter return (NIL); 80753Speter } 81753Speter put1(op); 82753Speter return (nl+T4INT); 83753Speter case O_EOF: 84753Speter case O_EOLN: 85753Speter if (argc == 0) { 86753Speter argv = tr; 87753Speter tr[1] = tr2; 88753Speter tr2[0] = T_VAR; 89753Speter tr2[2] = input->symbol; 90753Speter tr2[1] = tr2[3] = NIL; 91753Speter argc = 1; 92753Speter } else if (argc != 1) { 93753Speter error("%s takes either zero or one argument", p->symbol); 94753Speter rvlist(argv); 95753Speter return (NIL); 96753Speter } 97753Speter } 98753Speter /* 99753Speter * All other functions take 100753Speter * exactly one argument. 101753Speter */ 102753Speter if (argc != 1) { 103753Speter error("%s takes exactly one argument", p->symbol); 104753Speter rvlist(argv); 105753Speter return (NIL); 106753Speter } 107753Speter /* 108753Speter * Evaluate the argmument 109753Speter */ 1102070Smckusic if (op == O_EOF || op == O_EOLN) 1112070Smckusic p1 = stklval((int *) argv[1], NLNIL , LREQ ); 1122070Smckusic else 1132070Smckusic p1 = stkrval((int *) argv[1], NLNIL , RREQ ); 114753Speter if (p1 == NIL) 115753Speter return (NIL); 116753Speter switch (op) { 117753Speter case O_EXP: 118753Speter case O_SIN: 119753Speter case O_COS: 120753Speter case O_ATAN: 121753Speter case O_LN: 122753Speter case O_SQRT: 123753Speter case O_RANDOM: 124753Speter case O_EXPO: 125753Speter case O_UNDEF: 126753Speter if (isa(p1, "i")) 127*2537Speter convert( nl+T4INT , nl+TDOUBLE); 128753Speter else if (isnta(p1, "d")) { 129753Speter error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1)); 130753Speter return (NIL); 131753Speter } 132753Speter put1(op); 133753Speter if (op == O_UNDEF) 134753Speter return (nl+TBOOL); 135753Speter else if (op == O_EXPO) 136753Speter return (nl+T4INT); 137753Speter else 138753Speter return (nl+TDOUBLE); 139753Speter case O_SEED: 140753Speter if (isnta(p1, "i")) { 141753Speter error("seed's argument must be an integer, not %s", nameof(p1)); 142753Speter return (NIL); 143753Speter } 144753Speter put1(op); 145753Speter return (nl+T4INT); 146753Speter case O_ROUND: 147753Speter case O_TRUNC: 148753Speter if (isnta(p1, "d")) { 149753Speter error("%s's argument must be a real, not %s", p->symbol, nameof(p1)); 150753Speter return (NIL); 151753Speter } 152753Speter put1(op); 153753Speter return (nl+T4INT); 154753Speter case O_ABS2: 155753Speter case O_SQR2: 156753Speter if (isa(p1, "d")) { 157753Speter put1(op + O_ABS8-O_ABS2); 158753Speter return (nl+TDOUBLE); 159753Speter } 160753Speter if (isa(p1, "i")) { 161753Speter put1(op + (width(p1) >> 2)); 162753Speter return (nl+T4INT); 163753Speter } 164753Speter error("%s's argument must be an integer or real, not %s", p->symbol, nameof(p1)); 165753Speter return (NIL); 166753Speter case O_ORD2: 167753Speter if (isa(p1, "bcis") || classify(p1) == TPTR) { 168753Speter return (nl+T4INT); 169753Speter } 170753Speter error("ord's argument must be of scalar type or a pointer, not %s", nameof(p1)); 171753Speter return (NIL); 172753Speter case O_SUCC2: 173753Speter case O_PRED2: 1742104Smckusic if (isa(p1, "d")) { 1752104Smckusic error("%s is forbidden for reals", p->symbol); 1762104Smckusic return (NIL); 177753Speter } 1782104Smckusic if ( isnta( p1 , "bcsi" ) ) { 1792104Smckusic error("%s's argument must be of scalar type, not %s", p->symbol, nameof(p1)); 1802104Smckusic return NIL; 1812104Smckusic } 182753Speter if (isa(p1, "i")) { 183753Speter if (width(p1) <= 2) 1842104Smckusic op += O_PRED24 - O_PRED2; 185753Speter else 186753Speter op++; 1872104Smckusic put(3, op, p1->range[0], p1->range[1]); 1882104Smckusic return nl + T4INT; 1892104Smckusic } else { 1902104Smckusic put(3, op, p1->range[0], p1->range[1]); 1912104Smckusic return p1; 192753Speter } 193753Speter case O_ODD2: 194753Speter if (isnta(p1, "i")) { 195753Speter error("odd's argument must be an integer, not %s", nameof(p1)); 196753Speter return (NIL); 197753Speter } 198753Speter put1(op + (width(p1) >> 2)); 199753Speter return (nl+TBOOL); 200753Speter case O_CHR2: 201753Speter if (isnta(p1, "i")) { 202753Speter error("chr's argument must be an integer, not %s", nameof(p1)); 203753Speter return (NIL); 204753Speter } 205753Speter put1(op + (width(p1) >> 2)); 206753Speter return (nl+TCHAR); 207753Speter case O_CARD: 2081553Speter if (isnta(p1, "t")) { 2091553Speter error("Argument to card must be a set, not %s", nameof(p1)); 2101553Speter return (NIL); 211753Speter } 2121553Speter put2(O_CARD, width(p1)); 213753Speter return (nl+T2INT); 214753Speter case O_EOLN: 215753Speter if (!text(p1)) { 216753Speter error("Argument to eoln must be a text file, not %s", nameof(p1)); 217753Speter return (NIL); 218753Speter } 219753Speter put1(op); 220753Speter return (nl+TBOOL); 221753Speter case O_EOF: 222753Speter if (p1->class != FILET) { 223753Speter error("Argument to eof must be file, not %s", nameof(p1)); 224753Speter return (NIL); 225753Speter } 226753Speter put1(op); 227753Speter return (nl+TBOOL); 228753Speter case 0: 229753Speter error("%s is an unimplemented 6000-3.4 extension", p->symbol); 230753Speter default: 231753Speter panic("func1"); 232753Speter } 233753Speter } 234753Speter #endif OBJ 235