xref: /csrg-svn/usr.bin/pascal/src/func.c (revision 62213)
148116Sbostic /*-
2*62213Sbostic  * Copyright (c) 1980, 1993
3*62213Sbostic  *	The Regents of the University of California.  All rights reserved.
448116Sbostic  *
548116Sbostic  * %sccs.include.redist.c%
622168Sdist  */
7753Speter 
814733Sthien #ifndef lint
9*62213Sbostic static char sccsid[] = "@(#)func.c	8.1 (Berkeley) 06/06/93";
1048116Sbostic #endif /* not lint */
11753Speter 
12753Speter #include "whoami.h"
13753Speter #ifdef OBJ
14753Speter     /*
15753Speter      *	the rest of the file
16753Speter      */
17753Speter #include "0.h"
18753Speter #include "tree.h"
19753Speter #include "opcode.h"
2014733Sthien #include "tree_ty.h"
21753Speter 
22753Speter /*
23753Speter  * Funccod generates code for
24753Speter  * built in function calls and calls
25753Speter  * call to generate calls to user
26753Speter  * defined functions and procedures.
27753Speter  */
2814733Sthien struct nl
funccod(r)2914733Sthien *funccod(r)
3014733Sthien 	struct tnode *r;
31753Speter {
32753Speter 	struct nl *p;
33753Speter 	register struct nl *p1;
346595Smckusick 	struct nl *tempnlp;
3514733Sthien 	register struct tnode *al;
36753Speter 	register op;
3714733Sthien 	int argc;
3814733Sthien 	struct tnode *argv, tr, tr2;
39753Speter 
40753Speter 	/*
41753Speter 	 * Verify that the given name
42753Speter 	 * is defined and the name of
43753Speter 	 * a function.
44753Speter 	 */
4514733Sthien 	p = lookup(r->pcall_node.proc_id);
4614733Sthien 	if (p == NLNIL) {
4714733Sthien 		rvlist(r->pcall_node.arg);
4814733Sthien 		return (NLNIL);
49753Speter 	}
501197Speter 	if (p->class != FUNC && p->class != FFUNC) {
51753Speter 		error("%s is not a function", p->symbol);
5214733Sthien 		rvlist(r->pcall_node.arg);
5314733Sthien 		return (NLNIL);
54753Speter 	}
5514733Sthien 	argv = r->pcall_node.arg;
56753Speter 	/*
57753Speter 	 * Call handles user defined
58753Speter 	 * procedures and functions
59753Speter 	 */
60753Speter 	if (bn != 0)
61753Speter 		return (call(p, argv, FUNC, bn));
62753Speter 	/*
63753Speter 	 * Count the arguments
64753Speter 	 */
65753Speter 	argc = 0;
6614733Sthien 	for (al = argv; al != TR_NIL; al = al->list_node.next)
67753Speter 		argc++;
68753Speter 	/*
69753Speter 	 * Built-in functions have
70753Speter 	 * their interpreter opcode
71753Speter 	 * associated with them.
72753Speter 	 */
73753Speter 	op = p->value[0] &~ NSTAND;
74753Speter 	if (opt('s') && (p->value[0] & NSTAND)) {
75753Speter 		standard();
76753Speter 		error("%s is a nonstandard function", p->symbol);
77753Speter 	}
78753Speter 	switch (op) {
79753Speter 		/*
80753Speter 		 * Parameterless functions
81753Speter 		 */
82753Speter 		case O_CLCK:
83753Speter 		case O_SCLCK:
84753Speter 		case O_WCLCK:
85753Speter 		case O_ARGC:
86753Speter 			if (argc != 0) {
87753Speter 				error("%s takes no arguments", p->symbol);
88753Speter 				rvlist(argv);
8914733Sthien 				return (NLNIL);
90753Speter 			}
9114733Sthien 			(void) put(1, op);
92753Speter 			return (nl+T4INT);
93753Speter 		case O_EOF:
94753Speter 		case O_EOLN:
95753Speter 			if (argc == 0) {
9614733Sthien 				argv = (&tr);
9714733Sthien 				tr.list_node.list = (&tr2);
9814733Sthien 				tr2.tag = T_VAR;
9914733Sthien 				tr2.var_node.cptr = input->symbol;
10014733Sthien 				tr2.var_node.line_no = NIL;
10114733Sthien 				tr2.var_node.qual = TR_NIL;
102753Speter 				argc = 1;
103753Speter 			} else if (argc != 1) {
104753Speter 				error("%s takes either zero or one argument", p->symbol);
105753Speter 				rvlist(argv);
10614733Sthien 				return (NLNIL);
107753Speter 			}
108753Speter 		}
109753Speter 	/*
110753Speter 	 * All other functions take
111753Speter 	 * exactly one argument.
112753Speter 	 */
113753Speter 	if (argc != 1) {
114753Speter 		error("%s takes exactly one argument", p->symbol);
115753Speter 		rvlist(argv);
11614733Sthien 		return (NLNIL);
117753Speter 	}
118753Speter 	/*
119753Speter 	 * Evaluate the argmument
120753Speter 	 */
1212070Smckusic 	if (op == O_EOF || op == O_EOLN)
12214733Sthien 		p1 = stklval(argv->list_node.list, NIL );
1232070Smckusic 	else
12414733Sthien 		p1 = stkrval(argv->list_node.list, NLNIL , (long) RREQ );
12514733Sthien 	if (p1 == NLNIL)
12614733Sthien 		return (NLNIL);
127753Speter 	switch (op) {
12814733Sthien 		case 0:
12914733Sthien 			error("%s is an unimplemented 6000-3.4 extension", p->symbol);
13014733Sthien 		default:
13114733Sthien 			panic("func1");
132753Speter 		case O_EXP:
133753Speter 		case O_SIN:
134753Speter 		case O_COS:
135753Speter 		case O_ATAN:
136753Speter 		case O_LN:
137753Speter 		case O_SQRT:
138753Speter 		case O_RANDOM:
139753Speter 		case O_EXPO:
140753Speter 		case O_UNDEF:
141753Speter 			if (isa(p1, "i"))
1422537Speter 				convert( nl+T4INT , nl+TDOUBLE);
143753Speter 			else if (isnta(p1, "d")) {
144753Speter 				error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1));
14514733Sthien 				return (NLNIL);
146753Speter 			}
14714733Sthien 			(void) put(1, op);
148753Speter 			if (op == O_UNDEF)
149753Speter 				return (nl+TBOOL);
150753Speter 			else if (op == O_EXPO)
151753Speter 				return (nl+T4INT);
152753Speter 			else
153753Speter 				return (nl+TDOUBLE);
154753Speter 		case O_SEED:
155753Speter 			if (isnta(p1, "i")) {
156753Speter 				error("seed's argument must be an integer, not %s", nameof(p1));
15714733Sthien 				return (NLNIL);
158753Speter 			}
15914733Sthien 			(void) put(1, op);
160753Speter 			return (nl+T4INT);
161753Speter 		case O_ROUND:
162753Speter 		case O_TRUNC:
163753Speter 			if (isnta(p1, "d"))  {
164753Speter 				error("%s's argument must be a real, not %s", p->symbol, nameof(p1));
16514733Sthien 				return (NLNIL);
166753Speter 			}
16714733Sthien 			(void) put(1, op);
168753Speter 			return (nl+T4INT);
169753Speter 		case O_ABS2:
170753Speter 		case O_SQR2:
171753Speter 			if (isa(p1, "d")) {
17214733Sthien 				(void) put(1, op + O_ABS8-O_ABS2);
173753Speter 				return (nl+TDOUBLE);
174753Speter 			}
175753Speter 			if (isa(p1, "i")) {
17614733Sthien 				(void) put(1, op + (width(p1) >> 2));
177753Speter 				return (nl+T4INT);
178753Speter 			}
179753Speter 			error("%s's argument must be an integer or real, not %s", p->symbol, nameof(p1));
18014733Sthien 			return (NLNIL);
181753Speter 		case O_ORD2:
1829573Speter 			if (isa(p1, "bcis")) {
183753Speter 				return (nl+T4INT);
184753Speter 			}
1859573Speter 			if (classify(p1) == TPTR) {
1869573Speter 			    if (!opt('s')) {
1879573Speter 				return (nl+T4INT);
1889573Speter 			    }
1899573Speter 			    standard();
1909573Speter 			}
1919573Speter 			error("ord's argument must be of scalar type, not %s",
1929573Speter 				nameof(p1));
19314733Sthien 			return (NLNIL);
194753Speter 		case O_SUCC2:
195753Speter 		case O_PRED2:
1962104Smckusic 			if (isa(p1, "d")) {
1972104Smckusic 				error("%s is forbidden for reals", p->symbol);
19814733Sthien 				return (NLNIL);
199753Speter 			}
2002104Smckusic 			if ( isnta( p1 , "bcsi" ) ) {
2012104Smckusic 				error("%s's argument must be of scalar type, not %s", p->symbol, nameof(p1));
2022104Smckusic 				return NIL;
2032104Smckusic 			}
2046595Smckusick 			tempnlp = p1 -> class == TYPE ? p1 -> type : p1;
205753Speter 			if (isa(p1, "i")) {
2063074Smckusic 				if (width(p1) <= 2) {
2072104Smckusic 					op += O_PRED24 - O_PRED2;
20814733Sthien 					(void) put(3, op, (int)tempnlp->range[0],
2096595Smckusick 						(int)tempnlp->range[1]);
2103074Smckusic 				} else {
211753Speter 					op++;
21214733Sthien 					(void) put(3, op, tempnlp->range[0],
2136595Smckusick 						tempnlp->range[1]);
2143074Smckusic 				}
2152104Smckusic 				return nl + T4INT;
2162104Smckusic 			} else {
21714733Sthien 				(void) put(3, op, (int)tempnlp->range[0],
2186595Smckusick 					(int)tempnlp->range[1]);
2192104Smckusic 				return p1;
220753Speter 			}
221753Speter 		case O_ODD2:
222753Speter 			if (isnta(p1, "i")) {
223753Speter 				error("odd's argument must be an integer, not %s", nameof(p1));
22414733Sthien 				return (NLNIL);
225753Speter 			}
22614733Sthien 			(void) put(1, op + (width(p1) >> 2));
227753Speter 			return (nl+TBOOL);
228753Speter 		case O_CHR2:
229753Speter 			if (isnta(p1, "i")) {
230753Speter 				error("chr's argument must be an integer, not %s", nameof(p1));
23114733Sthien 				return (NLNIL);
232753Speter 			}
23314733Sthien 			(void) put(1, op + (width(p1) >> 2));
234753Speter 			return (nl+TCHAR);
235753Speter 		case O_CARD:
2361553Speter 			if (isnta(p1, "t")) {
2371553Speter 			    error("Argument to card must be a set, not %s", nameof(p1));
23814733Sthien 			    return (NLNIL);
239753Speter 			}
24014733Sthien 			(void) put(2, O_CARD, width(p1));
241753Speter 			return (nl+T2INT);
242753Speter 		case O_EOLN:
243753Speter 			if (!text(p1)) {
244753Speter 				error("Argument to eoln must be a text file, not %s", nameof(p1));
24514733Sthien 				return (NLNIL);
246753Speter 			}
24714733Sthien 			(void) put(1, op);
248753Speter 			return (nl+TBOOL);
249753Speter 		case O_EOF:
250753Speter 			if (p1->class != FILET) {
251753Speter 				error("Argument to eof must be file, not %s", nameof(p1));
25214733Sthien 				return (NLNIL);
253753Speter 			}
25414733Sthien 			(void) put(1, op);
255753Speter 			return (nl+TBOOL);
256753Speter 	}
257753Speter }
258753Speter #endif OBJ
259