1*753Speter /* Copyright (c) 1979 Regents of the University of California */ 2*753Speter 3*753Speter static char sccsid[] = "@(#)func.c 1.1 08/27/80"; 4*753Speter 5*753Speter #include "whoami.h" 6*753Speter #ifdef OBJ 7*753Speter /* 8*753Speter * the rest of the file 9*753Speter */ 10*753Speter #include "0.h" 11*753Speter #include "tree.h" 12*753Speter #include "opcode.h" 13*753Speter 14*753Speter bool cardempty = FALSE; 15*753Speter 16*753Speter /* 17*753Speter * Funccod generates code for 18*753Speter * built in function calls and calls 19*753Speter * call to generate calls to user 20*753Speter * defined functions and procedures. 21*753Speter */ 22*753Speter funccod(r) 23*753Speter int *r; 24*753Speter { 25*753Speter struct nl *p; 26*753Speter register struct nl *p1; 27*753Speter register int *al; 28*753Speter register op; 29*753Speter int argc, *argv; 30*753Speter int tr[2], tr2[4]; 31*753Speter 32*753Speter /* 33*753Speter * Verify that the given name 34*753Speter * is defined and the name of 35*753Speter * a function. 36*753Speter */ 37*753Speter p = lookup(r[2]); 38*753Speter if (p == NIL) { 39*753Speter rvlist(r[3]); 40*753Speter return (NIL); 41*753Speter } 42*753Speter if (p->class != FUNC) { 43*753Speter error("%s is not a function", p->symbol); 44*753Speter rvlist(r[3]); 45*753Speter return (NIL); 46*753Speter } 47*753Speter argv = r[3]; 48*753Speter /* 49*753Speter * Call handles user defined 50*753Speter * procedures and functions 51*753Speter */ 52*753Speter if (bn != 0) 53*753Speter return (call(p, argv, FUNC, bn)); 54*753Speter /* 55*753Speter * Count the arguments 56*753Speter */ 57*753Speter argc = 0; 58*753Speter for (al = argv; al != NIL; al = al[2]) 59*753Speter argc++; 60*753Speter /* 61*753Speter * Built-in functions have 62*753Speter * their interpreter opcode 63*753Speter * associated with them. 64*753Speter */ 65*753Speter op = p->value[0] &~ NSTAND; 66*753Speter if (opt('s') && (p->value[0] & NSTAND)) { 67*753Speter standard(); 68*753Speter error("%s is a nonstandard function", p->symbol); 69*753Speter } 70*753Speter switch (op) { 71*753Speter /* 72*753Speter * Parameterless functions 73*753Speter */ 74*753Speter case O_CLCK: 75*753Speter case O_SCLCK: 76*753Speter case O_WCLCK: 77*753Speter case O_ARGC: 78*753Speter if (argc != 0) { 79*753Speter error("%s takes no arguments", p->symbol); 80*753Speter rvlist(argv); 81*753Speter return (NIL); 82*753Speter } 83*753Speter put1(op); 84*753Speter return (nl+T4INT); 85*753Speter case O_EOF: 86*753Speter case O_EOLN: 87*753Speter if (argc == 0) { 88*753Speter argv = tr; 89*753Speter tr[1] = tr2; 90*753Speter tr2[0] = T_VAR; 91*753Speter tr2[2] = input->symbol; 92*753Speter tr2[1] = tr2[3] = NIL; 93*753Speter argc = 1; 94*753Speter } else if (argc != 1) { 95*753Speter error("%s takes either zero or one argument", p->symbol); 96*753Speter rvlist(argv); 97*753Speter return (NIL); 98*753Speter } 99*753Speter } 100*753Speter /* 101*753Speter * All other functions take 102*753Speter * exactly one argument. 103*753Speter */ 104*753Speter if (argc != 1) { 105*753Speter error("%s takes exactly one argument", p->symbol); 106*753Speter rvlist(argv); 107*753Speter return (NIL); 108*753Speter } 109*753Speter /* 110*753Speter * Evaluate the argmument 111*753Speter */ 112*753Speter p1 = stkrval((int *) argv[1], NLNIL , RREQ ); 113*753Speter if (p1 == NIL) 114*753Speter return (NIL); 115*753Speter switch (op) { 116*753Speter case O_EXP: 117*753Speter case O_SIN: 118*753Speter case O_COS: 119*753Speter case O_ATAN: 120*753Speter case O_LN: 121*753Speter case O_SQRT: 122*753Speter case O_RANDOM: 123*753Speter case O_EXPO: 124*753Speter case O_UNDEF: 125*753Speter if (isa(p1, "i")) 126*753Speter convert(p1, nl+TDOUBLE); 127*753Speter else if (isnta(p1, "d")) { 128*753Speter error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1)); 129*753Speter return (NIL); 130*753Speter } 131*753Speter put1(op); 132*753Speter if (op == O_UNDEF) 133*753Speter return (nl+TBOOL); 134*753Speter else if (op == O_EXPO) 135*753Speter return (nl+T4INT); 136*753Speter else 137*753Speter return (nl+TDOUBLE); 138*753Speter case O_SEED: 139*753Speter if (isnta(p1, "i")) { 140*753Speter error("seed's argument must be an integer, not %s", nameof(p1)); 141*753Speter return (NIL); 142*753Speter } 143*753Speter put1(op); 144*753Speter return (nl+T4INT); 145*753Speter case O_ROUND: 146*753Speter case O_TRUNC: 147*753Speter if (isnta(p1, "d")) { 148*753Speter error("%s's argument must be a real, not %s", p->symbol, nameof(p1)); 149*753Speter return (NIL); 150*753Speter } 151*753Speter put1(op); 152*753Speter return (nl+T4INT); 153*753Speter case O_ABS2: 154*753Speter case O_SQR2: 155*753Speter if (isa(p1, "d")) { 156*753Speter put1(op + O_ABS8-O_ABS2); 157*753Speter return (nl+TDOUBLE); 158*753Speter } 159*753Speter if (isa(p1, "i")) { 160*753Speter put1(op + (width(p1) >> 2)); 161*753Speter return (nl+T4INT); 162*753Speter } 163*753Speter error("%s's argument must be an integer or real, not %s", p->symbol, nameof(p1)); 164*753Speter return (NIL); 165*753Speter case O_ORD2: 166*753Speter if (isa(p1, "bcis") || classify(p1) == TPTR) { 167*753Speter return (nl+T4INT); 168*753Speter } 169*753Speter error("ord's argument must be of scalar type or a pointer, not %s", nameof(p1)); 170*753Speter return (NIL); 171*753Speter case O_SUCC2: 172*753Speter case O_PRED2: 173*753Speter if (isa(p1, "bcs")) { 174*753Speter put1(op); 175*753Speter return (p1); 176*753Speter } 177*753Speter if (isa(p1, "i")) { 178*753Speter if (width(p1) <= 2) 179*753Speter op += O_PRED24-O_PRED2; 180*753Speter else 181*753Speter op++; 182*753Speter put1(op); 183*753Speter return (nl+T4INT); 184*753Speter } 185*753Speter if (isa(p1, "id")) { 186*753Speter error("%s is forbidden for reals", p->symbol); 187*753Speter return (NIL); 188*753Speter } 189*753Speter error("%s's argument must be of scalar type, not %s", p->symbol, nameof(p1)); 190*753Speter return (NIL); 191*753Speter case O_ODD2: 192*753Speter if (isnta(p1, "i")) { 193*753Speter error("odd's argument must be an integer, not %s", nameof(p1)); 194*753Speter return (NIL); 195*753Speter } 196*753Speter put1(op + (width(p1) >> 2)); 197*753Speter return (nl+TBOOL); 198*753Speter case O_CHR2: 199*753Speter if (isnta(p1, "i")) { 200*753Speter error("chr's argument must be an integer, not %s", nameof(p1)); 201*753Speter return (NIL); 202*753Speter } 203*753Speter put1(op + (width(p1) >> 2)); 204*753Speter return (nl+TCHAR); 205*753Speter case O_CARD: 206*753Speter if ( p1 != nl + TSET ) { 207*753Speter if (isnta(p1, "t")) { 208*753Speter error("Argument to card must be a set, not %s", nameof(p1)); 209*753Speter return (NIL); 210*753Speter } 211*753Speter put2(O_CARD, width(p1)); 212*753Speter } else { 213*753Speter if ( !cardempty ) { 214*753Speter warning(); 215*753Speter error("Cardinality of the empty set is 0." ); 216*753Speter cardempty = TRUE; 217*753Speter } 218*753Speter put(1, O_CON1, 0); 219*753Speter } 220*753Speter return (nl+T2INT); 221*753Speter case O_EOLN: 222*753Speter if (!text(p1)) { 223*753Speter error("Argument to eoln must be a text file, not %s", nameof(p1)); 224*753Speter return (NIL); 225*753Speter } 226*753Speter put1(op); 227*753Speter return (nl+TBOOL); 228*753Speter case O_EOF: 229*753Speter if (p1->class != FILET) { 230*753Speter error("Argument to eof must be file, not %s", nameof(p1)); 231*753Speter return (NIL); 232*753Speter } 233*753Speter put1(op); 234*753Speter return (nl+TBOOL); 235*753Speter case 0: 236*753Speter error("%s is an unimplemented 6000-3.4 extension", p->symbol); 237*753Speter default: 238*753Speter panic("func1"); 239*753Speter } 240*753Speter } 241*753Speter #endif OBJ 242