xref: /csrg-svn/usr.bin/pascal/src/pcfunc.c (revision 18464)
1764Speter /* Copyright (c) 1979 Regents of the University of California */
2764Speter 
314738Sthien #ifndef lint
4*18464Sralph static	char sccsid[] = "@(#)pcfunc.c 2.2 03/20/85";
514738Sthien #endif
6764Speter 
7764Speter #include "whoami.h"
8764Speter #ifdef PC
9764Speter     /*
10764Speter      *	and to the end of the file
11764Speter      */
12764Speter #include "0.h"
13764Speter #include "tree.h"
1410375Speter #include "objfmt.h"
15764Speter #include "opcode.h"
1610375Speter #include "pc.h"
17*18464Sralph #include <pcc.h>
1811328Speter #include "tmps.h"
1914738Sthien #include "tree_ty.h"
20764Speter 
21764Speter /*
22764Speter  * Funccod generates code for
23764Speter  * built in function calls and calls
24764Speter  * call to generate calls to user
25764Speter  * defined functions and procedures.
26764Speter  */
2714738Sthien struct nl *
28764Speter pcfunccod( r )
2914738Sthien 	struct tnode	 *r; /* T_FCALL */
30764Speter {
31764Speter 	struct nl *p;
32764Speter 	register struct nl *p1;
3314738Sthien 	register struct tnode *al;
34764Speter 	register op;
3514738Sthien 	int argc;
3614738Sthien 	struct tnode *argv;
3714738Sthien 	struct tnode tr, tr2;
38764Speter 	char		*funcname;
393831Speter 	struct nl	*tempnlp;
40764Speter 	long		temptype;
41764Speter 	struct nl	*rettype;
42764Speter 
43764Speter 	/*
44764Speter 	 * Verify that the given name
45764Speter 	 * is defined and the name of
46764Speter 	 * a function.
47764Speter 	 */
4814738Sthien 	p = lookup(r->pcall_node.proc_id);
4914738Sthien 	if (p == NLNIL) {
5014738Sthien 		rvlist(r->pcall_node.arg);
5114738Sthien 		return (NLNIL);
52764Speter 	}
531197Speter 	if (p->class != FUNC && p->class != FFUNC) {
54764Speter 		error("%s is not a function", p->symbol);
5514738Sthien 		rvlist(r->pcall_node.arg);
5614738Sthien 		return (NLNIL);
57764Speter 	}
5814738Sthien 	argv = r->pcall_node.arg;
59764Speter 	/*
60764Speter 	 * Call handles user defined
61764Speter 	 * procedures and functions
62764Speter 	 */
63764Speter 	if (bn != 0)
64764Speter 		return (call(p, argv, FUNC, bn));
65764Speter 	/*
66764Speter 	 * Count the arguments
67764Speter 	 */
68764Speter 	argc = 0;
6914738Sthien 	for (al = argv; al != TR_NIL; al = al->list_node.next)
70764Speter 		argc++;
71764Speter 	/*
72764Speter 	 * Built-in functions have
73764Speter 	 * their interpreter opcode
74764Speter 	 * associated with them.
75764Speter 	 */
76764Speter 	op = p->value[0] &~ NSTAND;
77764Speter 	if (opt('s') && (p->value[0] & NSTAND)) {
78764Speter 		standard();
79764Speter 		error("%s is a nonstandard function", p->symbol);
80764Speter 	}
81764Speter 	if ( op == O_ARGC ) {
82*18464Sralph 	    putleaf( PCC_NAME , 0 , 0 , PCCT_INT , "__argc" );
83764Speter 	    return nl + T4INT;
84764Speter 	}
85764Speter 	switch (op) {
86764Speter 		/*
87764Speter 		 * Parameterless functions
88764Speter 		 */
89764Speter 		case O_CLCK:
90764Speter 			funcname = "_CLCK";
91764Speter 			goto noargs;
92764Speter 		case O_SCLCK:
93764Speter 			funcname = "_SCLCK";
94764Speter 			goto noargs;
95764Speter noargs:
96764Speter 			if (argc != 0) {
97764Speter 				error("%s takes no arguments", p->symbol);
98764Speter 				rvlist(argv);
9914738Sthien 				return (NLNIL);
100764Speter 			}
101*18464Sralph 			putleaf( PCC_ICON , 0 , 0
102*18464Sralph 				, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
103764Speter 				, funcname );
104*18464Sralph 			putop( PCCOM_UNARY PCC_CALL , PCCT_INT );
105764Speter 			return (nl+T4INT);
106764Speter 		case O_WCLCK:
107764Speter 			if (argc != 0) {
108764Speter 				error("%s takes no arguments", p->symbol);
109764Speter 				rvlist(argv);
11014738Sthien 				return (NLNIL);
111764Speter 			}
112*18464Sralph 			putleaf( PCC_ICON , 0 , 0
113*18464Sralph 				, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
114764Speter 				, "_time" );
115*18464Sralph 			putleaf( PCC_ICON , 0 , 0 , PCCT_INT , (char *) 0 );
116*18464Sralph 			putop( PCC_CALL , PCCT_INT );
117764Speter 			return (nl+T4INT);
118764Speter 		case O_EOF:
119764Speter 		case O_EOLN:
120764Speter 			if (argc == 0) {
12114738Sthien 				argv = &(tr);
12214738Sthien 				tr.list_node.list = &(tr2);
12314738Sthien 				tr2.tag = T_VAR;
12414738Sthien 				tr2.var_node.cptr = input->symbol;
12514738Sthien 				tr2.var_node.line_no = NIL;
12614738Sthien 				tr2.var_node.qual = TR_NIL;
127764Speter 				argc = 1;
128764Speter 			} else if (argc != 1) {
129764Speter 				error("%s takes either zero or one argument", p->symbol);
130764Speter 				rvlist(argv);
13114738Sthien 				return (NLNIL);
132764Speter 			}
133764Speter 		}
134764Speter 	/*
135764Speter 	 * All other functions take
136764Speter 	 * exactly one argument.
137764Speter 	 */
138764Speter 	if (argc != 1) {
139764Speter 		error("%s takes exactly one argument", p->symbol);
140764Speter 		rvlist(argv);
14114738Sthien 		return (NLNIL);
142764Speter 	}
143764Speter 	/*
144764Speter 	 * find out the type of the argument
145764Speter 	 */
146764Speter 	codeoff();
14714738Sthien 	p1 = stkrval( argv->list_node.list, NLNIL , (long) RREQ );
148764Speter 	codeon();
14914738Sthien 	if (p1 == NLNIL)
15014738Sthien 		return (NLNIL);
151764Speter 	/*
152764Speter 	 * figure out the return type and the funtion name
153764Speter 	 */
154764Speter 	switch (op) {
15514738Sthien 	    case 0:
15614738Sthien 			error("%s is an unimplemented 6000-3.4 extension", p->symbol);
15714738Sthien 	    default:
15814738Sthien 			panic("func1");
159764Speter 	    case O_EXP:
1605715Smckusic 		    funcname = opt('t') ? "_EXP" : "_exp";
161764Speter 		    goto mathfunc;
162764Speter 	    case O_SIN:
1635715Smckusic 		    funcname = opt('t') ? "_SIN" : "_sin";
164764Speter 		    goto mathfunc;
165764Speter 	    case O_COS:
1665715Smckusic 		    funcname = opt('t') ? "_COS" : "_cos";
167764Speter 		    goto mathfunc;
168764Speter 	    case O_ATAN:
1695715Smckusic 		    funcname = opt('t') ? "_ATAN" : "_atan";
170764Speter 		    goto mathfunc;
171764Speter 	    case O_LN:
172764Speter 		    funcname = opt('t') ? "_LN" : "_log";
173764Speter 		    goto mathfunc;
174764Speter 	    case O_SQRT:
175764Speter 		    funcname = opt('t') ? "_SQRT" : "_sqrt";
176764Speter 		    goto mathfunc;
177764Speter 	    case O_RANDOM:
178764Speter 		    funcname = "_RANDOM";
179764Speter 		    goto mathfunc;
180764Speter mathfunc:
181764Speter 		    if (isnta(p1, "id")) {
182764Speter 			    error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1));
18314738Sthien 			    return (NLNIL);
184764Speter 		    }
185*18464Sralph 		    putleaf( PCC_ICON , 0 , 0
186*18464Sralph 			    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_DOUBLE , PCCTM_PTR ) , funcname );
18714738Sthien 		    p1 = stkrval(  argv->list_node.list , NLNIL , (long) RREQ );
188*18464Sralph 		    sconv(p2type(p1), PCCT_DOUBLE);
189*18464Sralph 		    putop( PCC_CALL , PCCT_DOUBLE );
190764Speter 		    return nl + TDOUBLE;
191764Speter 	    case O_EXPO:
192764Speter 		    if (isnta( p1 , "id" ) ) {
193764Speter 			    error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1));
194764Speter 			    return NIL;
195764Speter 		    }
196*18464Sralph 		    putleaf( PCC_ICON , 0 , 0
197*18464Sralph 			    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , "_EXPO" );
19814738Sthien 		    p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ );
199*18464Sralph 		    sconv(p2type(p1), PCCT_DOUBLE);
200*18464Sralph 		    putop( PCC_CALL , PCCT_INT );
201764Speter 		    return ( nl + T4INT );
202764Speter 	    case O_UNDEF:
203764Speter 		    if ( isnta( p1 , "id" ) ) {
204764Speter 			    error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1));
20514738Sthien 			    return NLNIL;
206764Speter 		    }
20714738Sthien 		    p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ );
208*18464Sralph 		    putleaf( PCC_ICON , 0 , 0 , PCCT_CHAR , (char *) 0 );
209*18464Sralph 		    putop( PCC_COMOP , PCCT_CHAR );
210764Speter 		    return ( nl + TBOOL );
211764Speter 	    case O_SEED:
212764Speter 		    if (isnta(p1, "i")) {
213764Speter 			    error("seed's argument must be an integer, not %s", nameof(p1));
21414738Sthien 			    return (NLNIL);
215764Speter 		    }
216*18464Sralph 		    putleaf( PCC_ICON , 0 , 0
217*18464Sralph 			    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , "_SEED" );
21814738Sthien 		    p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ );
219*18464Sralph 		    putop( PCC_CALL , PCCT_INT );
220764Speter 		    return nl + T4INT;
221764Speter 	    case O_ROUND:
222764Speter 	    case O_TRUNC:
223764Speter 		    if ( isnta( p1 , "d" ) ) {
224764Speter 			    error("%s's argument must be a real, not %s", p->symbol, nameof(p1));
22514738Sthien 			    return (NLNIL);
226764Speter 		    }
227*18464Sralph 		    putleaf( PCC_ICON , 0 , 0
228*18464Sralph 			    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
229764Speter 			    , op == O_ROUND ? "_ROUND" : "_TRUNC" );
23014738Sthien 		    p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ );
231*18464Sralph 		    putop( PCC_CALL , PCCT_INT );
232764Speter 		    return nl + T4INT;
233764Speter 	    case O_ABS2:
234764Speter 			if ( isa( p1 , "d" ) ) {
235*18464Sralph 			    putleaf( PCC_ICON , 0 , 0
236*18464Sralph 				, PCCM_ADDTYPE( PCCTM_FTN | PCCT_DOUBLE , PCCTM_PTR )
237764Speter 				, "_fabs" );
23814738Sthien 			    p1 = stkrval( argv->list_node.list , NLNIL ,(long) RREQ );
239*18464Sralph 			    putop( PCC_CALL , PCCT_DOUBLE );
240764Speter 			    return nl + TDOUBLE;
241764Speter 			}
242764Speter 			if ( isa( p1 , "i" ) ) {
243*18464Sralph 			    putleaf( PCC_ICON , 0 , 0
244*18464Sralph 				, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , "_abs" );
24514738Sthien 			    p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ );
246*18464Sralph 			    putop( PCC_CALL , PCCT_INT );
247764Speter 			    return nl + T4INT;
248764Speter 			}
249764Speter 			error("%s's argument must be an integer or real, not %s", p->symbol, nameof(p1));
25014738Sthien 			return NLNIL;
251764Speter 	    case O_SQR2:
252764Speter 			if ( isa( p1 , "d" ) ) {
253*18464Sralph 			    temptype = PCCT_DOUBLE;
254764Speter 			    rettype = nl + TDOUBLE;
25514738Sthien 			    tempnlp = tmpalloc((long) (sizeof(double)), rettype, REGOK);
256764Speter 			} else if ( isa( p1 , "i" ) ) {
257*18464Sralph 			    temptype = PCCT_INT;
258764Speter 			    rettype = nl + T4INT;
25914738Sthien 			    tempnlp = tmpalloc((long) (sizeof(long)), rettype, REGOK);
260764Speter 			} else {
261764Speter 			    error("%s's argument must be an integer or real, not %s", p->symbol, nameof(p1));
26214738Sthien 			    return NLNIL;
263764Speter 			}
26414738Sthien 			putRV( (char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] ,
26514738Sthien 				tempnlp -> extra_flags , (char) temptype  );
26614738Sthien 			p1 = rvalue( argv->list_node.list , NLNIL , RREQ );
26714738Sthien 			sconv(p2type(p1), (int) temptype);
268*18464Sralph 			putop( PCC_ASSIGN , (int) temptype );
26914738Sthien 			putRV((char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] ,
27014738Sthien 				tempnlp -> extra_flags , (char) temptype );
27114738Sthien 			putRV((char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] ,
27214738Sthien 				tempnlp -> extra_flags , (char) temptype );
273*18464Sralph 			putop( PCC_MUL , (int) temptype );
274*18464Sralph 			putop( PCC_COMOP , (int) temptype );
275764Speter 			return rettype;
276764Speter 	    case O_ORD2:
27714738Sthien 			p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ );
2789573Speter 			if (isa(p1, "bcis")) {
279764Speter 				return (nl+T4INT);
280764Speter 			}
2819573Speter 			if (classify(p1) == TPTR) {
2829573Speter 			    if (!opt('s')) {
2839573Speter 				return (nl+T4INT);
2849573Speter 			    }
2859573Speter 			    standard();
2869573Speter 			}
2879573Speter 			error("ord's argument must be of scalar type, not %s",
2889573Speter 				nameof(p1));
28914738Sthien 			return (NLNIL);
290764Speter 	    case O_SUCC2:
291764Speter 	    case O_PRED2:
292764Speter 			if (isa(p1, "d")) {
293764Speter 				error("%s is forbidden for reals", p->symbol);
29414738Sthien 				return (NLNIL);
295764Speter 			}
296764Speter 			if ( isnta( p1 , "bcsi" ) ) {
297764Speter 			    error("%s's argument must be of scalar type, not %s", p->symbol, nameof(p1));
29814738Sthien 			    return NLNIL;
299764Speter 			}
300764Speter 			if ( opt( 't' ) ) {
301*18464Sralph 			    putleaf( PCC_ICON , 0 , 0
302*18464Sralph 				    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
303764Speter 				    , op == O_SUCC2 ? "_SUCC" : "_PRED" );
30414738Sthien 			    p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ );
3056596Smckusick 			    tempnlp = p1 -> class == TYPE ? p1 -> type : p1;
306*18464Sralph 			    putleaf( PCC_ICON, (int) tempnlp -> range[0], 0, PCCT_INT, (char *) 0 );
307*18464Sralph 			    putop( PCC_CM , PCCT_INT );
308*18464Sralph 			    putleaf( PCC_ICON, (int) tempnlp -> range[1], 0, PCCT_INT, (char *) 0 );
309*18464Sralph 			    putop( PCC_CM , PCCT_INT );
310*18464Sralph 			    putop( PCC_CALL , PCCT_INT );
311*18464Sralph 			    sconv(PCCT_INT, p2type(p1));
312764Speter 			} else {
31314738Sthien 			    p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ );
314*18464Sralph 			    putleaf( PCC_ICON , 1 , 0 , PCCT_INT , (char *) 0 );
315*18464Sralph 			    putop( op == O_SUCC2 ? PCC_PLUS : PCC_MINUS , PCCT_INT );
316*18464Sralph 			    sconv(PCCT_INT, p2type(p1));
317764Speter 			}
318764Speter 			if ( isa( p1 , "bcs" ) ) {
319764Speter 			    return p1;
320764Speter 			} else {
321764Speter 			    return nl + T4INT;
322764Speter 			}
323764Speter 	    case O_ODD2:
324764Speter 			if (isnta(p1, "i")) {
325764Speter 				error("odd's argument must be an integer, not %s", nameof(p1));
32614738Sthien 				return (NLNIL);
327764Speter 			}
32814738Sthien 			p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ );
32910669Speter 			    /*
33010669Speter 			     *	THIS IS MACHINE-DEPENDENT!!!
33110669Speter 			     */
332*18464Sralph 			putleaf( PCC_ICON , 1 , 0 , PCCT_INT , (char *) 0 );
333*18464Sralph 			putop( PCC_AND , PCCT_INT );
334*18464Sralph 			sconv(PCCT_INT, PCCT_CHAR);
335764Speter 			return nl + TBOOL;
336764Speter 	    case O_CHR2:
337764Speter 			if (isnta(p1, "i")) {
338764Speter 				error("chr's argument must be an integer, not %s", nameof(p1));
33914738Sthien 				return (NLNIL);
340764Speter 			}
341764Speter 			if (opt('t')) {
342*18464Sralph 			    putleaf( PCC_ICON , 0 , 0
343*18464Sralph 				, PCCM_ADDTYPE( PCCTM_FTN | PCCT_CHAR , PCCTM_PTR ) , "_CHR" );
34414738Sthien 			    p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ );
345*18464Sralph 			    putop( PCC_CALL , PCCT_CHAR );
346764Speter 			} else {
34714738Sthien 			    p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ );
348*18464Sralph 			    sconv(PCCT_INT, PCCT_CHAR);
349764Speter 			}
350764Speter 			return nl + TCHAR;
351764Speter 	    case O_CARD:
3521554Speter 			if (isnta(p1, "t")) {
3531554Speter 			    error("Argument to card must be a set, not %s", nameof(p1));
35414738Sthien 			    return (NLNIL);
355764Speter 			}
356*18464Sralph 			putleaf( PCC_ICON , 0 , 0
357*18464Sralph 			    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , "_CARD" );
35814738Sthien 			p1 = stkrval( argv->list_node.list , NLNIL , (long) LREQ );
359*18464Sralph 			putleaf( PCC_ICON , (int) lwidth( p1 ) , 0 , PCCT_INT , (char *) 0 );
360*18464Sralph 			putop( PCC_CM , PCCT_INT );
361*18464Sralph 			putop( PCC_CALL , PCCT_INT );
36210669Speter 			return nl + T4INT;
363764Speter 	    case O_EOLN:
364764Speter 			if (!text(p1)) {
365764Speter 				error("Argument to eoln must be a text file, not %s", nameof(p1));
36614738Sthien 				return (NLNIL);
367764Speter 			}
368*18464Sralph 			putleaf( PCC_ICON , 0 , 0
369*18464Sralph 			    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , "_TEOLN" );
37014738Sthien 			p1 = stklval( argv->list_node.list , NOFLAGS );
371*18464Sralph 			putop( PCC_CALL , PCCT_INT );
372*18464Sralph 			sconv(PCCT_INT, PCCT_CHAR);
373764Speter 			return nl + TBOOL;
374764Speter 	    case O_EOF:
375764Speter 			if (p1->class != FILET) {
376764Speter 				error("Argument to eof must be file, not %s", nameof(p1));
37714738Sthien 				return (NLNIL);
378764Speter 			}
379*18464Sralph 			putleaf( PCC_ICON , 0 , 0
380*18464Sralph 			    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , "_TEOF" );
38114738Sthien 			p1 = stklval( argv->list_node.list , NOFLAGS );
382*18464Sralph 			putop( PCC_CALL , PCCT_INT );
383*18464Sralph 			sconv(PCCT_INT, PCCT_CHAR);
384764Speter 			return nl + TBOOL;
385764Speter 	}
386764Speter }
387764Speter #endif PC
388