1753Speter /* Copyright (c) 1979 Regents of the University of California */ 2753Speter 3*3074Smckusic static char sccsid[] = "@(#)func.c 1.7 03/08/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 } 81*3074Smckusic put(1, 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")) 1272537Speter 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 } 132*3074Smckusic put(1, 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 } 144*3074Smckusic put(1, 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 } 152*3074Smckusic put(1, op); 153753Speter return (nl+T4INT); 154753Speter case O_ABS2: 155753Speter case O_SQR2: 156753Speter if (isa(p1, "d")) { 157*3074Smckusic put(1, op + O_ABS8-O_ABS2); 158753Speter return (nl+TDOUBLE); 159753Speter } 160753Speter if (isa(p1, "i")) { 161*3074Smckusic put(1, 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")) { 183*3074Smckusic if (width(p1) <= 2) { 1842104Smckusic op += O_PRED24 - O_PRED2; 185*3074Smckusic put(3, op, (int)p1->range[0], 186*3074Smckusic (int)p1->range[1]); 187*3074Smckusic } else { 188753Speter op++; 189*3074Smckusic put(3, op, p1->range[0], p1->range[1]); 190*3074Smckusic } 1912104Smckusic return nl + T4INT; 1922104Smckusic } else { 193*3074Smckusic put(3, op, (int)p1->range[0], (int)p1->range[1]); 1942104Smckusic return p1; 195753Speter } 196753Speter case O_ODD2: 197753Speter if (isnta(p1, "i")) { 198753Speter error("odd's argument must be an integer, not %s", nameof(p1)); 199753Speter return (NIL); 200753Speter } 201*3074Smckusic put(1, op + (width(p1) >> 2)); 202753Speter return (nl+TBOOL); 203753Speter case O_CHR2: 204753Speter if (isnta(p1, "i")) { 205753Speter error("chr's argument must be an integer, not %s", nameof(p1)); 206753Speter return (NIL); 207753Speter } 208*3074Smckusic put(1, op + (width(p1) >> 2)); 209753Speter return (nl+TCHAR); 210753Speter case O_CARD: 2111553Speter if (isnta(p1, "t")) { 2121553Speter error("Argument to card must be a set, not %s", nameof(p1)); 2131553Speter return (NIL); 214753Speter } 215*3074Smckusic put(2, O_CARD, width(p1)); 216753Speter return (nl+T2INT); 217753Speter case O_EOLN: 218753Speter if (!text(p1)) { 219753Speter error("Argument to eoln must be a text file, not %s", nameof(p1)); 220753Speter return (NIL); 221753Speter } 222*3074Smckusic put(1, op); 223753Speter return (nl+TBOOL); 224753Speter case O_EOF: 225753Speter if (p1->class != FILET) { 226753Speter error("Argument to eof must be file, not %s", nameof(p1)); 227753Speter return (NIL); 228753Speter } 229*3074Smckusic put(1, op); 230753Speter return (nl+TBOOL); 231753Speter case 0: 232753Speter error("%s is an unimplemented 6000-3.4 extension", p->symbol); 233753Speter default: 234753Speter panic("func1"); 235753Speter } 236753Speter } 237753Speter #endif OBJ 238