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[] = "@(#)callproc.c	5.1 (Berkeley) 6/6/85";
   9: #endif not lint
  10: /*
  11:  * Evaluate a call to a procedure.
  12:  *
  13:  * This file is a botch as far as modularity is concerned.
  14:  */
  15: 
  16: #include "defs.h"
  17: #include "runtime.h"
  18: #include "sym.h"
  19: #include "tree.h"
  20: #include "breakpoint.h"
  21: #include "machine.h"
  22: #include "process.h"
  23: #include "source.h"
  24: #include "frame.rep"
  25: #include "sym/classes.h"
  26: #include "sym/sym.rep"
  27: #include "tree/tree.rep"
  28: #include "process/process.rep"
  29: #include "process/pxinfo.h"
  30: 
  31: LOCAL ADDRESS retaddr;
  32: 
  33: /*
  34:  * Controlling logic of procedure calling.
  35:  * Calling a procedure before ever executing the program must
  36:  * be special cased.
  37:  */
  38: 
  39: callproc(procnode, arglist)
  40: NODE *procnode;
  41: NODE *arglist;
  42: {
  43:     SYM *proc;
  44: 
  45:     if (pc == 0) {
  46:         curline = firstline(program);
  47:         setbp(curline);
  48:         resume();
  49:         unsetbp(curline);
  50:     }
  51:     proc = procnode->nameval;
  52:     if (!isblock(proc)) {
  53:         error("\"%s\" is not a procedure or function", proc->symbol);
  54:     }
  55:     pushargs(proc, arglist);
  56:     pushenv(proc->symvalue.funcv.codeloc);
  57:     pushframe(proc->blkno);
  58:     execute(proc);
  59:     /* NOTREACHED */
  60: }
  61: 
  62: /*
  63:  * Push the arguments on the process' stack.  We do this by first
  64:  * evaluating them on the "eval" stack, then copying into the process'
  65:  * space.
  66:  */
  67: 
  68: LOCAL pushargs(proc, arglist)
  69: SYM *proc;
  70: NODE *arglist;
  71: {
  72:     STACK *savesp;
  73:     int args_size;
  74: 
  75:     savesp = sp;
  76:     evalargs(proc->symbol, proc->chain, arglist);
  77:     args_size = sp - savesp;
  78:     process->sp -= args_size;
  79:     dwrite(savesp, process->sp, args_size);
  80:     sp = savesp;
  81: }
  82: 
  83: /*
  84:  * Evaluate arguments right-to-left because the eval stack
  85:  * grows up, px's stack grows down.
  86:  */
  87: 
  88: LOCAL evalargs(procname, arg, explist)
  89: char *procname;
  90: SYM *arg;
  91: NODE *explist;
  92: {
  93:     NODE *exp;
  94:     STACK *savesp;
  95:     ADDRESS addr;
  96: 
  97:     if (arg == NIL) {
  98:         if (explist != NIL) {
  99:             error("too many parameters to \"%s\"", procname);
 100:         }
 101:     } else if (explist == NIL) {
 102:         error("not enough parameters to \"%s\"", procname);
 103:     } else {
 104:         if (explist->op != O_COMMA) {
 105:             panic("evalargs: arglist missing comma");
 106:         }
 107:         savesp = sp;
 108:         evalargs(procname, arg->chain, explist->right);
 109:         exp = explist->left;
 110:         if (!compatible(arg->type, exp->nodetype)) {
 111:             sp = savesp;
 112:             trerror("%t is not the same type as parameter \"%s\"",
 113:                 exp, arg->symbol);
 114:         }
 115:         if (arg->class == REF) {
 116:             if (exp->op != O_RVAL) {
 117:                 sp = savesp;
 118:                 error("variable expected for parameter \"%s\"", arg->symbol);
 119:             }
 120:             addr = lval(exp->left);
 121:             push(ADDRESS, addr);
 122:         } else {
 123:             eval(exp);
 124:         }
 125:     }
 126: }
 127: 
 128: /*
 129:  * Simulate a CALL instruction by pushing the appropriate
 130:  * stack frame information.
 131:  *
 132:  * Massage register 10 appropriately since it contains the
 133:  * stack frame pointer.
 134:  */
 135: 
 136: LOCAL pushframe(b)
 137: int b;
 138: {
 139:     ADDRESS *newdp;
 140:     FRAME callframe;
 141: 
 142:     retaddr = program->symvalue.funcv.codeloc;
 143: 
 144: /*
 145:  * This stuff is set by the callee, just here to take up space.
 146:  */
 147:     callframe.stackref = 0;
 148:     callframe.file = 0;
 149:     callframe.blockp = 0;
 150:     callframe.save_loc = NIL;
 151:     callframe.save_disp = NIL;
 152: 
 153: /*
 154:  * This is the useful stuff.
 155:  */
 156:     callframe.save_dp = curdp();
 157:     callframe.save_pc = retaddr + ENDOFF;
 158:     callframe.save_lino = 0;
 159:     newdp = DISPLAY + (2 * b);
 160:     dwrite(&newdp, DP, sizeof(newdp));
 161:     process->sp -= sizeof(callframe);
 162:     dwrite(&callframe, process->sp, sizeof(callframe));
 163:     process->reg[10] = process->sp;
 164: }
 165: 
 166: /*
 167:  * Execute the procedure.  This routine does NOT return because it
 168:  * calls "cont", which doesn't return.  We set a CALLPROC breakpoint
 169:  * at "retaddr", the address where the called routine will return.
 170:  *
 171:  * The action for a CALLPROC is to call "procreturn" where we restore
 172:  * the environment.
 173:  */
 174: 
 175: LOCAL execute(f)
 176: SYM *f;
 177: {
 178:     isstopped = TRUE;
 179:     addbp(retaddr, CALLPROC, f, NIL, NIL, 0);
 180:     cont();
 181:     /* NOTREACHED */
 182: }
 183: 
 184: procreturn(f)
 185: SYM *f;
 186: {
 187:     int len;
 188: 
 189:     printf("%s returns ", f->symbol);
 190:     if (f->class == FUNC) {
 191:         len = size(f->type);
 192:         dread(sp, process->sp, len);
 193:         sp += len;
 194:         printval(f->type);
 195:         putchar('\n');
 196:     } else {
 197:         printf("successfully\n");
 198:     }
 199:     popenv();
 200: }
 201: 
 202: /*
 203:  * Push the current environment.
 204:  *
 205:  * This involves both saving pdx and interpreter values.
 206:  * LOOPADDR is the address of the main interpreter loop.
 207:  */
 208: 
 209: LOCAL pushenv(newpc)
 210: ADDRESS newpc;
 211: {
 212:     push(ADDRESS, pc);
 213:     push(LINENO, curline);
 214:     push(char *, cursource);
 215:     push(BOOLEAN, isstopped);
 216:     push(SYM *, curfunc);
 217:     push(WORD, process->pc);
 218:     push(WORD, process->sp);
 219:     process->pc = LOOPADDR;
 220:     pc = newpc;
 221:     process->reg[11] = pc + ENDOFF;
 222: }
 223: 
 224: /*
 225:  * Pop back to the real world.
 226:  */
 227: 
 228: popenv()
 229: {
 230:     register PROCESS *p;
 231:     char *filename;
 232: 
 233:     p = process;
 234:     p->sp = pop(WORD);
 235:     p->pc = pop(WORD);
 236:     curfunc = pop(SYM *);
 237:     isstopped = pop(BOOLEAN);
 238:     filename = pop(char *);
 239:     curline = pop(LINENO);
 240:     pc = pop(ADDRESS);
 241:     if (filename != cursource) {
 242:         skimsource(filename);
 243:     }
 244: }

Defined functions

callproc defined in line 39; never used
evalargs defined in line 88; used 2 times
execute defined in line 175; used 1 times
  • in line 58
popenv defined in line 228; used 1 times
procreturn defined in line 184; never used
pushargs defined in line 68; used 1 times
  • in line 55
pushenv defined in line 209; used 1 times
  • in line 56
pushframe defined in line 136; used 1 times
  • in line 57

Defined variables

sccsid defined in line 8; never used
Last modified: 1985-06-06
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 929
Valid CSS Valid XHTML 1.0 Strict