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