xref: /csrg-svn/usr.bin/pascal/src/pcfunc.c (revision 14738)
1764Speter /* Copyright (c) 1979 Regents of the University of California */
2764Speter 
3*14738Sthien #ifndef lint
4*14738Sthien static	char sccsid[] = "@(#)pcfunc.c 1.14 08/19/83";
5*14738Sthien #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"
1710375Speter #include "pcops.h"
1811328Speter #include "tmps.h"
19*14738Sthien #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  */
27*14738Sthien struct nl *
28764Speter pcfunccod( r )
29*14738Sthien 	struct tnode	 *r; /* T_FCALL */
30764Speter {
31764Speter 	struct nl *p;
32764Speter 	register struct nl *p1;
33*14738Sthien 	register struct tnode *al;
34764Speter 	register op;
35*14738Sthien 	int argc;
36*14738Sthien 	struct tnode *argv;
37*14738Sthien 	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 	 */
48*14738Sthien 	p = lookup(r->pcall_node.proc_id);
49*14738Sthien 	if (p == NLNIL) {
50*14738Sthien 		rvlist(r->pcall_node.arg);
51*14738Sthien 		return (NLNIL);
52764Speter 	}
531197Speter 	if (p->class != FUNC && p->class != FFUNC) {
54764Speter 		error("%s is not a function", p->symbol);
55*14738Sthien 		rvlist(r->pcall_node.arg);
56*14738Sthien 		return (NLNIL);
57764Speter 	}
58*14738Sthien 	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;
69*14738Sthien 	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 ) {
82764Speter 	    putleaf( P2NAME , 0 , 0 , P2INT , "__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);
99*14738Sthien 				return (NLNIL);
100764Speter 			}
101764Speter 			putleaf( P2ICON , 0 , 0
102764Speter 				, ADDTYPE( P2FTN | P2INT , P2PTR )
103764Speter 				, funcname );
104764Speter 			putop( P2UNARY P2CALL , P2INT );
105764Speter 			return (nl+T4INT);
106764Speter 		case O_WCLCK:
107764Speter 			if (argc != 0) {
108764Speter 				error("%s takes no arguments", p->symbol);
109764Speter 				rvlist(argv);
110*14738Sthien 				return (NLNIL);
111764Speter 			}
112764Speter 			putleaf( P2ICON , 0 , 0
113764Speter 				, ADDTYPE( P2FTN | P2INT , P2PTR )
114764Speter 				, "_time" );
115*14738Sthien 			putleaf( P2ICON , 0 , 0 , P2INT , (char *) 0 );
116764Speter 			putop( P2CALL , P2INT );
117764Speter 			return (nl+T4INT);
118764Speter 		case O_EOF:
119764Speter 		case O_EOLN:
120764Speter 			if (argc == 0) {
121*14738Sthien 				argv = &(tr);
122*14738Sthien 				tr.list_node.list = &(tr2);
123*14738Sthien 				tr2.tag = T_VAR;
124*14738Sthien 				tr2.var_node.cptr = input->symbol;
125*14738Sthien 				tr2.var_node.line_no = NIL;
126*14738Sthien 				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);
131*14738Sthien 				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);
141*14738Sthien 		return (NLNIL);
142764Speter 	}
143764Speter 	/*
144764Speter 	 * find out the type of the argument
145764Speter 	 */
146764Speter 	codeoff();
147*14738Sthien 	p1 = stkrval( argv->list_node.list, NLNIL , (long) RREQ );
148764Speter 	codeon();
149*14738Sthien 	if (p1 == NLNIL)
150*14738Sthien 		return (NLNIL);
151764Speter 	/*
152764Speter 	 * figure out the return type and the funtion name
153764Speter 	 */
154764Speter 	switch (op) {
155*14738Sthien 	    case 0:
156*14738Sthien 			error("%s is an unimplemented 6000-3.4 extension", p->symbol);
157*14738Sthien 	    default:
158*14738Sthien 			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));
183*14738Sthien 			    return (NLNIL);
184764Speter 		    }
185764Speter 		    putleaf( P2ICON , 0 , 0
186764Speter 			    , ADDTYPE( P2FTN | P2DOUBLE , P2PTR ) , funcname );
187*14738Sthien 		    p1 = stkrval(  argv->list_node.list , NLNIL , (long) RREQ );
18810376Speter 		    sconv(p2type(p1), P2DOUBLE);
189764Speter 		    putop( P2CALL , P2DOUBLE );
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 		    }
196764Speter 		    putleaf( P2ICON , 0 , 0
197764Speter 			    , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_EXPO" );
198*14738Sthien 		    p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ );
19910376Speter 		    sconv(p2type(p1), P2DOUBLE);
200764Speter 		    putop( P2CALL , P2INT );
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));
205*14738Sthien 			    return NLNIL;
206764Speter 		    }
207*14738Sthien 		    p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ );
208*14738Sthien 		    putleaf( P2ICON , 0 , 0 , P2CHAR , (char *) 0 );
20910669Speter 		    putop( P2COMOP , P2CHAR );
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));
214*14738Sthien 			    return (NLNIL);
215764Speter 		    }
216764Speter 		    putleaf( P2ICON , 0 , 0
217764Speter 			    , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_SEED" );
218*14738Sthien 		    p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ );
219764Speter 		    putop( P2CALL , P2INT );
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));
225*14738Sthien 			    return (NLNIL);
226764Speter 		    }
227764Speter 		    putleaf( P2ICON , 0 , 0
228764Speter 			    , ADDTYPE( P2FTN | P2INT , P2PTR )
229764Speter 			    , op == O_ROUND ? "_ROUND" : "_TRUNC" );
230*14738Sthien 		    p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ );
231764Speter 		    putop( P2CALL , P2INT );
232764Speter 		    return nl + T4INT;
233764Speter 	    case O_ABS2:
234764Speter 			if ( isa( p1 , "d" ) ) {
235764Speter 			    putleaf( P2ICON , 0 , 0
236764Speter 				, ADDTYPE( P2FTN | P2DOUBLE , P2PTR )
237764Speter 				, "_fabs" );
238*14738Sthien 			    p1 = stkrval( argv->list_node.list , NLNIL ,(long) RREQ );
239764Speter 			    putop( P2CALL , P2DOUBLE );
240764Speter 			    return nl + TDOUBLE;
241764Speter 			}
242764Speter 			if ( isa( p1 , "i" ) ) {
243764Speter 			    putleaf( P2ICON , 0 , 0
244764Speter 				, ADDTYPE( P2FTN | P2INT , P2PTR ) , "_abs" );
245*14738Sthien 			    p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ );
246764Speter 			    putop( P2CALL , P2INT );
247764Speter 			    return nl + T4INT;
248764Speter 			}
249764Speter 			error("%s's argument must be an integer or real, not %s", p->symbol, nameof(p1));
250*14738Sthien 			return NLNIL;
251764Speter 	    case O_SQR2:
252764Speter 			if ( isa( p1 , "d" ) ) {
253764Speter 			    temptype = P2DOUBLE;
254764Speter 			    rettype = nl + TDOUBLE;
255*14738Sthien 			    tempnlp = tmpalloc((long) (sizeof(double)), rettype, REGOK);
256764Speter 			} else if ( isa( p1 , "i" ) ) {
257764Speter 			    temptype = P2INT;
258764Speter 			    rettype = nl + T4INT;
259*14738Sthien 			    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));
262*14738Sthien 			    return NLNIL;
263764Speter 			}
264*14738Sthien 			putRV( (char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] ,
265*14738Sthien 				tempnlp -> extra_flags , (char) temptype  );
266*14738Sthien 			p1 = rvalue( argv->list_node.list , NLNIL , RREQ );
267*14738Sthien 			sconv(p2type(p1), (int) temptype);
268*14738Sthien 			putop( P2ASSIGN , (int) temptype );
269*14738Sthien 			putRV((char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] ,
270*14738Sthien 				tempnlp -> extra_flags , (char) temptype );
271*14738Sthien 			putRV((char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] ,
272*14738Sthien 				tempnlp -> extra_flags , (char) temptype );
273*14738Sthien 			putop( P2MUL , (int) temptype );
274*14738Sthien 			putop( P2COMOP , (int) temptype );
275764Speter 			return rettype;
276764Speter 	    case O_ORD2:
277*14738Sthien 			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));
289*14738Sthien 			return (NLNIL);
290764Speter 	    case O_SUCC2:
291764Speter 	    case O_PRED2:
292764Speter 			if (isa(p1, "d")) {
293764Speter 				error("%s is forbidden for reals", p->symbol);
294*14738Sthien 				return (NLNIL);
295764Speter 			}
296764Speter 			if ( isnta( p1 , "bcsi" ) ) {
297764Speter 			    error("%s's argument must be of scalar type, not %s", p->symbol, nameof(p1));
298*14738Sthien 			    return NLNIL;
299764Speter 			}
300764Speter 			if ( opt( 't' ) ) {
301764Speter 			    putleaf( P2ICON , 0 , 0
302764Speter 				    , ADDTYPE( P2FTN | P2INT , P2PTR )
303764Speter 				    , op == O_SUCC2 ? "_SUCC" : "_PRED" );
304*14738Sthien 			    p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ );
3056596Smckusick 			    tempnlp = p1 -> class == TYPE ? p1 -> type : p1;
306*14738Sthien 			    putleaf( P2ICON, (int) tempnlp -> range[0], 0, P2INT, (char *) 0 );
307764Speter 			    putop( P2LISTOP , P2INT );
308*14738Sthien 			    putleaf( P2ICON, (int) tempnlp -> range[1], 0, P2INT, (char *) 0 );
309764Speter 			    putop( P2LISTOP , P2INT );
310764Speter 			    putop( P2CALL , P2INT );
31110669Speter 			    sconv(P2INT, p2type(p1));
312764Speter 			} else {
313*14738Sthien 			    p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ );
314*14738Sthien 			    putleaf( P2ICON , 1 , 0 , P2INT , (char *) 0 );
315764Speter 			    putop( op == O_SUCC2 ? P2PLUS : P2MINUS , P2INT );
31610669Speter 			    sconv(P2INT, 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));
326*14738Sthien 				return (NLNIL);
327764Speter 			}
328*14738Sthien 			p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ );
32910669Speter 			    /*
33010669Speter 			     *	THIS IS MACHINE-DEPENDENT!!!
33110669Speter 			     */
332*14738Sthien 			putleaf( P2ICON , 1 , 0 , P2INT , (char *) 0 );
333764Speter 			putop( P2AND , P2INT );
33410669Speter 			sconv(P2INT, P2CHAR);
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));
339*14738Sthien 				return (NLNIL);
340764Speter 			}
341764Speter 			if (opt('t')) {
342764Speter 			    putleaf( P2ICON , 0 , 0
343764Speter 				, ADDTYPE( P2FTN | P2CHAR , P2PTR ) , "_CHR" );
344*14738Sthien 			    p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ );
345764Speter 			    putop( P2CALL , P2CHAR );
346764Speter 			} else {
347*14738Sthien 			    p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ );
34810669Speter 			    sconv(P2INT, P2CHAR);
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));
354*14738Sthien 			    return (NLNIL);
355764Speter 			}
3561554Speter 			putleaf( P2ICON , 0 , 0
3571554Speter 			    , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_CARD" );
358*14738Sthien 			p1 = stkrval( argv->list_node.list , NLNIL , (long) LREQ );
359*14738Sthien 			putleaf( P2ICON , (int) lwidth( p1 ) , 0 , P2INT , (char *) 0 );
3601554Speter 			putop( P2LISTOP , P2INT );
3611554Speter 			putop( P2CALL , P2INT );
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));
366*14738Sthien 				return (NLNIL);
367764Speter 			}
368764Speter 			putleaf( P2ICON , 0 , 0
369764Speter 			    , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_TEOLN" );
370*14738Sthien 			p1 = stklval( argv->list_node.list , NOFLAGS );
371764Speter 			putop( P2CALL , P2INT );
37210669Speter 			sconv(P2INT, P2CHAR);
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));
377*14738Sthien 				return (NLNIL);
378764Speter 			}
379764Speter 			putleaf( P2ICON , 0 , 0
380764Speter 			    , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_TEOF" );
381*14738Sthien 			p1 = stklval( argv->list_node.list , NOFLAGS );
382764Speter 			putop( P2CALL , P2INT );
38310669Speter 			sconv(P2INT, P2CHAR);
384764Speter 			return nl + TBOOL;
385764Speter 	}
386764Speter }
387764Speter #endif PC
388