|
|
1.1 root 1: #include "../h/rt.h"
2:
3: #define PerilDelta 100
4: extern word *stackend; /* End of main interpreter stack */
5: /*
6: * invoke -- Perform setup for invocation.
7: */
8: invoke(nargs,cargp,n)
9: struct descrip **cargp;
10: int nargs, *n;
11: {
12: register struct pf_marker *newpfp;
13: register struct descrip *newargp;
14: register word *newsp = sp;
15: register word i;
16: struct b_proc *proc;
17: int nparam;
18: long longint;
19: char strbuf[MaxCvtLen];
20:
21: /*
22: * Point newargp at Arg0 and dereference it.
23: */
24: newargp = (struct descrip *)(sp - 1) - nargs;
25: DeRef(newargp[0]);
26:
27: /*
28: * See what course the invocation is to take.
29: */
30: if (newargp->dword != D_Proc) {
31: /*
32: * Arg0 is not a procedure.
33: */
34: if (cvint(&newargp[0], &longint) == T_Integer) {
35: /*
36: * Arg0 is an integer, select result.
37: */
38: i = cvpos(longint, (word)nargs);
39: if (i > nargs)
40: return I_Goal_Fail;
41: newargp[0] = newargp[i];
42: sp = (word *)newargp + 1;
43: return I_Continue;
44: }
45: else {
46: /*
47: * See if Arg0 can be converted to a string that names a procedure
48: * or operator. If not, generate run-time error 106.
49: */
50: if (cvstr(&newargp[0],strbuf) == NULL || strprc(&newargp[0],(word)nargs) == 0)
51: runerr(106, newargp);
52: }
53: }
54:
55: /*
56: * newargp[0] is now a descriptor suitable for invocation. Dereference
57: * the supplied arguments.
58: */
59: for (i = 1; i <= nargs; i++)
60: DeRef(newargp[i]);
61:
62: /*
63: * Adjust the argument list to conform to what the routine being invoked
64: * expects (proc->nparam). If nparam is -1, the number of arguments
65: * is variable and no adjustment is required. If too many arguments
66: * were supplied, adjusting the stack pointer is all that is necessary.
67: * If too few arguments were supplied, null descriptors are pushed
68: * for each missing argument.
69: */
70: proc = (struct b_proc *)BlkLoc(newargp[0]);
71: nparam = proc->nparam;
72: if (nparam != -1) {
73: if (nargs > nparam)
74: newsp -= (nargs - nparam) * 2;
75: else if (nargs < nparam) {
76: i = nparam - nargs;
77: while (i--) {
78: *++newsp = D_Null;
79: *++newsp = 0;
80: }
81: }
82: nargs = nparam;
83: }
84:
85: if (proc->ndynam < 0) {
86: /*
87: * A built-in procedure is being invoked, so nothing else here
88: * needs to be done.
89: */
90: *n = nargs;
91: *cargp = newargp;
92: sp = newsp;
93: if ((nparam == -1) || (proc->ndynam == -2))
94: return I_Vararg;
95: else
96: return I_Builtin;
97: }
98:
99: /*
100: * Make a stab at catching interpreter stack overflow. This does
101: * nothing for invocation in a co-expression other than &main.
102: */
103: if (BlkLoc(current) == BlkLoc(k_main) && (sp + PerilDelta) > stackend)
104: runerr(301, NULL);
105: /*
106: * Build the procedure frame.
107: */
108: newpfp = (struct pf_marker *)(newsp + 1);
109: newpfp->pf_nargs = nargs;
110: newpfp->pf_argp = argp;
111: newpfp->pf_pfp = pfp;
112: newpfp->pf_ilevel = ilevel;
113:
114: newpfp->pf_ipc = ipc;
115: newpfp->pf_gfp = gfp;
116: newpfp->pf_efp = efp;
117:
118: argp = newargp;
119: pfp = newpfp;
120: newsp += Vwsizeof(*pfp);
121:
122: /*
123: * Point ipc at the icode entry point of the procedure being invoked.
124: */
125: ipc = (word *)proc->entryp.icode;
126: efp = 0;
127: gfp = 0;
128:
129: newpfp->pf_line = line;
130:
131: /*
132: * If tracing is on, use ctrace to generate a message.
133: */
134: if (k_trace != 0)
135: ctrace(proc, nargs, &newargp[1]);
136:
137: /*
138: * Push a null descriptor on the stack for each dynamic local.
139: */
140: for (i = proc->ndynam; i > 0; i--) {
141: *++newsp = D_Null;
142: *++newsp = 0;
143: }
144:
145: sp = newsp;
146: k_level++;
147: return I_Continue;
148: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.