1753Speter /* Copyright (c) 1979 Regents of the University of California */ 2753Speter 3*2070Smckusic static char sccsid[] = "@(#)func.c 1.4 01/06/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 */ 110*2070Smckusic if (op == O_EOF || op == O_EOLN) 111*2070Smckusic p1 = stklval((int *) argv[1], NLNIL , LREQ ); 112*2070Smckusic else 113*2070Smckusic 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")) 127753Speter convert(p1, 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: 174753Speter if (isa(p1, "bcs")) { 175753Speter put1(op); 176753Speter return (p1); 177753Speter } 178753Speter if (isa(p1, "i")) { 179753Speter if (width(p1) <= 2) 180753Speter op += O_PRED24-O_PRED2; 181753Speter else 182753Speter op++; 183753Speter put1(op); 184753Speter return (nl+T4INT); 185753Speter } 186753Speter if (isa(p1, "id")) { 187753Speter error("%s is forbidden for reals", p->symbol); 188753Speter return (NIL); 189753Speter } 190753Speter error("%s's argument must be of scalar type, not %s", p->symbol, nameof(p1)); 191753Speter return (NIL); 192753Speter case O_ODD2: 193753Speter if (isnta(p1, "i")) { 194753Speter error("odd's argument must be an integer, not %s", nameof(p1)); 195753Speter return (NIL); 196753Speter } 197753Speter put1(op + (width(p1) >> 2)); 198753Speter return (nl+TBOOL); 199753Speter case O_CHR2: 200753Speter if (isnta(p1, "i")) { 201753Speter error("chr's argument must be an integer, not %s", nameof(p1)); 202753Speter return (NIL); 203753Speter } 204753Speter put1(op + (width(p1) >> 2)); 205753Speter return (nl+TCHAR); 206753Speter case O_CARD: 2071553Speter if (isnta(p1, "t")) { 2081553Speter error("Argument to card must be a set, not %s", nameof(p1)); 2091553Speter return (NIL); 210753Speter } 2111553Speter put2(O_CARD, width(p1)); 212753Speter return (nl+T2INT); 213753Speter case O_EOLN: 214753Speter if (!text(p1)) { 215753Speter error("Argument to eoln must be a text file, not %s", nameof(p1)); 216753Speter return (NIL); 217753Speter } 218753Speter put1(op); 219753Speter return (nl+TBOOL); 220753Speter case O_EOF: 221753Speter if (p1->class != FILET) { 222753Speter error("Argument to eof must be file, not %s", nameof(p1)); 223753Speter return (NIL); 224753Speter } 225753Speter put1(op); 226753Speter return (nl+TBOOL); 227753Speter case 0: 228753Speter error("%s is an unimplemented 6000-3.4 extension", p->symbol); 229753Speter default: 230753Speter panic("func1"); 231753Speter } 232753Speter } 233753Speter #endif OBJ 234