xref: /csrg-svn/usr.bin/pascal/src/pcfunc.c (revision 22183)
1*22183Sdist /*
2*22183Sdist  * Copyright (c) 1980 Regents of the University of California.
3*22183Sdist  * All rights reserved.  The Berkeley software License Agreement
4*22183Sdist  * specifies the terms and conditions for redistribution.
5*22183Sdist  */
6764Speter 
714738Sthien #ifndef lint
8*22183Sdist static char sccsid[] = "@(#)pcfunc.c	5.1 (Berkeley) 06/05/85";
9*22183Sdist #endif not lint
10764Speter 
11764Speter #include "whoami.h"
12764Speter #ifdef PC
13764Speter     /*
14764Speter      *	and to the end of the file
15764Speter      */
16764Speter #include "0.h"
17764Speter #include "tree.h"
1810375Speter #include "objfmt.h"
19764Speter #include "opcode.h"
2010375Speter #include "pc.h"
2118464Sralph #include <pcc.h>
2211328Speter #include "tmps.h"
2314738Sthien #include "tree_ty.h"
24764Speter 
25764Speter /*
26764Speter  * Funccod generates code for
27764Speter  * built in function calls and calls
28764Speter  * call to generate calls to user
29764Speter  * defined functions and procedures.
30764Speter  */
3114738Sthien struct nl *
32764Speter pcfunccod( r )
3314738Sthien 	struct tnode	 *r; /* T_FCALL */
34764Speter {
35764Speter 	struct nl *p;
36764Speter 	register struct nl *p1;
3714738Sthien 	register struct tnode *al;
38764Speter 	register op;
3914738Sthien 	int argc;
4014738Sthien 	struct tnode *argv;
4114738Sthien 	struct tnode tr, tr2;
42764Speter 	char		*funcname;
433831Speter 	struct nl	*tempnlp;
44764Speter 	long		temptype;
45764Speter 	struct nl	*rettype;
46764Speter 
47764Speter 	/*
48764Speter 	 * Verify that the given name
49764Speter 	 * is defined and the name of
50764Speter 	 * a function.
51764Speter 	 */
5214738Sthien 	p = lookup(r->pcall_node.proc_id);
5314738Sthien 	if (p == NLNIL) {
5414738Sthien 		rvlist(r->pcall_node.arg);
5514738Sthien 		return (NLNIL);
56764Speter 	}
571197Speter 	if (p->class != FUNC && p->class != FFUNC) {
58764Speter 		error("%s is not a function", p->symbol);
5914738Sthien 		rvlist(r->pcall_node.arg);
6014738Sthien 		return (NLNIL);
61764Speter 	}
6214738Sthien 	argv = r->pcall_node.arg;
63764Speter 	/*
64764Speter 	 * Call handles user defined
65764Speter 	 * procedures and functions
66764Speter 	 */
67764Speter 	if (bn != 0)
68764Speter 		return (call(p, argv, FUNC, bn));
69764Speter 	/*
70764Speter 	 * Count the arguments
71764Speter 	 */
72764Speter 	argc = 0;
7314738Sthien 	for (al = argv; al != TR_NIL; al = al->list_node.next)
74764Speter 		argc++;
75764Speter 	/*
76764Speter 	 * Built-in functions have
77764Speter 	 * their interpreter opcode
78764Speter 	 * associated with them.
79764Speter 	 */
80764Speter 	op = p->value[0] &~ NSTAND;
81764Speter 	if (opt('s') && (p->value[0] & NSTAND)) {
82764Speter 		standard();
83764Speter 		error("%s is a nonstandard function", p->symbol);
84764Speter 	}
85764Speter 	if ( op == O_ARGC ) {
8618464Sralph 	    putleaf( PCC_NAME , 0 , 0 , PCCT_INT , "__argc" );
87764Speter 	    return nl + T4INT;
88764Speter 	}
89764Speter 	switch (op) {
90764Speter 		/*
91764Speter 		 * Parameterless functions
92764Speter 		 */
93764Speter 		case O_CLCK:
94764Speter 			funcname = "_CLCK";
95764Speter 			goto noargs;
96764Speter 		case O_SCLCK:
97764Speter 			funcname = "_SCLCK";
98764Speter 			goto noargs;
99764Speter noargs:
100764Speter 			if (argc != 0) {
101764Speter 				error("%s takes no arguments", p->symbol);
102764Speter 				rvlist(argv);
10314738Sthien 				return (NLNIL);
104764Speter 			}
10518464Sralph 			putleaf( PCC_ICON , 0 , 0
10618464Sralph 				, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
107764Speter 				, funcname );
10818464Sralph 			putop( PCCOM_UNARY PCC_CALL , PCCT_INT );
109764Speter 			return (nl+T4INT);
110764Speter 		case O_WCLCK:
111764Speter 			if (argc != 0) {
112764Speter 				error("%s takes no arguments", p->symbol);
113764Speter 				rvlist(argv);
11414738Sthien 				return (NLNIL);
115764Speter 			}
11618464Sralph 			putleaf( PCC_ICON , 0 , 0
11718464Sralph 				, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
118764Speter 				, "_time" );
11918464Sralph 			putleaf( PCC_ICON , 0 , 0 , PCCT_INT , (char *) 0 );
12018464Sralph 			putop( PCC_CALL , PCCT_INT );
121764Speter 			return (nl+T4INT);
122764Speter 		case O_EOF:
123764Speter 		case O_EOLN:
124764Speter 			if (argc == 0) {
12514738Sthien 				argv = &(tr);
12614738Sthien 				tr.list_node.list = &(tr2);
12714738Sthien 				tr2.tag = T_VAR;
12814738Sthien 				tr2.var_node.cptr = input->symbol;
12914738Sthien 				tr2.var_node.line_no = NIL;
13014738Sthien 				tr2.var_node.qual = TR_NIL;
131764Speter 				argc = 1;
132764Speter 			} else if (argc != 1) {
133764Speter 				error("%s takes either zero or one argument", p->symbol);
134764Speter 				rvlist(argv);
13514738Sthien 				return (NLNIL);
136764Speter 			}
137764Speter 		}
138764Speter 	/*
139764Speter 	 * All other functions take
140764Speter 	 * exactly one argument.
141764Speter 	 */
142764Speter 	if (argc != 1) {
143764Speter 		error("%s takes exactly one argument", p->symbol);
144764Speter 		rvlist(argv);
14514738Sthien 		return (NLNIL);
146764Speter 	}
147764Speter 	/*
148764Speter 	 * find out the type of the argument
149764Speter 	 */
150764Speter 	codeoff();
15114738Sthien 	p1 = stkrval( argv->list_node.list, NLNIL , (long) RREQ );
152764Speter 	codeon();
15314738Sthien 	if (p1 == NLNIL)
15414738Sthien 		return (NLNIL);
155764Speter 	/*
156764Speter 	 * figure out the return type and the funtion name
157764Speter 	 */
158764Speter 	switch (op) {
15914738Sthien 	    case 0:
16014738Sthien 			error("%s is an unimplemented 6000-3.4 extension", p->symbol);
16114738Sthien 	    default:
16214738Sthien 			panic("func1");
163764Speter 	    case O_EXP:
1645715Smckusic 		    funcname = opt('t') ? "_EXP" : "_exp";
165764Speter 		    goto mathfunc;
166764Speter 	    case O_SIN:
1675715Smckusic 		    funcname = opt('t') ? "_SIN" : "_sin";
168764Speter 		    goto mathfunc;
169764Speter 	    case O_COS:
1705715Smckusic 		    funcname = opt('t') ? "_COS" : "_cos";
171764Speter 		    goto mathfunc;
172764Speter 	    case O_ATAN:
1735715Smckusic 		    funcname = opt('t') ? "_ATAN" : "_atan";
174764Speter 		    goto mathfunc;
175764Speter 	    case O_LN:
176764Speter 		    funcname = opt('t') ? "_LN" : "_log";
177764Speter 		    goto mathfunc;
178764Speter 	    case O_SQRT:
179764Speter 		    funcname = opt('t') ? "_SQRT" : "_sqrt";
180764Speter 		    goto mathfunc;
181764Speter 	    case O_RANDOM:
182764Speter 		    funcname = "_RANDOM";
183764Speter 		    goto mathfunc;
184764Speter mathfunc:
185764Speter 		    if (isnta(p1, "id")) {
186764Speter 			    error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1));
18714738Sthien 			    return (NLNIL);
188764Speter 		    }
18918464Sralph 		    putleaf( PCC_ICON , 0 , 0
19018464Sralph 			    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_DOUBLE , PCCTM_PTR ) , funcname );
19114738Sthien 		    p1 = stkrval(  argv->list_node.list , NLNIL , (long) RREQ );
19218464Sralph 		    sconv(p2type(p1), PCCT_DOUBLE);
19318464Sralph 		    putop( PCC_CALL , PCCT_DOUBLE );
194764Speter 		    return nl + TDOUBLE;
195764Speter 	    case O_EXPO:
196764Speter 		    if (isnta( p1 , "id" ) ) {
197764Speter 			    error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1));
198764Speter 			    return NIL;
199764Speter 		    }
20018464Sralph 		    putleaf( PCC_ICON , 0 , 0
20118464Sralph 			    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , "_EXPO" );
20214738Sthien 		    p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ );
20318464Sralph 		    sconv(p2type(p1), PCCT_DOUBLE);
20418464Sralph 		    putop( PCC_CALL , PCCT_INT );
205764Speter 		    return ( nl + T4INT );
206764Speter 	    case O_UNDEF:
207764Speter 		    if ( isnta( p1 , "id" ) ) {
208764Speter 			    error("%s's argument must be integer or real, not %s", p->symbol, nameof(p1));
20914738Sthien 			    return NLNIL;
210764Speter 		    }
21114738Sthien 		    p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ );
21218464Sralph 		    putleaf( PCC_ICON , 0 , 0 , PCCT_CHAR , (char *) 0 );
21318464Sralph 		    putop( PCC_COMOP , PCCT_CHAR );
214764Speter 		    return ( nl + TBOOL );
215764Speter 	    case O_SEED:
216764Speter 		    if (isnta(p1, "i")) {
217764Speter 			    error("seed's argument must be an integer, not %s", nameof(p1));
21814738Sthien 			    return (NLNIL);
219764Speter 		    }
22018464Sralph 		    putleaf( PCC_ICON , 0 , 0
22118464Sralph 			    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , "_SEED" );
22214738Sthien 		    p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ );
22318464Sralph 		    putop( PCC_CALL , PCCT_INT );
224764Speter 		    return nl + T4INT;
225764Speter 	    case O_ROUND:
226764Speter 	    case O_TRUNC:
227764Speter 		    if ( isnta( p1 , "d" ) ) {
228764Speter 			    error("%s's argument must be a real, not %s", p->symbol, nameof(p1));
22914738Sthien 			    return (NLNIL);
230764Speter 		    }
23118464Sralph 		    putleaf( PCC_ICON , 0 , 0
23218464Sralph 			    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
233764Speter 			    , op == O_ROUND ? "_ROUND" : "_TRUNC" );
23414738Sthien 		    p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ );
23518464Sralph 		    putop( PCC_CALL , PCCT_INT );
236764Speter 		    return nl + T4INT;
237764Speter 	    case O_ABS2:
238764Speter 			if ( isa( p1 , "d" ) ) {
23918464Sralph 			    putleaf( PCC_ICON , 0 , 0
24018464Sralph 				, PCCM_ADDTYPE( PCCTM_FTN | PCCT_DOUBLE , PCCTM_PTR )
241764Speter 				, "_fabs" );
24214738Sthien 			    p1 = stkrval( argv->list_node.list , NLNIL ,(long) RREQ );
24318464Sralph 			    putop( PCC_CALL , PCCT_DOUBLE );
244764Speter 			    return nl + TDOUBLE;
245764Speter 			}
246764Speter 			if ( isa( p1 , "i" ) ) {
24718464Sralph 			    putleaf( PCC_ICON , 0 , 0
24818464Sralph 				, PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , "_abs" );
24914738Sthien 			    p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ );
25018464Sralph 			    putop( PCC_CALL , PCCT_INT );
251764Speter 			    return nl + T4INT;
252764Speter 			}
253764Speter 			error("%s's argument must be an integer or real, not %s", p->symbol, nameof(p1));
25414738Sthien 			return NLNIL;
255764Speter 	    case O_SQR2:
256764Speter 			if ( isa( p1 , "d" ) ) {
25718464Sralph 			    temptype = PCCT_DOUBLE;
258764Speter 			    rettype = nl + TDOUBLE;
25914738Sthien 			    tempnlp = tmpalloc((long) (sizeof(double)), rettype, REGOK);
260764Speter 			} else if ( isa( p1 , "i" ) ) {
26118464Sralph 			    temptype = PCCT_INT;
262764Speter 			    rettype = nl + T4INT;
26314738Sthien 			    tempnlp = tmpalloc((long) (sizeof(long)), rettype, REGOK);
264764Speter 			} else {
265764Speter 			    error("%s's argument must be an integer or real, not %s", p->symbol, nameof(p1));
26614738Sthien 			    return NLNIL;
267764Speter 			}
26814738Sthien 			putRV( (char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] ,
26914738Sthien 				tempnlp -> extra_flags , (char) temptype  );
27014738Sthien 			p1 = rvalue( argv->list_node.list , NLNIL , RREQ );
27114738Sthien 			sconv(p2type(p1), (int) temptype);
27218464Sralph 			putop( PCC_ASSIGN , (int) temptype );
27314738Sthien 			putRV((char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] ,
27414738Sthien 				tempnlp -> extra_flags , (char) temptype );
27514738Sthien 			putRV((char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] ,
27614738Sthien 				tempnlp -> extra_flags , (char) temptype );
27718464Sralph 			putop( PCC_MUL , (int) temptype );
27818464Sralph 			putop( PCC_COMOP , (int) temptype );
279764Speter 			return rettype;
280764Speter 	    case O_ORD2:
28114738Sthien 			p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ );
2829573Speter 			if (isa(p1, "bcis")) {
283764Speter 				return (nl+T4INT);
284764Speter 			}
2859573Speter 			if (classify(p1) == TPTR) {
2869573Speter 			    if (!opt('s')) {
2879573Speter 				return (nl+T4INT);
2889573Speter 			    }
2899573Speter 			    standard();
2909573Speter 			}
2919573Speter 			error("ord's argument must be of scalar type, not %s",
2929573Speter 				nameof(p1));
29314738Sthien 			return (NLNIL);
294764Speter 	    case O_SUCC2:
295764Speter 	    case O_PRED2:
296764Speter 			if (isa(p1, "d")) {
297764Speter 				error("%s is forbidden for reals", p->symbol);
29814738Sthien 				return (NLNIL);
299764Speter 			}
300764Speter 			if ( isnta( p1 , "bcsi" ) ) {
301764Speter 			    error("%s's argument must be of scalar type, not %s", p->symbol, nameof(p1));
30214738Sthien 			    return NLNIL;
303764Speter 			}
304764Speter 			if ( opt( 't' ) ) {
30518464Sralph 			    putleaf( PCC_ICON , 0 , 0
30618464Sralph 				    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR )
307764Speter 				    , op == O_SUCC2 ? "_SUCC" : "_PRED" );
30814738Sthien 			    p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ );
3096596Smckusick 			    tempnlp = p1 -> class == TYPE ? p1 -> type : p1;
31018464Sralph 			    putleaf( PCC_ICON, (int) tempnlp -> range[0], 0, PCCT_INT, (char *) 0 );
31118464Sralph 			    putop( PCC_CM , PCCT_INT );
31218464Sralph 			    putleaf( PCC_ICON, (int) tempnlp -> range[1], 0, PCCT_INT, (char *) 0 );
31318464Sralph 			    putop( PCC_CM , PCCT_INT );
31418464Sralph 			    putop( PCC_CALL , PCCT_INT );
31518464Sralph 			    sconv(PCCT_INT, p2type(p1));
316764Speter 			} else {
31714738Sthien 			    p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ );
31818464Sralph 			    putleaf( PCC_ICON , 1 , 0 , PCCT_INT , (char *) 0 );
31918464Sralph 			    putop( op == O_SUCC2 ? PCC_PLUS : PCC_MINUS , PCCT_INT );
32018464Sralph 			    sconv(PCCT_INT, p2type(p1));
321764Speter 			}
322764Speter 			if ( isa( p1 , "bcs" ) ) {
323764Speter 			    return p1;
324764Speter 			} else {
325764Speter 			    return nl + T4INT;
326764Speter 			}
327764Speter 	    case O_ODD2:
328764Speter 			if (isnta(p1, "i")) {
329764Speter 				error("odd's argument must be an integer, not %s", nameof(p1));
33014738Sthien 				return (NLNIL);
331764Speter 			}
33214738Sthien 			p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ );
33310669Speter 			    /*
33410669Speter 			     *	THIS IS MACHINE-DEPENDENT!!!
33510669Speter 			     */
33618464Sralph 			putleaf( PCC_ICON , 1 , 0 , PCCT_INT , (char *) 0 );
33718464Sralph 			putop( PCC_AND , PCCT_INT );
33818464Sralph 			sconv(PCCT_INT, PCCT_CHAR);
339764Speter 			return nl + TBOOL;
340764Speter 	    case O_CHR2:
341764Speter 			if (isnta(p1, "i")) {
342764Speter 				error("chr's argument must be an integer, not %s", nameof(p1));
34314738Sthien 				return (NLNIL);
344764Speter 			}
345764Speter 			if (opt('t')) {
34618464Sralph 			    putleaf( PCC_ICON , 0 , 0
34718464Sralph 				, PCCM_ADDTYPE( PCCTM_FTN | PCCT_CHAR , PCCTM_PTR ) , "_CHR" );
34814738Sthien 			    p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ );
34918464Sralph 			    putop( PCC_CALL , PCCT_CHAR );
350764Speter 			} else {
35114738Sthien 			    p1 = stkrval( argv->list_node.list , NLNIL , (long) RREQ );
35218464Sralph 			    sconv(PCCT_INT, PCCT_CHAR);
353764Speter 			}
354764Speter 			return nl + TCHAR;
355764Speter 	    case O_CARD:
3561554Speter 			if (isnta(p1, "t")) {
3571554Speter 			    error("Argument to card must be a set, not %s", nameof(p1));
35814738Sthien 			    return (NLNIL);
359764Speter 			}
36018464Sralph 			putleaf( PCC_ICON , 0 , 0
36118464Sralph 			    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , "_CARD" );
36214738Sthien 			p1 = stkrval( argv->list_node.list , NLNIL , (long) LREQ );
36318464Sralph 			putleaf( PCC_ICON , (int) lwidth( p1 ) , 0 , PCCT_INT , (char *) 0 );
36418464Sralph 			putop( PCC_CM , PCCT_INT );
36518464Sralph 			putop( PCC_CALL , PCCT_INT );
36610669Speter 			return nl + T4INT;
367764Speter 	    case O_EOLN:
368764Speter 			if (!text(p1)) {
369764Speter 				error("Argument to eoln must be a text file, not %s", nameof(p1));
37014738Sthien 				return (NLNIL);
371764Speter 			}
37218464Sralph 			putleaf( PCC_ICON , 0 , 0
37318464Sralph 			    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , "_TEOLN" );
37414738Sthien 			p1 = stklval( argv->list_node.list , NOFLAGS );
37518464Sralph 			putop( PCC_CALL , PCCT_INT );
37618464Sralph 			sconv(PCCT_INT, PCCT_CHAR);
377764Speter 			return nl + TBOOL;
378764Speter 	    case O_EOF:
379764Speter 			if (p1->class != FILET) {
380764Speter 				error("Argument to eof must be file, not %s", nameof(p1));
38114738Sthien 				return (NLNIL);
382764Speter 			}
38318464Sralph 			putleaf( PCC_ICON , 0 , 0
38418464Sralph 			    , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , "_TEOF" );
38514738Sthien 			p1 = stklval( argv->list_node.list , NOFLAGS );
38618464Sralph 			putop( PCC_CALL , PCCT_INT );
38718464Sralph 			sconv(PCCT_INT, PCCT_CHAR);
388764Speter 			return nl + TBOOL;
389764Speter 	}
390764Speter }
391764Speter #endif PC
392