$ cat code.c#include "hoc.h"#include "y.tab.h"#include <stdio.h>#define NSTACK 256static Datum stack[NSTACK]; /* the stack */static Datum *stackp; /* next free spot on stack */#define NPROG 2000Inst prog[NPROG]; /* the machine */Inst *progp; /* next free spot for code generation */Inst *pc; /* program counter during execution */Inst *progbase = prog; /* start of current subprogram */int returning; /* 1 if return stmt seen */typedef struct Frame { /* proc/func call stack frame */ Symbol *sp; /* symbol table entry */ Inst *retpc; /* where to resume after return */ Datum *argn; /* n-th argument on stack */ int nargs; /* number of arguments */} Frame;#define NFRAME 100 Frame frame[NFRAME];Frame *fp; /* frame pointer */initcode() { progp = progbase; stackp = stack; fp = frame; returning = 0;}...$Поскольку теперь в таблице имен хранятся указатели на функции и процедуры, а также на строки для печати, необходимо расширить определение типа объединения в файле
hoc.h$ cat hoc.htypedef struct Symbol { /* symbol table entry */ char *name; short type; union { double val; /* VAR */ double (*ptr)(); /* BLTIN */ int (*defn)(); /* FUNCTION, PROCEDURE */ char *str; /* STRING */ } u; struct Symbol *next; /* to link to another */} Symbol;$В процессе трансляции функция
definedefine(sp) /* put func/proc in symbol table */ Symbol *sp;{ sp->u.defn = (Inst)progbase; /* start of code */ progbase = progp; /* next code starts here */}Когда в процессе выполнения вызывается функция или процедура, все аргументы уже вычислены и помещены в стек (первый аргумент находится на наибольшем уровне). Код операции вызова (
callcallcall() /* call a function */{ Symbol *sp = (Symbol*)pc[0]; /* symbol table entry */ /* for function */ if (fp++ >= &frame[NFRAME-1]) execerror(sp->name, "call nested too deeply"); fp->sp = sp; fp->nargs = (int)pc[1]; fp->retpc = pc + 2; fp->argn = stackp - 1; /* last argument */ execute(sp->u.defn); returning = 0;}Создаваемая структура показана на рис. 8.2.

Рис. 8.2: Структуры данных для вызова процедуры
В конце концов произойдет возврат из вызываемой программы при выполнении
procretfuncretfuncret() /* return from a function */{ Datum d; if (fp->sp->type == PROCEDURE) execerror(fp->sp->name, "(proc) returns value"); d = pop(); /* preserve function return value */ ret(); push(d);}procret() /* return from a procedure */{ if (fp->sp->type == FUNCTION) execerror(fp->sp->name(func) returns no value"); ret();}Функция
retfpret() /* common return from func or proc */{ int i; for (i = 0; i < fp->nargs; i++) pop(); /* pop arguments */