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

unix.superglobalmegacorp.com

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