xref: /csrg-svn/usr.bin/pascal/src/func.c (revision 9573)
1753Speter /* Copyright (c) 1979 Regents of the University of California */
2753Speter 
3*9573Speter static char sccsid[] = "@(#)func.c 1.9 12/06/82";
4753Speter 
5753Speter #include "whoami.h"
6753Speter #ifdef OBJ
7753Speter     /*
8753Speter      *	the rest of the file
9753Speter      */
10753Speter #include "0.h"
11753Speter #include "tree.h"
12753Speter #include "opcode.h"
13753Speter 
14753Speter /*
15753Speter  * Funccod generates code for
16753Speter  * built in function calls and calls
17753Speter  * call to generate calls to user
18753Speter  * defined functions and procedures.
19753Speter  */
20753Speter funccod(r)
21753Speter 	int *r;
22753Speter {
23753Speter 	struct nl *p;
24753Speter 	register struct nl *p1;
256595Smckusick 	struct nl *tempnlp;
26753Speter 	register int *al;
27753Speter 	register op;
28753Speter 	int argc, *argv;
29753Speter 	int tr[2], tr2[4];
30753Speter 
31753Speter 	/*
32753Speter 	 * Verify that the given name
33753Speter 	 * is defined and the name of
34753Speter 	 * a function.
35753Speter 	 */
36753Speter 	p = lookup(r[2]);
37753Speter 	if (p == NIL) {
38753Speter 		rvlist(r[3]);
39753Speter 		return (NIL);
40753Speter 	}
411197Speter 	if (p->class != FUNC && p->class != FFUNC) {
42753Speter 		error("%s is not a function", p->symbol);
43753Speter 		rvlist(r[3]);
44753Speter 		return (NIL);
45753Speter 	}
46753Speter 	argv = r[3];
47753Speter 	/*
48753Speter 	 * Call handles user defined
49753Speter 	 * procedures and functions
50753Speter 	 */
51753Speter 	if (bn != 0)
52753Speter 		return (call(p, argv, FUNC, bn));
53753Speter 	/*
54753Speter 	 * Count the arguments
55753Speter 	 */
56753Speter 	argc = 0;
57753Speter 	for (al = argv; al != NIL; al = al[2])
58753Speter 		argc++;
59753Speter 	/*
60753Speter 	 * Built-in functions have
61753Speter 	 * their interpreter opcode
62753Speter 	 * associated with them.
63753Speter 	 */
64753Speter 	op = p->value[0] &~ NSTAND;
65753Speter 	if (opt('s') && (p->value[0] & NSTAND)) {
66753Speter 		standard();
67753Speter 		error("%s is a nonstandard function", p->symbol);
68753Speter 	}
69753Speter 	switch (op) {
70753Speter 		/*
71753Speter 		 * Parameterless functions
72753Speter 		 */
73753Speter 		case O_CLCK:
74753Speter 		case O_SCLCK:
75753Speter 		case O_WCLCK:
76753Speter 		case O_ARGC:
77753Speter 			if (argc != 0) {
78753Speter 				error("%s takes no arguments", p->symbol);
79753Speter 				rvlist(argv);
80753Speter 				return (NIL);
81753Speter 			}
823074Smckusic 			put(1, op);
83753Speter 			return (nl+T4INT);
84753Speter 		case O_EOF:
85753Speter 		case O_EOLN:
86753Speter 			if (argc == 0) {
87753Speter 				argv = tr;
88753Speter 				tr[1] = tr2;
89753Speter 				tr2[0] = T_VAR;
90753Speter 				tr2[2] = input->symbol;
91753Speter 				tr2[1] = tr2[3] = NIL;
92753Speter 				argc = 1;
93753Speter 			} else if (argc != 1) {
94753Speter 				error("%s takes either zero or one argument", p->symbol);
95753Speter 				rvlist(argv);
96753Speter 				return (NIL);
97753Speter 			}
98753Speter 		}
99753Speter 	/*
100753Speter 	 * All other functions take
101753Speter 	 * exactly one argument.
102753Speter 	 */
103753Speter 	if (argc != 1) {
104753Speter 		error("%s takes exactly one argument", p->symbol);
105753Speter 		rvlist(argv);
106753Speter 		return (NIL);
107753Speter 	}
108753Speter 	/*
109753Speter 	 * Evaluate the argmument
110753Speter 	 */
1112070Smckusic 	if (op == O_EOF || op == O_EOLN)
1122070Smckusic 		p1 = stklval((int *) argv[1], NLNIL , LREQ );
1132070Smckusic 	else
1142070Smckusic 		p1 = stkrval((int *) argv[1], NLNIL , RREQ );
115753Speter 	if (p1 == NIL)
116753Speter 		return (NIL);
117753Speter 	switch (op) {
118753Speter 		case O_EXP:
119753Speter 		case O_SIN:
120753Speter 		case O_COS:
121753Speter 		case O_ATAN:
122753Speter 		case O_LN:
123753Speter 		case O_SQRT:
124753Speter 		case O_RANDOM:
125753Speter 		case O_EXPO:
126753Speter 		case O_UNDEF:
127753Speter 			if (isa(p1, "i"))
1282537Speter 				convert( nl+T4INT , nl+TDOUBLE);
129753Speter 			else if (isnta(p1, "d")) {
130753Speter 				error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1));
131753Speter 				return (NIL);
132753Speter 			}
1333074Smckusic 			put(1, op);
134753Speter 			if (op == O_UNDEF)
135753Speter 				return (nl+TBOOL);
136753Speter 			else if (op == O_EXPO)
137753Speter 				return (nl+T4INT);
138753Speter 			else
139753Speter 				return (nl+TDOUBLE);
140753Speter 		case O_SEED:
141753Speter 			if (isnta(p1, "i")) {
142753Speter 				error("seed's argument must be an integer, not %s", nameof(p1));
143753Speter 				return (NIL);
144753Speter 			}
1453074Smckusic 			put(1, op);
146753Speter 			return (nl+T4INT);
147753Speter 		case O_ROUND:
148753Speter 		case O_TRUNC:
149753Speter 			if (isnta(p1, "d"))  {
150753Speter 				error("%s's argument must be a real, not %s", p->symbol, nameof(p1));
151753Speter 				return (NIL);
152753Speter 			}
1533074Smckusic 			put(1, op);
154753Speter 			return (nl+T4INT);
155753Speter 		case O_ABS2:
156753Speter 		case O_SQR2:
157753Speter 			if (isa(p1, "d")) {
1583074Smckusic 				put(1, op + O_ABS8-O_ABS2);
159753Speter 				return (nl+TDOUBLE);
160753Speter 			}
161753Speter 			if (isa(p1, "i")) {
1623074Smckusic 				put(1, op + (width(p1) >> 2));
163753Speter 				return (nl+T4INT);
164753Speter 			}
165753Speter 			error("%s's argument must be an integer or real, not %s", p->symbol, nameof(p1));
166753Speter 			return (NIL);
167753Speter 		case O_ORD2:
168*9573Speter 			if (isa(p1, "bcis")) {
169753Speter 				return (nl+T4INT);
170753Speter 			}
171*9573Speter 			if (classify(p1) == TPTR) {
172*9573Speter 			    if (!opt('s')) {
173*9573Speter 				return (nl+T4INT);
174*9573Speter 			    }
175*9573Speter 			    standard();
176*9573Speter 			}
177*9573Speter 			error("ord's argument must be of scalar type, not %s",
178*9573Speter 				nameof(p1));
179753Speter 			return (NIL);
180753Speter 		case O_SUCC2:
181753Speter 		case O_PRED2:
1822104Smckusic 			if (isa(p1, "d")) {
1832104Smckusic 				error("%s is forbidden for reals", p->symbol);
1842104Smckusic 				return (NIL);
185753Speter 			}
1862104Smckusic 			if ( isnta( p1 , "bcsi" ) ) {
1872104Smckusic 				error("%s's argument must be of scalar type, not %s", p->symbol, nameof(p1));
1882104Smckusic 				return NIL;
1892104Smckusic 			}
1906595Smckusick 			tempnlp = p1 -> class == TYPE ? p1 -> type : p1;
191753Speter 			if (isa(p1, "i")) {
1923074Smckusic 				if (width(p1) <= 2) {
1932104Smckusic 					op += O_PRED24 - O_PRED2;
1946595Smckusick 					put(3, op, (int)tempnlp->range[0],
1956595Smckusick 						(int)tempnlp->range[1]);
1963074Smckusic 				} else {
197753Speter 					op++;
1986595Smckusick 					put(3, op, tempnlp->range[0],
1996595Smckusick 						tempnlp->range[1]);
2003074Smckusic 				}
2012104Smckusic 				return nl + T4INT;
2022104Smckusic 			} else {
2036595Smckusick 				put(3, op, (int)tempnlp->range[0],
2046595Smckusick 					(int)tempnlp->range[1]);
2052104Smckusic 				return p1;
206753Speter 			}
207753Speter 		case O_ODD2:
208753Speter 			if (isnta(p1, "i")) {
209753Speter 				error("odd's argument must be an integer, not %s", nameof(p1));
210753Speter 				return (NIL);
211753Speter 			}
2123074Smckusic 			put(1, op + (width(p1) >> 2));
213753Speter 			return (nl+TBOOL);
214753Speter 		case O_CHR2:
215753Speter 			if (isnta(p1, "i")) {
216753Speter 				error("chr's argument must be an integer, not %s", nameof(p1));
217753Speter 				return (NIL);
218753Speter 			}
2193074Smckusic 			put(1, op + (width(p1) >> 2));
220753Speter 			return (nl+TCHAR);
221753Speter 		case O_CARD:
2221553Speter 			if (isnta(p1, "t")) {
2231553Speter 			    error("Argument to card must be a set, not %s", nameof(p1));
2241553Speter 			    return (NIL);
225753Speter 			}
2263074Smckusic 			put(2, O_CARD, width(p1));
227753Speter 			return (nl+T2INT);
228753Speter 		case O_EOLN:
229753Speter 			if (!text(p1)) {
230753Speter 				error("Argument to eoln must be a text file, not %s", nameof(p1));
231753Speter 				return (NIL);
232753Speter 			}
2333074Smckusic 			put(1, op);
234753Speter 			return (nl+TBOOL);
235753Speter 		case O_EOF:
236753Speter 			if (p1->class != FILET) {
237753Speter 				error("Argument to eof must be file, not %s", nameof(p1));
238753Speter 				return (NIL);
239753Speter 			}
2403074Smckusic 			put(1, op);
241753Speter 			return (nl+TBOOL);
242753Speter 		case 0:
243753Speter 			error("%s is an unimplemented 6000-3.4 extension", p->symbol);
244753Speter 		default:
245753Speter 			panic("func1");
246753Speter 	}
247753Speter }
248753Speter #endif OBJ
249