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