xref: /csrg-svn/usr.bin/pascal/src/func.c (revision 753)
1*753Speter /* Copyright (c) 1979 Regents of the University of California */
2*753Speter 
3*753Speter static	char sccsid[] = "@(#)func.c 1.1 08/27/80";
4*753Speter 
5*753Speter #include "whoami.h"
6*753Speter #ifdef OBJ
7*753Speter     /*
8*753Speter      *	the rest of the file
9*753Speter      */
10*753Speter #include "0.h"
11*753Speter #include "tree.h"
12*753Speter #include "opcode.h"
13*753Speter 
14*753Speter bool cardempty = FALSE;
15*753Speter 
16*753Speter /*
17*753Speter  * Funccod generates code for
18*753Speter  * built in function calls and calls
19*753Speter  * call to generate calls to user
20*753Speter  * defined functions and procedures.
21*753Speter  */
22*753Speter funccod(r)
23*753Speter 	int *r;
24*753Speter {
25*753Speter 	struct nl *p;
26*753Speter 	register struct nl *p1;
27*753Speter 	register int *al;
28*753Speter 	register op;
29*753Speter 	int argc, *argv;
30*753Speter 	int tr[2], tr2[4];
31*753Speter 
32*753Speter 	/*
33*753Speter 	 * Verify that the given name
34*753Speter 	 * is defined and the name of
35*753Speter 	 * a function.
36*753Speter 	 */
37*753Speter 	p = lookup(r[2]);
38*753Speter 	if (p == NIL) {
39*753Speter 		rvlist(r[3]);
40*753Speter 		return (NIL);
41*753Speter 	}
42*753Speter 	if (p->class != FUNC) {
43*753Speter 		error("%s is not a function", p->symbol);
44*753Speter 		rvlist(r[3]);
45*753Speter 		return (NIL);
46*753Speter 	}
47*753Speter 	argv = r[3];
48*753Speter 	/*
49*753Speter 	 * Call handles user defined
50*753Speter 	 * procedures and functions
51*753Speter 	 */
52*753Speter 	if (bn != 0)
53*753Speter 		return (call(p, argv, FUNC, bn));
54*753Speter 	/*
55*753Speter 	 * Count the arguments
56*753Speter 	 */
57*753Speter 	argc = 0;
58*753Speter 	for (al = argv; al != NIL; al = al[2])
59*753Speter 		argc++;
60*753Speter 	/*
61*753Speter 	 * Built-in functions have
62*753Speter 	 * their interpreter opcode
63*753Speter 	 * associated with them.
64*753Speter 	 */
65*753Speter 	op = p->value[0] &~ NSTAND;
66*753Speter 	if (opt('s') && (p->value[0] & NSTAND)) {
67*753Speter 		standard();
68*753Speter 		error("%s is a nonstandard function", p->symbol);
69*753Speter 	}
70*753Speter 	switch (op) {
71*753Speter 		/*
72*753Speter 		 * Parameterless functions
73*753Speter 		 */
74*753Speter 		case O_CLCK:
75*753Speter 		case O_SCLCK:
76*753Speter 		case O_WCLCK:
77*753Speter 		case O_ARGC:
78*753Speter 			if (argc != 0) {
79*753Speter 				error("%s takes no arguments", p->symbol);
80*753Speter 				rvlist(argv);
81*753Speter 				return (NIL);
82*753Speter 			}
83*753Speter 			put1(op);
84*753Speter 			return (nl+T4INT);
85*753Speter 		case O_EOF:
86*753Speter 		case O_EOLN:
87*753Speter 			if (argc == 0) {
88*753Speter 				argv = tr;
89*753Speter 				tr[1] = tr2;
90*753Speter 				tr2[0] = T_VAR;
91*753Speter 				tr2[2] = input->symbol;
92*753Speter 				tr2[1] = tr2[3] = NIL;
93*753Speter 				argc = 1;
94*753Speter 			} else if (argc != 1) {
95*753Speter 				error("%s takes either zero or one argument", p->symbol);
96*753Speter 				rvlist(argv);
97*753Speter 				return (NIL);
98*753Speter 			}
99*753Speter 		}
100*753Speter 	/*
101*753Speter 	 * All other functions take
102*753Speter 	 * exactly one argument.
103*753Speter 	 */
104*753Speter 	if (argc != 1) {
105*753Speter 		error("%s takes exactly one argument", p->symbol);
106*753Speter 		rvlist(argv);
107*753Speter 		return (NIL);
108*753Speter 	}
109*753Speter 	/*
110*753Speter 	 * Evaluate the argmument
111*753Speter 	 */
112*753Speter 	p1 = stkrval((int *) argv[1], NLNIL , RREQ );
113*753Speter 	if (p1 == NIL)
114*753Speter 		return (NIL);
115*753Speter 	switch (op) {
116*753Speter 		case O_EXP:
117*753Speter 		case O_SIN:
118*753Speter 		case O_COS:
119*753Speter 		case O_ATAN:
120*753Speter 		case O_LN:
121*753Speter 		case O_SQRT:
122*753Speter 		case O_RANDOM:
123*753Speter 		case O_EXPO:
124*753Speter 		case O_UNDEF:
125*753Speter 			if (isa(p1, "i"))
126*753Speter 				convert(p1, nl+TDOUBLE);
127*753Speter 			else if (isnta(p1, "d")) {
128*753Speter 				error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1));
129*753Speter 				return (NIL);
130*753Speter 			}
131*753Speter 			put1(op);
132*753Speter 			if (op == O_UNDEF)
133*753Speter 				return (nl+TBOOL);
134*753Speter 			else if (op == O_EXPO)
135*753Speter 				return (nl+T4INT);
136*753Speter 			else
137*753Speter 				return (nl+TDOUBLE);
138*753Speter 		case O_SEED:
139*753Speter 			if (isnta(p1, "i")) {
140*753Speter 				error("seed's argument must be an integer, not %s", nameof(p1));
141*753Speter 				return (NIL);
142*753Speter 			}
143*753Speter 			put1(op);
144*753Speter 			return (nl+T4INT);
145*753Speter 		case O_ROUND:
146*753Speter 		case O_TRUNC:
147*753Speter 			if (isnta(p1, "d"))  {
148*753Speter 				error("%s's argument must be a real, not %s", p->symbol, nameof(p1));
149*753Speter 				return (NIL);
150*753Speter 			}
151*753Speter 			put1(op);
152*753Speter 			return (nl+T4INT);
153*753Speter 		case O_ABS2:
154*753Speter 		case O_SQR2:
155*753Speter 			if (isa(p1, "d")) {
156*753Speter 				put1(op + O_ABS8-O_ABS2);
157*753Speter 				return (nl+TDOUBLE);
158*753Speter 			}
159*753Speter 			if (isa(p1, "i")) {
160*753Speter 				put1(op + (width(p1) >> 2));
161*753Speter 				return (nl+T4INT);
162*753Speter 			}
163*753Speter 			error("%s's argument must be an integer or real, not %s", p->symbol, nameof(p1));
164*753Speter 			return (NIL);
165*753Speter 		case O_ORD2:
166*753Speter 			if (isa(p1, "bcis") || classify(p1) == TPTR) {
167*753Speter 				return (nl+T4INT);
168*753Speter 			}
169*753Speter 			error("ord's argument must be of scalar type or a pointer, not %s", nameof(p1));
170*753Speter 			return (NIL);
171*753Speter 		case O_SUCC2:
172*753Speter 		case O_PRED2:
173*753Speter 			if (isa(p1, "bcs")) {
174*753Speter 				put1(op);
175*753Speter 				return (p1);
176*753Speter 			}
177*753Speter 			if (isa(p1, "i")) {
178*753Speter 				if (width(p1) <= 2)
179*753Speter 					op += O_PRED24-O_PRED2;
180*753Speter 				else
181*753Speter 					op++;
182*753Speter 				put1(op);
183*753Speter 				return (nl+T4INT);
184*753Speter 			}
185*753Speter 			if (isa(p1, "id")) {
186*753Speter 				error("%s is forbidden for reals", p->symbol);
187*753Speter 				return (NIL);
188*753Speter 			}
189*753Speter 			error("%s's argument must be of scalar type, not %s", p->symbol, nameof(p1));
190*753Speter 			return (NIL);
191*753Speter 		case O_ODD2:
192*753Speter 			if (isnta(p1, "i")) {
193*753Speter 				error("odd's argument must be an integer, not %s", nameof(p1));
194*753Speter 				return (NIL);
195*753Speter 			}
196*753Speter 			put1(op + (width(p1) >> 2));
197*753Speter 			return (nl+TBOOL);
198*753Speter 		case O_CHR2:
199*753Speter 			if (isnta(p1, "i")) {
200*753Speter 				error("chr's argument must be an integer, not %s", nameof(p1));
201*753Speter 				return (NIL);
202*753Speter 			}
203*753Speter 			put1(op + (width(p1) >> 2));
204*753Speter 			return (nl+TCHAR);
205*753Speter 		case O_CARD:
206*753Speter 			if ( p1 != nl + TSET ) {
207*753Speter 			    if (isnta(p1, "t")) {
208*753Speter 				error("Argument to card must be a set, not %s", nameof(p1));
209*753Speter 				return (NIL);
210*753Speter 			    }
211*753Speter 			    put2(O_CARD, width(p1));
212*753Speter 			} else {
213*753Speter 			    if ( !cardempty ) {
214*753Speter 				warning();
215*753Speter 				error("Cardinality of the empty set is 0." );
216*753Speter 				cardempty = TRUE;
217*753Speter 			    }
218*753Speter 			    put(1, O_CON1, 0);
219*753Speter 			}
220*753Speter 			return (nl+T2INT);
221*753Speter 		case O_EOLN:
222*753Speter 			if (!text(p1)) {
223*753Speter 				error("Argument to eoln must be a text file, not %s", nameof(p1));
224*753Speter 				return (NIL);
225*753Speter 			}
226*753Speter 			put1(op);
227*753Speter 			return (nl+TBOOL);
228*753Speter 		case O_EOF:
229*753Speter 			if (p1->class != FILET) {
230*753Speter 				error("Argument to eof must be file, not %s", nameof(p1));
231*753Speter 				return (NIL);
232*753Speter 			}
233*753Speter 			put1(op);
234*753Speter 			return (nl+TBOOL);
235*753Speter 		case 0:
236*753Speter 			error("%s is an unimplemented 6000-3.4 extension", p->symbol);
237*753Speter 		default:
238*753Speter 			panic("func1");
239*753Speter 	}
240*753Speter }
241*753Speter #endif OBJ
242