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