xref: /csrg-svn/usr.bin/pascal/src/func.c (revision 14733)
1753Speter /* Copyright (c) 1979 Regents of the University of California */
2753Speter 
3*14733Sthien #ifndef lint
4*14733Sthien static char sccsid[] = "@(#)func.c 1.10 08/19/83";
5*14733Sthien #endif
6753Speter 
7753Speter #include "whoami.h"
8753Speter #ifdef OBJ
9753Speter     /*
10753Speter      *	the rest of the file
11753Speter      */
12753Speter #include "0.h"
13753Speter #include "tree.h"
14753Speter #include "opcode.h"
15*14733Sthien #include "tree_ty.h"
16753Speter 
17753Speter /*
18753Speter  * Funccod generates code for
19753Speter  * built in function calls and calls
20753Speter  * call to generate calls to user
21753Speter  * defined functions and procedures.
22753Speter  */
23*14733Sthien struct nl
24*14733Sthien *funccod(r)
25*14733Sthien 	struct tnode *r;
26753Speter {
27753Speter 	struct nl *p;
28753Speter 	register struct nl *p1;
296595Smckusick 	struct nl *tempnlp;
30*14733Sthien 	register struct tnode *al;
31753Speter 	register op;
32*14733Sthien 	int argc;
33*14733Sthien 	struct tnode *argv, tr, tr2;
34753Speter 
35753Speter 	/*
36753Speter 	 * Verify that the given name
37753Speter 	 * is defined and the name of
38753Speter 	 * a function.
39753Speter 	 */
40*14733Sthien 	p = lookup(r->pcall_node.proc_id);
41*14733Sthien 	if (p == NLNIL) {
42*14733Sthien 		rvlist(r->pcall_node.arg);
43*14733Sthien 		return (NLNIL);
44753Speter 	}
451197Speter 	if (p->class != FUNC && p->class != FFUNC) {
46753Speter 		error("%s is not a function", p->symbol);
47*14733Sthien 		rvlist(r->pcall_node.arg);
48*14733Sthien 		return (NLNIL);
49753Speter 	}
50*14733Sthien 	argv = r->pcall_node.arg;
51753Speter 	/*
52753Speter 	 * Call handles user defined
53753Speter 	 * procedures and functions
54753Speter 	 */
55753Speter 	if (bn != 0)
56753Speter 		return (call(p, argv, FUNC, bn));
57753Speter 	/*
58753Speter 	 * Count the arguments
59753Speter 	 */
60753Speter 	argc = 0;
61*14733Sthien 	for (al = argv; al != TR_NIL; al = al->list_node.next)
62753Speter 		argc++;
63753Speter 	/*
64753Speter 	 * Built-in functions have
65753Speter 	 * their interpreter opcode
66753Speter 	 * associated with them.
67753Speter 	 */
68753Speter 	op = p->value[0] &~ NSTAND;
69753Speter 	if (opt('s') && (p->value[0] & NSTAND)) {
70753Speter 		standard();
71753Speter 		error("%s is a nonstandard function", p->symbol);
72753Speter 	}
73753Speter 	switch (op) {
74753Speter 		/*
75753Speter 		 * Parameterless functions
76753Speter 		 */
77753Speter 		case O_CLCK:
78753Speter 		case O_SCLCK:
79753Speter 		case O_WCLCK:
80753Speter 		case O_ARGC:
81753Speter 			if (argc != 0) {
82753Speter 				error("%s takes no arguments", p->symbol);
83753Speter 				rvlist(argv);
84*14733Sthien 				return (NLNIL);
85753Speter 			}
86*14733Sthien 			(void) put(1, op);
87753Speter 			return (nl+T4INT);
88753Speter 		case O_EOF:
89753Speter 		case O_EOLN:
90753Speter 			if (argc == 0) {
91*14733Sthien 				argv = (&tr);
92*14733Sthien 				tr.list_node.list = (&tr2);
93*14733Sthien 				tr2.tag = T_VAR;
94*14733Sthien 				tr2.var_node.cptr = input->symbol;
95*14733Sthien 				tr2.var_node.line_no = NIL;
96*14733Sthien 				tr2.var_node.qual = TR_NIL;
97753Speter 				argc = 1;
98753Speter 			} else if (argc != 1) {
99753Speter 				error("%s takes either zero or one argument", p->symbol);
100753Speter 				rvlist(argv);
101*14733Sthien 				return (NLNIL);
102753Speter 			}
103753Speter 		}
104753Speter 	/*
105753Speter 	 * All other functions take
106753Speter 	 * exactly one argument.
107753Speter 	 */
108753Speter 	if (argc != 1) {
109753Speter 		error("%s takes exactly one argument", p->symbol);
110753Speter 		rvlist(argv);
111*14733Sthien 		return (NLNIL);
112753Speter 	}
113753Speter 	/*
114753Speter 	 * Evaluate the argmument
115753Speter 	 */
1162070Smckusic 	if (op == O_EOF || op == O_EOLN)
117*14733Sthien 		p1 = stklval(argv->list_node.list, NIL );
1182070Smckusic 	else
119*14733Sthien 		p1 = stkrval(argv->list_node.list, NLNIL , (long) RREQ );
120*14733Sthien 	if (p1 == NLNIL)
121*14733Sthien 		return (NLNIL);
122753Speter 	switch (op) {
123*14733Sthien 		case 0:
124*14733Sthien 			error("%s is an unimplemented 6000-3.4 extension", p->symbol);
125*14733Sthien 		default:
126*14733Sthien 			panic("func1");
127753Speter 		case O_EXP:
128753Speter 		case O_SIN:
129753Speter 		case O_COS:
130753Speter 		case O_ATAN:
131753Speter 		case O_LN:
132753Speter 		case O_SQRT:
133753Speter 		case O_RANDOM:
134753Speter 		case O_EXPO:
135753Speter 		case O_UNDEF:
136753Speter 			if (isa(p1, "i"))
1372537Speter 				convert( nl+T4INT , nl+TDOUBLE);
138753Speter 			else if (isnta(p1, "d")) {
139753Speter 				error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1));
140*14733Sthien 				return (NLNIL);
141753Speter 			}
142*14733Sthien 			(void) put(1, op);
143753Speter 			if (op == O_UNDEF)
144753Speter 				return (nl+TBOOL);
145753Speter 			else if (op == O_EXPO)
146753Speter 				return (nl+T4INT);
147753Speter 			else
148753Speter 				return (nl+TDOUBLE);
149753Speter 		case O_SEED:
150753Speter 			if (isnta(p1, "i")) {
151753Speter 				error("seed's argument must be an integer, not %s", nameof(p1));
152*14733Sthien 				return (NLNIL);
153753Speter 			}
154*14733Sthien 			(void) put(1, op);
155753Speter 			return (nl+T4INT);
156753Speter 		case O_ROUND:
157753Speter 		case O_TRUNC:
158753Speter 			if (isnta(p1, "d"))  {
159753Speter 				error("%s's argument must be a real, not %s", p->symbol, nameof(p1));
160*14733Sthien 				return (NLNIL);
161753Speter 			}
162*14733Sthien 			(void) put(1, op);
163753Speter 			return (nl+T4INT);
164753Speter 		case O_ABS2:
165753Speter 		case O_SQR2:
166753Speter 			if (isa(p1, "d")) {
167*14733Sthien 				(void) put(1, op + O_ABS8-O_ABS2);
168753Speter 				return (nl+TDOUBLE);
169753Speter 			}
170753Speter 			if (isa(p1, "i")) {
171*14733Sthien 				(void) put(1, op + (width(p1) >> 2));
172753Speter 				return (nl+T4INT);
173753Speter 			}
174753Speter 			error("%s's argument must be an integer or real, not %s", p->symbol, nameof(p1));
175*14733Sthien 			return (NLNIL);
176753Speter 		case O_ORD2:
1779573Speter 			if (isa(p1, "bcis")) {
178753Speter 				return (nl+T4INT);
179753Speter 			}
1809573Speter 			if (classify(p1) == TPTR) {
1819573Speter 			    if (!opt('s')) {
1829573Speter 				return (nl+T4INT);
1839573Speter 			    }
1849573Speter 			    standard();
1859573Speter 			}
1869573Speter 			error("ord's argument must be of scalar type, not %s",
1879573Speter 				nameof(p1));
188*14733Sthien 			return (NLNIL);
189753Speter 		case O_SUCC2:
190753Speter 		case O_PRED2:
1912104Smckusic 			if (isa(p1, "d")) {
1922104Smckusic 				error("%s is forbidden for reals", p->symbol);
193*14733Sthien 				return (NLNIL);
194753Speter 			}
1952104Smckusic 			if ( isnta( p1 , "bcsi" ) ) {
1962104Smckusic 				error("%s's argument must be of scalar type, not %s", p->symbol, nameof(p1));
1972104Smckusic 				return NIL;
1982104Smckusic 			}
1996595Smckusick 			tempnlp = p1 -> class == TYPE ? p1 -> type : p1;
200753Speter 			if (isa(p1, "i")) {
2013074Smckusic 				if (width(p1) <= 2) {
2022104Smckusic 					op += O_PRED24 - O_PRED2;
203*14733Sthien 					(void) put(3, op, (int)tempnlp->range[0],
2046595Smckusick 						(int)tempnlp->range[1]);
2053074Smckusic 				} else {
206753Speter 					op++;
207*14733Sthien 					(void) put(3, op, tempnlp->range[0],
2086595Smckusick 						tempnlp->range[1]);
2093074Smckusic 				}
2102104Smckusic 				return nl + T4INT;
2112104Smckusic 			} else {
212*14733Sthien 				(void) put(3, op, (int)tempnlp->range[0],
2136595Smckusick 					(int)tempnlp->range[1]);
2142104Smckusic 				return p1;
215753Speter 			}
216753Speter 		case O_ODD2:
217753Speter 			if (isnta(p1, "i")) {
218753Speter 				error("odd's argument must be an integer, not %s", nameof(p1));
219*14733Sthien 				return (NLNIL);
220753Speter 			}
221*14733Sthien 			(void) put(1, op + (width(p1) >> 2));
222753Speter 			return (nl+TBOOL);
223753Speter 		case O_CHR2:
224753Speter 			if (isnta(p1, "i")) {
225753Speter 				error("chr's argument must be an integer, not %s", nameof(p1));
226*14733Sthien 				return (NLNIL);
227753Speter 			}
228*14733Sthien 			(void) put(1, op + (width(p1) >> 2));
229753Speter 			return (nl+TCHAR);
230753Speter 		case O_CARD:
2311553Speter 			if (isnta(p1, "t")) {
2321553Speter 			    error("Argument to card must be a set, not %s", nameof(p1));
233*14733Sthien 			    return (NLNIL);
234753Speter 			}
235*14733Sthien 			(void) put(2, O_CARD, width(p1));
236753Speter 			return (nl+T2INT);
237753Speter 		case O_EOLN:
238753Speter 			if (!text(p1)) {
239753Speter 				error("Argument to eoln must be a text file, not %s", nameof(p1));
240*14733Sthien 				return (NLNIL);
241753Speter 			}
242*14733Sthien 			(void) put(1, op);
243753Speter 			return (nl+TBOOL);
244753Speter 		case O_EOF:
245753Speter 			if (p1->class != FILET) {
246753Speter 				error("Argument to eof must be file, not %s", nameof(p1));
247*14733Sthien 				return (NLNIL);
248753Speter 			}
249*14733Sthien 			(void) put(1, op);
250753Speter 			return (nl+TBOOL);
251753Speter 	}
252753Speter }
253753Speter #endif OBJ
254