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