1753Speter /* Copyright (c) 1979 Regents of the University of California */ 2753Speter 3*1197Speter static char sccsid[] = "@(#)func.c 1.2 10/03/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 bool cardempty = FALSE; 15753Speter 16753Speter /* 17753Speter * Funccod generates code for 18753Speter * built in function calls and calls 19753Speter * call to generate calls to user 20753Speter * defined functions and procedures. 21753Speter */ 22753Speter funccod(r) 23753Speter int *r; 24753Speter { 25753Speter struct nl *p; 26753Speter register struct nl *p1; 27753Speter register int *al; 28753Speter register op; 29753Speter int argc, *argv; 30753Speter int tr[2], tr2[4]; 31753Speter 32753Speter /* 33753Speter * Verify that the given name 34753Speter * is defined and the name of 35753Speter * a function. 36753Speter */ 37753Speter p = lookup(r[2]); 38753Speter if (p == NIL) { 39753Speter rvlist(r[3]); 40753Speter return (NIL); 41753Speter } 42*1197Speter if (p->class != FUNC && p->class != FFUNC) { 43753Speter error("%s is not a function", p->symbol); 44753Speter rvlist(r[3]); 45753Speter return (NIL); 46753Speter } 47753Speter argv = r[3]; 48753Speter /* 49753Speter * Call handles user defined 50753Speter * procedures and functions 51753Speter */ 52753Speter if (bn != 0) 53753Speter return (call(p, argv, FUNC, bn)); 54753Speter /* 55753Speter * Count the arguments 56753Speter */ 57753Speter argc = 0; 58753Speter for (al = argv; al != NIL; al = al[2]) 59753Speter argc++; 60753Speter /* 61753Speter * Built-in functions have 62753Speter * their interpreter opcode 63753Speter * associated with them. 64753Speter */ 65753Speter op = p->value[0] &~ NSTAND; 66753Speter if (opt('s') && (p->value[0] & NSTAND)) { 67753Speter standard(); 68753Speter error("%s is a nonstandard function", p->symbol); 69753Speter } 70753Speter switch (op) { 71753Speter /* 72753Speter * Parameterless functions 73753Speter */ 74753Speter case O_CLCK: 75753Speter case O_SCLCK: 76753Speter case O_WCLCK: 77753Speter case O_ARGC: 78753Speter if (argc != 0) { 79753Speter error("%s takes no arguments", p->symbol); 80753Speter rvlist(argv); 81753Speter return (NIL); 82753Speter } 83753Speter put1(op); 84753Speter return (nl+T4INT); 85753Speter case O_EOF: 86753Speter case O_EOLN: 87753Speter if (argc == 0) { 88753Speter argv = tr; 89753Speter tr[1] = tr2; 90753Speter tr2[0] = T_VAR; 91753Speter tr2[2] = input->symbol; 92753Speter tr2[1] = tr2[3] = NIL; 93753Speter argc = 1; 94753Speter } else if (argc != 1) { 95753Speter error("%s takes either zero or one argument", p->symbol); 96753Speter rvlist(argv); 97753Speter return (NIL); 98753Speter } 99753Speter } 100753Speter /* 101753Speter * All other functions take 102753Speter * exactly one argument. 103753Speter */ 104753Speter if (argc != 1) { 105753Speter error("%s takes exactly one argument", p->symbol); 106753Speter rvlist(argv); 107753Speter return (NIL); 108753Speter } 109753Speter /* 110753Speter * Evaluate the argmument 111753Speter */ 112753Speter p1 = stkrval((int *) argv[1], NLNIL , RREQ ); 113753Speter if (p1 == NIL) 114753Speter return (NIL); 115753Speter switch (op) { 116753Speter case O_EXP: 117753Speter case O_SIN: 118753Speter case O_COS: 119753Speter case O_ATAN: 120753Speter case O_LN: 121753Speter case O_SQRT: 122753Speter case O_RANDOM: 123753Speter case O_EXPO: 124753Speter case O_UNDEF: 125753Speter if (isa(p1, "i")) 126753Speter convert(p1, nl+TDOUBLE); 127753Speter else if (isnta(p1, "d")) { 128753Speter error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1)); 129753Speter return (NIL); 130753Speter } 131753Speter put1(op); 132753Speter if (op == O_UNDEF) 133753Speter return (nl+TBOOL); 134753Speter else if (op == O_EXPO) 135753Speter return (nl+T4INT); 136753Speter else 137753Speter return (nl+TDOUBLE); 138753Speter case O_SEED: 139753Speter if (isnta(p1, "i")) { 140753Speter error("seed's argument must be an integer, not %s", nameof(p1)); 141753Speter return (NIL); 142753Speter } 143753Speter put1(op); 144753Speter return (nl+T4INT); 145753Speter case O_ROUND: 146753Speter case O_TRUNC: 147753Speter if (isnta(p1, "d")) { 148753Speter error("%s's argument must be a real, not %s", p->symbol, nameof(p1)); 149753Speter return (NIL); 150753Speter } 151753Speter put1(op); 152753Speter return (nl+T4INT); 153753Speter case O_ABS2: 154753Speter case O_SQR2: 155753Speter if (isa(p1, "d")) { 156753Speter put1(op + O_ABS8-O_ABS2); 157753Speter return (nl+TDOUBLE); 158753Speter } 159753Speter if (isa(p1, "i")) { 160753Speter put1(op + (width(p1) >> 2)); 161753Speter return (nl+T4INT); 162753Speter } 163753Speter error("%s's argument must be an integer or real, not %s", p->symbol, nameof(p1)); 164753Speter return (NIL); 165753Speter case O_ORD2: 166753Speter if (isa(p1, "bcis") || classify(p1) == TPTR) { 167753Speter return (nl+T4INT); 168753Speter } 169753Speter error("ord's argument must be of scalar type or a pointer, not %s", nameof(p1)); 170753Speter return (NIL); 171753Speter case O_SUCC2: 172753Speter case O_PRED2: 173753Speter if (isa(p1, "bcs")) { 174753Speter put1(op); 175753Speter return (p1); 176753Speter } 177753Speter if (isa(p1, "i")) { 178753Speter if (width(p1) <= 2) 179753Speter op += O_PRED24-O_PRED2; 180753Speter else 181753Speter op++; 182753Speter put1(op); 183753Speter return (nl+T4INT); 184753Speter } 185753Speter if (isa(p1, "id")) { 186753Speter error("%s is forbidden for reals", p->symbol); 187753Speter return (NIL); 188753Speter } 189753Speter error("%s's argument must be of scalar type, not %s", p->symbol, nameof(p1)); 190753Speter return (NIL); 191753Speter case O_ODD2: 192753Speter if (isnta(p1, "i")) { 193753Speter error("odd's argument must be an integer, not %s", nameof(p1)); 194753Speter return (NIL); 195753Speter } 196753Speter put1(op + (width(p1) >> 2)); 197753Speter return (nl+TBOOL); 198753Speter case O_CHR2: 199753Speter if (isnta(p1, "i")) { 200753Speter error("chr's argument must be an integer, not %s", nameof(p1)); 201753Speter return (NIL); 202753Speter } 203753Speter put1(op + (width(p1) >> 2)); 204753Speter return (nl+TCHAR); 205753Speter case O_CARD: 206753Speter if ( p1 != nl + TSET ) { 207753Speter if (isnta(p1, "t")) { 208753Speter error("Argument to card must be a set, not %s", nameof(p1)); 209753Speter return (NIL); 210753Speter } 211753Speter put2(O_CARD, width(p1)); 212753Speter } else { 213753Speter if ( !cardempty ) { 214753Speter warning(); 215753Speter error("Cardinality of the empty set is 0." ); 216753Speter cardempty = TRUE; 217753Speter } 218753Speter put(1, O_CON1, 0); 219753Speter } 220753Speter return (nl+T2INT); 221753Speter case O_EOLN: 222753Speter if (!text(p1)) { 223753Speter error("Argument to eoln must be a text file, not %s", nameof(p1)); 224753Speter return (NIL); 225753Speter } 226753Speter put1(op); 227753Speter return (nl+TBOOL); 228753Speter case O_EOF: 229753Speter if (p1->class != FILET) { 230753Speter error("Argument to eof must be file, not %s", nameof(p1)); 231753Speter return (NIL); 232753Speter } 233753Speter put1(op); 234753Speter return (nl+TBOOL); 235753Speter case 0: 236753Speter error("%s is an unimplemented 6000-3.4 extension", p->symbol); 237753Speter default: 238753Speter panic("func1"); 239753Speter } 240753Speter } 241753Speter #endif OBJ 242