Annotation of 43BSD/ucb/pascal/pdx/runtime/callproc.c, revision 1.1.1.1

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[] = "@(#)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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.