xref: /csrg-svn/usr.bin/pascal/src/pcfunc.c (revision 10669)
1764Speter /* Copyright (c) 1979 Regents of the University of California */
2764Speter 
3*10669Speter static	char sccsid[] = "@(#)pcfunc.c 1.12 02/01/83";
4764Speter 
5764Speter #include "whoami.h"
6764Speter #ifdef PC
7764Speter     /*
8764Speter      *	and to the end of the file
9764Speter      */
10764Speter #include "0.h"
11764Speter #include "tree.h"
1210375Speter #include "objfmt.h"
13764Speter #include "opcode.h"
1410375Speter #include "pc.h"
1510375Speter #include "pcops.h"
16764Speter 
17764Speter /*
18764Speter  * Funccod generates code for
19764Speter  * built in function calls and calls
20764Speter  * call to generate calls to user
21764Speter  * defined functions and procedures.
22764Speter  */
23764Speter pcfunccod( r )
24764Speter 	int	 *r;
25764Speter {
26764Speter 	struct nl *p;
27764Speter 	register struct nl *p1;
28764Speter 	register int *al;
29764Speter 	register op;
30764Speter 	int argc, *argv;
31764Speter 	int tr[2], tr2[4];
32764Speter 	char		*funcname;
333831Speter 	struct nl	*tempnlp;
34764Speter 	long		temptype;
35764Speter 	struct nl	*rettype;
36764Speter 
37764Speter 	/*
38764Speter 	 * Verify that the given name
39764Speter 	 * is defined and the name of
40764Speter 	 * a function.
41764Speter 	 */
42764Speter 	p = lookup(r[2]);
43764Speter 	if (p == NIL) {
44764Speter 		rvlist(r[3]);
45764Speter 		return (NIL);
46764Speter 	}
471197Speter 	if (p->class != FUNC && p->class != FFUNC) {
48764Speter 		error("%s is not a function", p->symbol);
49764Speter 		rvlist(r[3]);
50764Speter 		return (NIL);
51764Speter 	}
52764Speter 	argv = r[3];
53764Speter 	/*
54764Speter 	 * Call handles user defined
55764Speter 	 * procedures and functions
56764Speter 	 */
57764Speter 	if (bn != 0)
58764Speter 		return (call(p, argv, FUNC, bn));
59764Speter 	/*
60764Speter 	 * Count the arguments
61764Speter 	 */
62764Speter 	argc = 0;
63764Speter 	for (al = argv; al != NIL; al = al[2])
64764Speter 		argc++;
65764Speter 	/*
66764Speter 	 * Built-in functions have
67764Speter 	 * their interpreter opcode
68764Speter 	 * associated with them.
69764Speter 	 */
70764Speter 	op = p->value[0] &~ NSTAND;
71764Speter 	if (opt('s') && (p->value[0] & NSTAND)) {
72764Speter 		standard();
73764Speter 		error("%s is a nonstandard function", p->symbol);
74764Speter 	}
75764Speter 	if ( op == O_ARGC ) {
76764Speter 	    putleaf( P2NAME , 0 , 0 , P2INT , "__argc" );
77764Speter 	    return nl + T4INT;
78764Speter 	}
79764Speter 	switch (op) {
80764Speter 		/*
81764Speter 		 * Parameterless functions
82764Speter 		 */
83764Speter 		case O_CLCK:
84764Speter 			funcname = "_CLCK";
85764Speter 			goto noargs;
86764Speter 		case O_SCLCK:
87764Speter 			funcname = "_SCLCK";
88764Speter 			goto noargs;
89764Speter noargs:
90764Speter 			if (argc != 0) {
91764Speter 				error("%s takes no arguments", p->symbol);
92764Speter 				rvlist(argv);
93764Speter 				return (NIL);
94764Speter 			}
95764Speter 			putleaf( P2ICON , 0 , 0
96764Speter 				, ADDTYPE( P2FTN | P2INT , P2PTR )
97764Speter 				, funcname );
98764Speter 			putop( P2UNARY P2CALL , P2INT );
99764Speter 			return (nl+T4INT);
100764Speter 		case O_WCLCK:
101764Speter 			if (argc != 0) {
102764Speter 				error("%s takes no arguments", p->symbol);
103764Speter 				rvlist(argv);
104764Speter 				return (NIL);
105764Speter 			}
106764Speter 			putleaf( P2ICON , 0 , 0
107764Speter 				, ADDTYPE( P2FTN | P2INT , P2PTR )
108764Speter 				, "_time" );
109764Speter 			putleaf( P2ICON , 0 , 0 , P2INT , 0 );
110764Speter 			putop( P2CALL , P2INT );
111764Speter 			return (nl+T4INT);
112764Speter 		case O_EOF:
113764Speter 		case O_EOLN:
114764Speter 			if (argc == 0) {
115764Speter 				argv = tr;
116764Speter 				tr[1] = tr2;
117764Speter 				tr2[0] = T_VAR;
118764Speter 				tr2[2] = input->symbol;
119764Speter 				tr2[1] = tr2[3] = NIL;
120764Speter 				argc = 1;
121764Speter 			} else if (argc != 1) {
122764Speter 				error("%s takes either zero or one argument", p->symbol);
123764Speter 				rvlist(argv);
124764Speter 				return (NIL);
125764Speter 			}
126764Speter 		}
127764Speter 	/*
128764Speter 	 * All other functions take
129764Speter 	 * exactly one argument.
130764Speter 	 */
131764Speter 	if (argc != 1) {
132764Speter 		error("%s takes exactly one argument", p->symbol);
133764Speter 		rvlist(argv);
134764Speter 		return (NIL);
135764Speter 	}
136764Speter 	/*
137764Speter 	 * find out the type of the argument
138764Speter 	 */
139764Speter 	codeoff();
140764Speter 	p1 = stkrval((int *) argv[1], NLNIL , RREQ );
141764Speter 	codeon();
142764Speter 	if (p1 == NIL)
143764Speter 		return (NIL);
144764Speter 	/*
145764Speter 	 * figure out the return type and the funtion name
146764Speter 	 */
147764Speter 	switch (op) {
148764Speter 	    case O_EXP:
1495715Smckusic 		    funcname = opt('t') ? "_EXP" : "_exp";
150764Speter 		    goto mathfunc;
151764Speter 	    case O_SIN:
1525715Smckusic 		    funcname = opt('t') ? "_SIN" : "_sin";
153764Speter 		    goto mathfunc;
154764Speter 	    case O_COS:
1555715Smckusic 		    funcname = opt('t') ? "_COS" : "_cos";
156764Speter 		    goto mathfunc;
157764Speter 	    case O_ATAN:
1585715Smckusic 		    funcname = opt('t') ? "_ATAN" : "_atan";
159764Speter 		    goto mathfunc;
160764Speter 	    case O_LN:
161764Speter 		    funcname = opt('t') ? "_LN" : "_log";
162764Speter 		    goto mathfunc;
163764Speter 	    case O_SQRT:
164764Speter 		    funcname = opt('t') ? "_SQRT" : "_sqrt";
165764Speter 		    goto mathfunc;
166764Speter 	    case O_RANDOM:
167764Speter 		    funcname = "_RANDOM";
168764Speter 		    goto mathfunc;
169764Speter mathfunc:
170764Speter 		    if (isnta(p1, "id")) {
171764Speter 			    error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1));
172764Speter 			    return (NIL);
173764Speter 		    }
174764Speter 		    putleaf( P2ICON , 0 , 0
175764Speter 			    , ADDTYPE( P2FTN | P2DOUBLE , P2PTR ) , funcname );
176764Speter 		    p1 = stkrval( (int *) argv[1] , NLNIL , RREQ );
17710376Speter 		    sconv(p2type(p1), P2DOUBLE);
178764Speter 		    putop( P2CALL , P2DOUBLE );
179764Speter 		    return nl + TDOUBLE;
180764Speter 	    case O_EXPO:
181764Speter 		    if (isnta( p1 , "id" ) ) {
182764Speter 			    error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1));
183764Speter 			    return NIL;
184764Speter 		    }
185764Speter 		    putleaf( P2ICON , 0 , 0
186764Speter 			    , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_EXPO" );
187764Speter 		    p1 = stkrval( (int *) argv[1] , NLNIL , RREQ );
18810376Speter 		    sconv(p2type(p1), P2DOUBLE);
189764Speter 		    putop( P2CALL , P2INT );
190764Speter 		    return ( nl + T4INT );
191764Speter 	    case O_UNDEF:
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 		    p1 = stkrval( (int *) argv[1] , NLNIL , RREQ );
197*10669Speter 		    putleaf( P2ICON , 0 , 0 , P2CHAR , 0 );
198*10669Speter 		    putop( P2COMOP , P2CHAR );
199764Speter 		    return ( nl + TBOOL );
200764Speter 	    case O_SEED:
201764Speter 		    if (isnta(p1, "i")) {
202764Speter 			    error("seed's argument must be an integer, not %s", nameof(p1));
203764Speter 			    return (NIL);
204764Speter 		    }
205764Speter 		    putleaf( P2ICON , 0 , 0
206764Speter 			    , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_SEED" );
207764Speter 		    p1 = stkrval( (int *) argv[1] , NLNIL , RREQ );
208764Speter 		    putop( P2CALL , P2INT );
209764Speter 		    return nl + T4INT;
210764Speter 	    case O_ROUND:
211764Speter 	    case O_TRUNC:
212764Speter 		    if ( isnta( p1 , "d" ) ) {
213764Speter 			    error("%s's argument must be a real, not %s", p->symbol, nameof(p1));
214764Speter 			    return (NIL);
215764Speter 		    }
216764Speter 		    putleaf( P2ICON , 0 , 0
217764Speter 			    , ADDTYPE( P2FTN | P2INT , P2PTR )
218764Speter 			    , op == O_ROUND ? "_ROUND" : "_TRUNC" );
219764Speter 		    p1 = stkrval( (int *) argv[1] , NLNIL , RREQ );
220764Speter 		    putop( P2CALL , P2INT );
221764Speter 		    return nl + T4INT;
222764Speter 	    case O_ABS2:
223764Speter 			if ( isa( p1 , "d" ) ) {
224764Speter 			    putleaf( P2ICON , 0 , 0
225764Speter 				, ADDTYPE( P2FTN | P2DOUBLE , P2PTR )
226764Speter 				, "_fabs" );
227764Speter 			    p1 = stkrval( (int *) argv[1] , NLNIL , RREQ );
228764Speter 			    putop( P2CALL , P2DOUBLE );
229764Speter 			    return nl + TDOUBLE;
230764Speter 			}
231764Speter 			if ( isa( p1 , "i" ) ) {
232764Speter 			    putleaf( P2ICON , 0 , 0
233764Speter 				, ADDTYPE( P2FTN | P2INT , P2PTR ) , "_abs" );
234764Speter 			    p1 = stkrval( (int *) argv[1] , NLNIL , RREQ );
235764Speter 			    putop( P2CALL , P2INT );
236764Speter 			    return nl + T4INT;
237764Speter 			}
238764Speter 			error("%s's argument must be an integer or real, not %s", p->symbol, nameof(p1));
239764Speter 			return NIL;
240764Speter 	    case O_SQR2:
241764Speter 			if ( isa( p1 , "d" ) ) {
242764Speter 			    temptype = P2DOUBLE;
243764Speter 			    rettype = nl + TDOUBLE;
2443831Speter 			    tempnlp = tmpalloc(sizeof(double), rettype, REGOK);
245764Speter 			} else if ( isa( p1 , "i" ) ) {
246764Speter 			    temptype = P2INT;
247764Speter 			    rettype = nl + T4INT;
2483831Speter 			    tempnlp = tmpalloc(sizeof(long), rettype, REGOK);
249764Speter 			} else {
250764Speter 			    error("%s's argument must be an integer or real, not %s", p->symbol, nameof(p1));
251764Speter 			    return NIL;
252764Speter 			}
2533831Speter 			putRV( 0 , cbn , tempnlp -> value[ NL_OFFS ] ,
2543831Speter 				tempnlp -> extra_flags , temptype , 0 );
255764Speter 			p1 = rvalue( (int *) argv[1] , NLNIL , RREQ );
25610376Speter 			sconv(p2type(p1), temptype);
257764Speter 			putop( P2ASSIGN , temptype );
2583831Speter 			putRV( 0 , cbn , tempnlp -> value[ NL_OFFS ] ,
2593831Speter 				tempnlp -> extra_flags , temptype , 0 );
2603831Speter 			putRV( 0 , cbn , tempnlp -> value[ NL_OFFS ] ,
2613831Speter 				tempnlp -> extra_flags , temptype , 0 );
262764Speter 			putop( P2MUL , temptype );
263764Speter 			putop( P2COMOP , temptype );
264764Speter 			return rettype;
265764Speter 	    case O_ORD2:
266764Speter 			p1 = stkrval( (int *) argv[1] , NLNIL , RREQ );
2679573Speter 			if (isa(p1, "bcis")) {
268764Speter 				return (nl+T4INT);
269764Speter 			}
2709573Speter 			if (classify(p1) == TPTR) {
2719573Speter 			    if (!opt('s')) {
2729573Speter 				return (nl+T4INT);
2739573Speter 			    }
2749573Speter 			    standard();
2759573Speter 			}
2769573Speter 			error("ord's argument must be of scalar type, not %s",
2779573Speter 				nameof(p1));
278764Speter 			return (NIL);
279764Speter 	    case O_SUCC2:
280764Speter 	    case O_PRED2:
281764Speter 			if (isa(p1, "d")) {
282764Speter 				error("%s is forbidden for reals", p->symbol);
283764Speter 				return (NIL);
284764Speter 			}
285764Speter 			if ( isnta( p1 , "bcsi" ) ) {
286764Speter 			    error("%s's argument must be of scalar type, not %s", p->symbol, nameof(p1));
287764Speter 			    return NIL;
288764Speter 			}
289764Speter 			if ( opt( 't' ) ) {
290764Speter 			    putleaf( P2ICON , 0 , 0
291764Speter 				    , ADDTYPE( P2FTN | P2INT , P2PTR )
292764Speter 				    , op == O_SUCC2 ? "_SUCC" : "_PRED" );
293764Speter 			    p1 = stkrval( (int *) argv[1] , NLNIL , RREQ );
2946596Smckusick 			    tempnlp = p1 -> class == TYPE ? p1 -> type : p1;
2956596Smckusick 			    putleaf( P2ICON, tempnlp -> range[0], 0, P2INT, 0 );
296764Speter 			    putop( P2LISTOP , P2INT );
2976596Smckusick 			    putleaf( P2ICON, tempnlp -> range[1], 0, P2INT, 0 );
298764Speter 			    putop( P2LISTOP , P2INT );
299764Speter 			    putop( P2CALL , P2INT );
300*10669Speter 			    sconv(P2INT, p2type(p1));
301764Speter 			} else {
302*10669Speter 			    p1 = stkrval( (int *) argv[1] , NLNIL , RREQ );
303764Speter 			    putleaf( P2ICON , 1 , 0 , P2INT , 0 );
304764Speter 			    putop( op == O_SUCC2 ? P2PLUS : P2MINUS , P2INT );
305*10669Speter 			    sconv(P2INT, p2type(p1));
306764Speter 			}
307764Speter 			if ( isa( p1 , "bcs" ) ) {
308764Speter 			    return p1;
309764Speter 			} else {
310764Speter 			    return nl + T4INT;
311764Speter 			}
312764Speter 	    case O_ODD2:
313764Speter 			if (isnta(p1, "i")) {
314764Speter 				error("odd's argument must be an integer, not %s", nameof(p1));
315764Speter 				return (NIL);
316764Speter 			}
317*10669Speter 			p1 = stkrval( (int *) argv[1] , NLNIL , RREQ );
318*10669Speter 			    /*
319*10669Speter 			     *	THIS IS MACHINE-DEPENDENT!!!
320*10669Speter 			     */
321764Speter 			putleaf( P2ICON , 1 , 0 , P2INT , 0 );
322764Speter 			putop( P2AND , P2INT );
323*10669Speter 			sconv(P2INT, P2CHAR);
324764Speter 			return nl + TBOOL;
325764Speter 	    case O_CHR2:
326764Speter 			if (isnta(p1, "i")) {
327764Speter 				error("chr's argument must be an integer, not %s", nameof(p1));
328764Speter 				return (NIL);
329764Speter 			}
330764Speter 			if (opt('t')) {
331764Speter 			    putleaf( P2ICON , 0 , 0
332764Speter 				, ADDTYPE( P2FTN | P2CHAR , P2PTR ) , "_CHR" );
333764Speter 			    p1 = stkrval( (int *) argv[1] , NLNIL , RREQ );
334764Speter 			    putop( P2CALL , P2CHAR );
335764Speter 			} else {
336764Speter 			    p1 = stkrval( (int *) argv[1] , NLNIL , RREQ );
337*10669Speter 			    sconv(P2INT, P2CHAR);
338764Speter 			}
339764Speter 			return nl + TCHAR;
340764Speter 	    case O_CARD:
3411554Speter 			if (isnta(p1, "t")) {
3421554Speter 			    error("Argument to card must be a set, not %s", nameof(p1));
3431554Speter 			    return (NIL);
344764Speter 			}
3451554Speter 			putleaf( P2ICON , 0 , 0
3461554Speter 			    , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_CARD" );
3471554Speter 			p1 = stkrval( (int *) argv[1] , NLNIL , LREQ );
3481554Speter 			putleaf( P2ICON , lwidth( p1 ) , 0 , P2INT , 0 );
3491554Speter 			putop( P2LISTOP , P2INT );
3501554Speter 			putop( P2CALL , P2INT );
351*10669Speter 			return nl + T4INT;
352764Speter 	    case O_EOLN:
353764Speter 			if (!text(p1)) {
354764Speter 				error("Argument to eoln must be a text file, not %s", nameof(p1));
355764Speter 				return (NIL);
356764Speter 			}
357764Speter 			putleaf( P2ICON , 0 , 0
358764Speter 			    , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_TEOLN" );
359764Speter 			p1 = stklval( (int *) argv[1] , NOFLAGS );
360764Speter 			putop( P2CALL , P2INT );
361*10669Speter 			sconv(P2INT, P2CHAR);
362764Speter 			return nl + TBOOL;
363764Speter 	    case O_EOF:
364764Speter 			if (p1->class != FILET) {
365764Speter 				error("Argument to eof must be file, not %s", nameof(p1));
366764Speter 				return (NIL);
367764Speter 			}
368764Speter 			putleaf( P2ICON , 0 , 0
369764Speter 			    , ADDTYPE( P2FTN | P2INT , P2PTR ) , "_TEOF" );
370764Speter 			p1 = stklval( (int *) argv[1] , NOFLAGS );
371764Speter 			putop( P2CALL , P2INT );
372*10669Speter 			sconv(P2INT, P2CHAR);
373764Speter 			return nl + TBOOL;
374764Speter 	    case 0:
375764Speter 			error("%s is an unimplemented 6000-3.4 extension", p->symbol);
376764Speter 	    default:
377764Speter 			panic("func1");
378764Speter 	}
379764Speter }
380764Speter #endif PC
381