Annotation of 42BSD/ucb/pascal/pdx/runtime/callproc.c, revision 1.1

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

unix.superglobalmegacorp.com

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