Annotation of 43BSD/ucb/pascal/pdx/runtime/callproc.c, revision 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.