|
|
1.1 root 1: /* Copyright (c) 1979 Regents of the University of California */
2:
3: static char sccsid[] = "@(#)pcfunc.c 1.13 2/28/83";
4:
5: #include "whoami.h"
6: #ifdef PC
7: /*
8: * and to the end of the file
9: */
10: #include "0.h"
11: #include "tree.h"
12: #include "objfmt.h"
13: #include "opcode.h"
14: #include "pc.h"
15: #include "pcops.h"
16: #include "tmps.h"
17:
18: /*
19: * Funccod generates code for
20: * built in function calls and calls
21: * call to generate calls to user
22: * defined functions and procedures.
23: */
24: pcfunccod( r )
25: int *r;
26: {
27: struct nl *p;
28: register struct nl *p1;
29: register int *al;
30: register op;
31: int argc, *argv;
32: int tr[2], tr2[4];
33: char *funcname;
34: struct nl *tempnlp;
35: long temptype;
36: struct nl *rettype;
37:
38: /*
39: * Verify that the given name
40: * is defined and the name of
41: * a function.
42: */
43: p = lookup(r[2]);
44: if (p == NIL) {
45: rvlist(r[3]);
46: return (NIL);
47: }
48: if (p->class != FUNC && p->class != FFUNC) {
49: error("%s is not a function", p->symbol);
50: rvlist(r[3]);
51: return (NIL);
52: }
53: argv = r[3];
54: /*
55: * Call handles user defined
56: * procedures and functions
57: */
58: if (bn != 0)
59: return (call(p, argv, FUNC, bn));
60: /*
61: * Count the arguments
62: */
63: argc = 0;
64: for (al = argv; al != NIL; al = al[2])
65: argc++;
66: /*
67: * Built-in functions have
68: * their interpreter opcode
69: * associated with them.
70: */
71: op = p->value[0] &~ NSTAND;
72: if (opt('s') && (p->value[0] & NSTAND)) {
73: standard();
74: error("%s is a nonstandard function", p->symbol);
75: }
76: if ( op == O_ARGC ) {
77: putleaf( P2NAME , 0 , 0 , P2INT , "__argc" );
78: return nl + T4INT;
79: }
80: switch (op) {
81: /*
82: * Parameterless functions
83: */
84: case O_CLCK:
85: funcname = "_CLCK";
86: goto noargs;
87: case O_SCLCK:
88: funcname = "_SCLCK";
89: goto noargs;
90: noargs:
91: if (argc != 0) {
92: error("%s takes no arguments", p->symbol);
93: rvlist(argv);
94: return (NIL);
95: }
96: putleaf( P2ICON , 0 , 0
97: , ADDTYPE( P2FTN | P2INT , P2PTR )
98: , funcname );
99: putop( P2UNARY P2CALL , P2INT );
100: return (nl+T4INT);
101: case O_WCLCK:
102: if (argc != 0) {
103: error("%s takes no arguments", p->symbol);
104: rvlist(argv);
105: return (NIL);
106: }
107: putleaf( P2ICON , 0 , 0
108: , ADDTYPE( P2FTN | P2INT , P2PTR )
109: , "_time" );
110: putleaf( P2ICON , 0 , 0 , P2INT , 0 );
111: putop( P2CALL , P2INT );
112: return (nl+T4INT);
113: case O_EOF:
114: case O_EOLN:
115: if (argc == 0) {
116: argv = tr;
117: tr[1] = tr2;
118: tr2[0] = T_VAR;
119: tr2[2] = input->symbol;
120: tr2[1] = tr2[3] = NIL;
121: argc = 1;
122: } else if (argc != 1) {
123: error("%s takes either zero or one argument", p->symbol);
124: rvlist(argv);
125: return (NIL);
126: }
127: }
128: /*
129: * All other functions take
130: * exactly one argument.
131: */
132: if (argc != 1) {
133: error("%s takes exactly one argument", p->symbol);
134: rvlist(argv);
135: return (NIL);
136: }
137: /*
138: * find out the type of the argument
139: */
140: codeoff();
141: p1 = stkrval((int *) argv[1], NLNIL , RREQ );
142: codeon();
143: if (p1 == NIL)
144: return (NIL);
145: /*
146: * figure out the return type and the funtion name
147: */
148: switch (op) {
149: case O_EXP:
150: funcname = opt('t') ? "_EXP" : "_exp";
151: goto mathfunc;
152: case O_SIN:
153: funcname = opt('t') ? "_SIN" : "_sin";
154: goto mathfunc;
155: case O_COS:
156: funcname = opt('t') ? "_COS" : "_cos";
157: goto mathfunc;
158: case O_ATAN:
159: funcname = opt('t') ? "_ATAN" : "_atan";
160: goto mathfunc;
161: case O_LN:
162: funcname = opt('t') ? "_LN" : "_log";
163: goto mathfunc;
164: case O_SQRT:
165: funcname = opt('t') ? "_SQRT" : "_sqrt";
166: goto mathfunc;
167: case O_RANDOM:
168: funcname = "_RANDOM";
169: goto mathfunc;
170: mathfunc:
171: if (isnta(p1, "id")) {
172: error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1));
173: return (NIL);
174: }
175: putleaf( P2ICON , 0 , 0
176: , ADDTYPE( P2FTN | P2DOUBLE , P2PTR ) , funcname );
177: p1 = stkrval( (int *) argv[1] , NLNIL , RREQ );
178: sconv(p2type(p1), P2DOUBLE);
179: putop( P2CALL , P2DOUBLE );
180: return nl + TDOUBLE;
181: case O_EXPO:
182: if (isnta( p1 , "id" ) ) {
183: error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1));
184: return NIL;
185: }
186: putleaf( P2ICON , 0 , 0
187: , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_EXPO" );
188: p1 = stkrval( (int *) argv[1] , NLNIL , RREQ );
189: sconv(p2type(p1), P2DOUBLE);
190: putop( P2CALL , P2INT );
191: return ( nl + T4INT );
192: case O_UNDEF:
193: if ( isnta( p1 , "id" ) ) {
194: error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1));
195: return NIL;
196: }
197: p1 = stkrval( (int *) argv[1] , NLNIL , RREQ );
198: putleaf( P2ICON , 0 , 0 , P2CHAR , 0 );
199: putop( P2COMOP , P2CHAR );
200: return ( nl + TBOOL );
201: case O_SEED:
202: if (isnta(p1, "i")) {
203: error("seed's argument must be an integer, not %s", nameof(p1));
204: return (NIL);
205: }
206: putleaf( P2ICON , 0 , 0
207: , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_SEED" );
208: p1 = stkrval( (int *) argv[1] , NLNIL , RREQ );
209: putop( P2CALL , P2INT );
210: return nl + T4INT;
211: case O_ROUND:
212: case O_TRUNC:
213: if ( isnta( p1 , "d" ) ) {
214: error("%s's argument must be a real, not %s", p->symbol, nameof(p1));
215: return (NIL);
216: }
217: putleaf( P2ICON , 0 , 0
218: , ADDTYPE( P2FTN | P2INT , P2PTR )
219: , op == O_ROUND ? "_ROUND" : "_TRUNC" );
220: p1 = stkrval( (int *) argv[1] , NLNIL , RREQ );
221: putop( P2CALL , P2INT );
222: return nl + T4INT;
223: case O_ABS2:
224: if ( isa( p1 , "d" ) ) {
225: putleaf( P2ICON , 0 , 0
226: , ADDTYPE( P2FTN | P2DOUBLE , P2PTR )
227: , "_fabs" );
228: p1 = stkrval( (int *) argv[1] , NLNIL , RREQ );
229: putop( P2CALL , P2DOUBLE );
230: return nl + TDOUBLE;
231: }
232: if ( isa( p1 , "i" ) ) {
233: putleaf( P2ICON , 0 , 0
234: , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_abs" );
235: p1 = stkrval( (int *) argv[1] , NLNIL , RREQ );
236: putop( P2CALL , P2INT );
237: return nl + T4INT;
238: }
239: error("%s's argument must be an integer or real, not %s", p->symbol, nameof(p1));
240: return NIL;
241: case O_SQR2:
242: if ( isa( p1 , "d" ) ) {
243: temptype = P2DOUBLE;
244: rettype = nl + TDOUBLE;
245: tempnlp = tmpalloc(sizeof(double), rettype, REGOK);
246: } else if ( isa( p1 , "i" ) ) {
247: temptype = P2INT;
248: rettype = nl + T4INT;
249: tempnlp = tmpalloc(sizeof(long), rettype, REGOK);
250: } else {
251: error("%s's argument must be an integer or real, not %s", p->symbol, nameof(p1));
252: return NIL;
253: }
254: putRV( 0 , cbn , tempnlp -> value[ NL_OFFS ] ,
255: tempnlp -> extra_flags , temptype , 0 );
256: p1 = rvalue( (int *) argv[1] , NLNIL , RREQ );
257: sconv(p2type(p1), temptype);
258: putop( P2ASSIGN , temptype );
259: putRV( 0 , cbn , tempnlp -> value[ NL_OFFS ] ,
260: tempnlp -> extra_flags , temptype , 0 );
261: putRV( 0 , cbn , tempnlp -> value[ NL_OFFS ] ,
262: tempnlp -> extra_flags , temptype , 0 );
263: putop( P2MUL , temptype );
264: putop( P2COMOP , temptype );
265: return rettype;
266: case O_ORD2:
267: p1 = stkrval( (int *) argv[1] , NLNIL , RREQ );
268: if (isa(p1, "bcis")) {
269: return (nl+T4INT);
270: }
271: if (classify(p1) == TPTR) {
272: if (!opt('s')) {
273: return (nl+T4INT);
274: }
275: standard();
276: }
277: error("ord's argument must be of scalar type, not %s",
278: nameof(p1));
279: return (NIL);
280: case O_SUCC2:
281: case O_PRED2:
282: if (isa(p1, "d")) {
283: error("%s is forbidden for reals", p->symbol);
284: return (NIL);
285: }
286: if ( isnta( p1 , "bcsi" ) ) {
287: error("%s's argument must be of scalar type, not %s", p->symbol, nameof(p1));
288: return NIL;
289: }
290: if ( opt( 't' ) ) {
291: putleaf( P2ICON , 0 , 0
292: , ADDTYPE( P2FTN | P2INT , P2PTR )
293: , op == O_SUCC2 ? "_SUCC" : "_PRED" );
294: p1 = stkrval( (int *) argv[1] , NLNIL , RREQ );
295: tempnlp = p1 -> class == TYPE ? p1 -> type : p1;
296: putleaf( P2ICON, tempnlp -> range[0], 0, P2INT, 0 );
297: putop( P2LISTOP , P2INT );
298: putleaf( P2ICON, tempnlp -> range[1], 0, P2INT, 0 );
299: putop( P2LISTOP , P2INT );
300: putop( P2CALL , P2INT );
301: sconv(P2INT, p2type(p1));
302: } else {
303: p1 = stkrval( (int *) argv[1] , NLNIL , RREQ );
304: putleaf( P2ICON , 1 , 0 , P2INT , 0 );
305: putop( op == O_SUCC2 ? P2PLUS : P2MINUS , P2INT );
306: sconv(P2INT, p2type(p1));
307: }
308: if ( isa( p1 , "bcs" ) ) {
309: return p1;
310: } else {
311: return nl + T4INT;
312: }
313: case O_ODD2:
314: if (isnta(p1, "i")) {
315: error("odd's argument must be an integer, not %s", nameof(p1));
316: return (NIL);
317: }
318: p1 = stkrval( (int *) argv[1] , NLNIL , RREQ );
319: /*
320: * THIS IS MACHINE-DEPENDENT!!!
321: */
322: putleaf( P2ICON , 1 , 0 , P2INT , 0 );
323: putop( P2AND , P2INT );
324: sconv(P2INT, P2CHAR);
325: return nl + TBOOL;
326: case O_CHR2:
327: if (isnta(p1, "i")) {
328: error("chr's argument must be an integer, not %s", nameof(p1));
329: return (NIL);
330: }
331: if (opt('t')) {
332: putleaf( P2ICON , 0 , 0
333: , ADDTYPE( P2FTN | P2CHAR , P2PTR ) , "_CHR" );
334: p1 = stkrval( (int *) argv[1] , NLNIL , RREQ );
335: putop( P2CALL , P2CHAR );
336: } else {
337: p1 = stkrval( (int *) argv[1] , NLNIL , RREQ );
338: sconv(P2INT, P2CHAR);
339: }
340: return nl + TCHAR;
341: case O_CARD:
342: if (isnta(p1, "t")) {
343: error("Argument to card must be a set, not %s", nameof(p1));
344: return (NIL);
345: }
346: putleaf( P2ICON , 0 , 0
347: , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_CARD" );
348: p1 = stkrval( (int *) argv[1] , NLNIL , LREQ );
349: putleaf( P2ICON , lwidth( p1 ) , 0 , P2INT , 0 );
350: putop( P2LISTOP , P2INT );
351: putop( P2CALL , P2INT );
352: return nl + T4INT;
353: case O_EOLN:
354: if (!text(p1)) {
355: error("Argument to eoln must be a text file, not %s", nameof(p1));
356: return (NIL);
357: }
358: putleaf( P2ICON , 0 , 0
359: , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_TEOLN" );
360: p1 = stklval( (int *) argv[1] , NOFLAGS );
361: putop( P2CALL , P2INT );
362: sconv(P2INT, P2CHAR);
363: return nl + TBOOL;
364: case O_EOF:
365: if (p1->class != FILET) {
366: error("Argument to eof must be file, not %s", nameof(p1));
367: return (NIL);
368: }
369: putleaf( P2ICON , 0 , 0
370: , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_TEOF" );
371: p1 = stklval( (int *) argv[1] , NOFLAGS );
372: putop( P2CALL , P2INT );
373: sconv(P2INT, P2CHAR);
374: return nl + TBOOL;
375: case 0:
376: error("%s is an unimplemented 6000-3.4 extension", p->symbol);
377: default:
378: panic("func1");
379: }
380: }
381: #endif PC
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.