1753Speter /* Copyright (c) 1979 Regents of the University of California */ 2753Speter 3*1553Speter static char sccsid[] = "@(#)func.c 1.3 10/19/80"; 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 */ 110753Speter p1 = stkrval((int *) argv[1], NLNIL , RREQ ); 111753Speter if (p1 == NIL) 112753Speter return (NIL); 113753Speter switch (op) { 114753Speter case O_EXP: 115753Speter case O_SIN: 116753Speter case O_COS: 117753Speter case O_ATAN: 118753Speter case O_LN: 119753Speter case O_SQRT: 120753Speter case O_RANDOM: 121753Speter case O_EXPO: 122753Speter case O_UNDEF: 123753Speter if (isa(p1, "i")) 124753Speter convert(p1, nl+TDOUBLE); 125753Speter else if (isnta(p1, "d")) { 126753Speter error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1)); 127753Speter return (NIL); 128753Speter } 129753Speter put1(op); 130753Speter if (op == O_UNDEF) 131753Speter return (nl+TBOOL); 132753Speter else if (op == O_EXPO) 133753Speter return (nl+T4INT); 134753Speter else 135753Speter return (nl+TDOUBLE); 136753Speter case O_SEED: 137753Speter if (isnta(p1, "i")) { 138753Speter error("seed's argument must be an integer, not %s", nameof(p1)); 139753Speter return (NIL); 140753Speter } 141753Speter put1(op); 142753Speter return (nl+T4INT); 143753Speter case O_ROUND: 144753Speter case O_TRUNC: 145753Speter if (isnta(p1, "d")) { 146753Speter error("%s's argument must be a real, not %s", p->symbol, nameof(p1)); 147753Speter return (NIL); 148753Speter } 149753Speter put1(op); 150753Speter return (nl+T4INT); 151753Speter case O_ABS2: 152753Speter case O_SQR2: 153753Speter if (isa(p1, "d")) { 154753Speter put1(op + O_ABS8-O_ABS2); 155753Speter return (nl+TDOUBLE); 156753Speter } 157753Speter if (isa(p1, "i")) { 158753Speter put1(op + (width(p1) >> 2)); 159753Speter return (nl+T4INT); 160753Speter } 161753Speter error("%s's argument must be an integer or real, not %s", p->symbol, nameof(p1)); 162753Speter return (NIL); 163753Speter case O_ORD2: 164753Speter if (isa(p1, "bcis") || classify(p1) == TPTR) { 165753Speter return (nl+T4INT); 166753Speter } 167753Speter error("ord's argument must be of scalar type or a pointer, not %s", nameof(p1)); 168753Speter return (NIL); 169753Speter case O_SUCC2: 170753Speter case O_PRED2: 171753Speter if (isa(p1, "bcs")) { 172753Speter put1(op); 173753Speter return (p1); 174753Speter } 175753Speter if (isa(p1, "i")) { 176753Speter if (width(p1) <= 2) 177753Speter op += O_PRED24-O_PRED2; 178753Speter else 179753Speter op++; 180753Speter put1(op); 181753Speter return (nl+T4INT); 182753Speter } 183753Speter if (isa(p1, "id")) { 184753Speter error("%s is forbidden for reals", p->symbol); 185753Speter return (NIL); 186753Speter } 187753Speter error("%s's argument must be of scalar type, not %s", p->symbol, nameof(p1)); 188753Speter return (NIL); 189753Speter case O_ODD2: 190753Speter if (isnta(p1, "i")) { 191753Speter error("odd's argument must be an integer, not %s", nameof(p1)); 192753Speter return (NIL); 193753Speter } 194753Speter put1(op + (width(p1) >> 2)); 195753Speter return (nl+TBOOL); 196753Speter case O_CHR2: 197753Speter if (isnta(p1, "i")) { 198753Speter error("chr's argument must be an integer, not %s", nameof(p1)); 199753Speter return (NIL); 200753Speter } 201753Speter put1(op + (width(p1) >> 2)); 202753Speter return (nl+TCHAR); 203753Speter case O_CARD: 204*1553Speter if (isnta(p1, "t")) { 205*1553Speter error("Argument to card must be a set, not %s", nameof(p1)); 206*1553Speter return (NIL); 207753Speter } 208*1553Speter put2(O_CARD, width(p1)); 209753Speter return (nl+T2INT); 210753Speter case O_EOLN: 211753Speter if (!text(p1)) { 212753Speter error("Argument to eoln must be a text file, not %s", nameof(p1)); 213753Speter return (NIL); 214753Speter } 215753Speter put1(op); 216753Speter return (nl+TBOOL); 217753Speter case O_EOF: 218753Speter if (p1->class != FILET) { 219753Speter error("Argument to eof must be file, not %s", nameof(p1)); 220753Speter return (NIL); 221753Speter } 222753Speter put1(op); 223753Speter return (nl+TBOOL); 224753Speter case 0: 225753Speter error("%s is an unimplemented 6000-3.4 extension", p->symbol); 226753Speter default: 227753Speter panic("func1"); 228753Speter } 229753Speter } 230753Speter #endif OBJ 231