/* Copyright (c) 1979 Regents of the University of California */
static char sccsid
[] = "@(#)interp.c 1.2 %G%";
char *_minptr
= (char *)0x7fffffff;
char *_maxptr
= (char *)0;
long *_pcpcount
= (long *)0;
struct iorechd _fchain
= {
0, 0, 0, 0, /* only use fchain field */
struct iorec
*_actfile
[MAXFILES
] = {
char _inwin
, _outwin
, _errwin
;
"standard input", /* pfname */
FTEXT
| FREAD
| SYNC
, /* funit */
struct iorechd output
= {
"standard output", /* pfname */
FTEXT
| FWRITE
| EOFF
, /* funit */
"Message file", /* pfname */
FTEXT
| FWRITE
| EOFF
, /* funit */
union progcntr pc
; /* interpreted program cntr */
register char *vpc
; /* register used for "pc" */
struct iorec
*curfile
; /* active file */
register struct stack
*stp
; /* active stack frame ptr */
* the following variables are used as scratch
register long tl
, tl1
, tl2
;
* necessary only on systems which do not initialize
for (ip
= &_actfile
[3]; ip
< &_actfile
[MAXFILES
]; *ip
++ = FILNIL
)
* set up global environment, then ``call'' the main program
_display
.frame
[0].locvars
= pushsp(2 * sizeof(struct iorec
*));
_display
.frame
[0].locvars
+= 8; /* local offsets are negative */
*(struct iorec
**)(_display
.frame
[0].locvars
- 4) = OUTPUT
;
*(struct iorec
**)(_display
.frame
[0].locvars
- 8) = INPUT
;
stp
= (struct stack
*)pushsp(sizeof(struct stack
));
_dp
= &_display
.frame
[0];
_dp
+= 1; /* enter local scope */
stp
->odisp
= *_dp
; /* save old display value */
tl
= *pc
.ucp
++; /* tl = name size */
stp
->entry
= pc
.hdrp
; /* pointer to entry info */
tl1
= *pc
.lp
++; /* tl1 = local variable size */
pc
.lp
++; /* skip over number of args */
_lino
= *pc
.usp
++; /* set new lino */
pc
.cp
+= tl
; /* skip over name text */
stp
->file
= curfile
; /* save active file */
tcp
= pushsp(tl1
); /* tcp = new top of stack */
blkclr(tl1
, tcp
); /* zero stack frame */
tcp
+= tl1
; /* offsets of locals are neg */
_dp
->locvars
= tcp
; /* set new display pointer */
stp
->tos
= pushsp(0); /* set top of stack pointer */
PCLOSE(_dp
->locvars
); /* flush & close local files */
curfile
= stp
->file
; /* restore old active file */
*_dp
= stp
->odisp
; /* restore old display entry */
if (_dp
== &_display
.frame
[1])
return; /* exiting main proc ??? */
_lino
= stp
->lino
; /* restore lino, pc, dp */
popsp(stp
->entry
->framesze
+ /* pop local vars */
sizeof(struct stack
) + /* pop stack frame */
stp
->entry
->nargs
); /* pop parms */
tcp
= base
+ *pc
.lp
++;/* calc new entry point */
tcp
= base
+ *(long *)tcp
;
stp
= (struct stack
*)pushsp(sizeof(struct stack
));
stp
->lino
= _lino
; /* save lino, pc, dp */
_dp
= &_display
.frame
[tl
]; /* set up new display ptr */
tl
= *pc
.cp
++; /* tl = number of args */
tfp
= (struct formalrtn
*)popaddr();
stp
= (struct stack
*)pushsp(sizeof(struct stack
));
stp
->lino
= _lino
; /* save lino, pc, dp */
pc
.cp
= tfp
->entryaddr
; /* calc new entry point */
ERROR(ENARGS
, tl
/ sizeof(int));
_dp
= &_display
.frame
[tfp
->cbn
];/* new display ptr */
blkcpy(sizeof(struct disp
) * tfp
->cbn
,
&_display
.frame
[1], &tfp
->disp
[tfp
->cbn
]);
blkcpy(sizeof(struct disp
) * tfp
->cbn
,
&tfp
->disp
[0], &_display
.frame
[1]);
tl
= *pc
.cp
++; /* tl = size of return obj */
tfp
= *(struct formalrtn
**)(tcp
+ tl
);
blkcpy(tl
, tcp
, tcp
+ sizeof(struct formalrtn
*));
popsp(sizeof(struct formalrtn
*));
blkcpy(sizeof(struct disp
) * tfp
->cbn
,
&tfp
->disp
[tfp
->cbn
], &_display
.frame
[1]);
tfp
= (struct formalrtn
*)popaddr();
tfp
->cbn
= *pc
.cp
++; /* blk number of routine */
tcp
= base
+ *pc
.lp
++;/* calc new entry point */
tfp
->entryaddr
= base
+ *(long *)tcp
;
blkcpy(sizeof(struct disp
) * tfp
->cbn
,
&_display
.frame
[1], &tfp
->disp
[0]);
tstp
= _display
.frame
[*pc
.cp
++].stp
; /* ptr to
if (_dp
== &_display
.frame
[1])
ERROR(EGOTO
); /* exiting prog ??? */
PCLOSE(_dp
->locvars
); /* close local files */
curfile
= stp
->file
; /* restore active file */
*_dp
= stp
->odisp
; /* old display entry */
_dp
= stp
->dp
; /* restore dp */
/* pop locals, stack frame, parms, and return values */
popsp(stp
->tos
- pushsp(0));
if (_dp
->stp
->tos
!= pushsp(0))
_lino
= *pc
.cp
++; /* set line number */
LINO(); /* inc statement count */
tl2
= *pc
.cp
++; /* tc has jump opcode */
tl
= *pc
.usp
++; /* tl has comparison length */
tl1
= (tl
+ 1) & ~1; /* tl1 has arg stack length */
tcp
= pushsp(0); /* tcp pts to first arg */
tl
= RELEQ(tl
, tcp
+ tl1
, tcp
);
tl
= RELNE(tl
, tcp
+ tl1
, tcp
);
tl
= RELSLT(tl
, tcp
+ tl1
, tcp
);
tl
= RELSGT(tl
, tcp
+ tl1
, tcp
);
tl
= RELSLE(tl
, tcp
+ tl1
, tcp
);
tl
= RELSGE(tl
, tcp
+ tl1
, tcp
);
tl2
= *pc
.cp
++; /* tc has jump opcode */
tl1
= *pc
.usp
++; /* tl1 has comparison length */
tcp
= pushsp(0); /* tcp pts to first arg */
tl
= RELEQ(tl1
, tcp
+ tl1
, tcp
);
tl
= RELNE(tl1
, tcp
+ tl1
, tcp
);
tl
= RELTLT(tl1
, tcp
+ tl1
, tcp
);
tl
= RELTGT(tl1
, tcp
+ tl1
, tcp
);
tl
= RELTLE(tl1
, tcp
+ tl1
, tcp
);
tl
= RELTGE(tl1
, tcp
+ tl1
, tcp
);
*(short *)popaddr() = tl
;
*(short *)popaddr() = tl
;
*(double *)popaddr() = tl
;
*(double *)popaddr() = tl
;
*(double *)popaddr() = td
;
blkcpy(tl
, tcp
, *(char **)(tcp
+ tl1
));
popsp(tl1
+ sizeof(char *));
tl
= *pc
.cp
++; /* tl has shift amount */
tl1
= (pop2() - *pc
.sp
++) << tl
;
pushaddr(popaddr() + tl1
);
tl
= *pc
.cp
++; /* tl has shift amount */
tl1
= (pop4() - *pc
.sp
++) << tl
;
pushaddr(popaddr() + tl1
);
tl
= *pc
.cp
++; /* tl has element size */
tl1
= pop2(); /* index */
SUBSC(tl1
, tl2
, *pc
.usp
++); /* range check */
pushaddr(popaddr() + (tl1
- tl2
) * tl
);
tl
= *pc
.cp
++; /* tl has element size */
tl1
= pop4(); /* index */
SUBSC(tl1
, tl2
, *pc
.usp
++); /* range check */
pushaddr(popaddr() + (tl1
- tl2
) * tl
);
push4(tl
>= 0 ? tl
: -tl
);
push8(td
>= 0.0 ? td
: -td
);
tcp
= _display
.raw
[*pc
.ucp
++];
push2(*(tcp
+ *pc
.sp
++));
tcp
= _display
.raw
[*pc
.ucp
++];
push4(*(tcp
+ *pc
.sp
++));
tcp
= _display
.raw
[*pc
.ucp
++];
push2(*(short *)(tcp
+ *pc
.sp
++));
tcp
= _display
.raw
[*pc
.ucp
++];
push4(*(short *)(tcp
+ *pc
.sp
++));
tcp
= _display
.raw
[*pc
.ucp
++];
push4(*(long *)(tcp
+ *pc
.sp
++));
tcp
= _display
.raw
[*pc
.ucp
++];
push8(*(double *)(tcp
+ *pc
.sp
++));
tcp
= _display
.raw
[*pc
.ucp
++];
tcp
= _display
.raw
[*pc
.ucp
++];
pushaddr(tcp
+ *pc
.sp
++);
tcp
= _display
.raw
[*pc
.ucp
++];
push2(*(tcp
+ *pc
.lp
++));
tcp
= _display
.raw
[*pc
.ucp
++];
push4(*(tcp
+ *pc
.lp
++));
tcp
= _display
.raw
[*pc
.ucp
++];
push2(*(short *)(tcp
+ *pc
.lp
++));
tcp
= _display
.raw
[*pc
.ucp
++];
push4(*(short *)(tcp
+ *pc
.lp
++));
tcp
= _display
.raw
[*pc
.ucp
++];
push4(*(long *)(tcp
+ *pc
.lp
++));
tcp
= _display
.raw
[*pc
.ucp
++];
push8(*(double *)(tcp
+ *pc
.lp
++));
tcp
= _display
.raw
[*pc
.ucp
++];
tcp
= _display
.raw
[*pc
.ucp
++];
pushaddr(tcp
+ *pc
.lp
++);
push2(*(short *)(popaddr()));
push4(*(short *)(popaddr()));
push4(*(long *)(popaddr()));
push8(*(double *)(popaddr()));
tcp1
= pushsp((tl
+ 1) & ~1);
push2(RANG4(tl1
, tl
, *pc
.sp
++));
push4(RANG4(tl1
, tl
, *pc
.sp
++));
push4(RANG4(tl1
, tl
, *pc
.lp
++));
push2(RANG4(tl1
, tl
, *pc
.lp
++));
push4(RSNG4(tl
, *pc
.lp
++));
push2(RSNG4(tl
, *pc
.lp
++));
_pcpcount
= (long *)calloc(_cntrs
+ 1, sizeof(long));
tl
= *pc
.cp
++; /* tl = number of cases */
tsp
= pc
.sp
+ tl
; /* ptr to end of jump table */
tcp
= (char *)tsp
; /* tcp = ptr to case values */
tl1
= pop2(); /* tl1 = element to find */
for(; tl
> 0; tl
--) /* look for element */
if (tl
== 0) /* default case => error */
tl
= *pc
.cp
++; /* tl = number of cases */
tsp
= pc
.sp
+ tl
; /* ptr to end of jump table */
tsp1
= tsp
; /* tsp1 = ptr to case values */
tl1
= (unsigned short)pop2();/* tl1 = element to find */
for(; tl
> 0; tl
--) /* look for element */
if (tl
== 0) /* default case => error */
tl
= *pc
.cp
++; /* tl = number of cases */
tsp
= pc
.sp
+ tl
; /* ptr to end of jump table */
tlp
= (long *)tsp
; /* tlp = ptr to case values */
tl1
= pop4(); /* tl1 = element to find */
for(; tl
> 0; tl
--) /* look for element */
if (tl
== 0) /* default case => error */
tl
= *pc
.cp
++; /* tl has comparison length */
tcp
= pushsp(0); /* tcp pts to first arg */
ADDT(tcp
+ tl
, tcp
+ tl
, tcp
, tl
>> 2);
tl
= *pc
.cp
++; /* tl has comparison length */
tcp
= pushsp(0); /* tcp pts to first arg */
SUBT(tcp
+ tl
, tcp
+ tl
, tcp
, tl
>> 2);
tl
= *pc
.cp
++; /* tl has comparison length */
tcp
= pushsp(0); /* tcp pts to first arg */
MULT(tcp
+ tl
, tcp
+ tl
, tcp
, tl
>> 2);
tl
= *pc
.cp
++; /* tl has number of args */
tl
= *pc
.cp
++; /* tl has number of args */
tcp
= pushsp(0) + tl1
; /* tcp pts to result space */
tl
= *pc
.cp
++; /* tl has comparison length */
tcp
= pushsp(0); /* tcp pts to set */
tl
= *pc
.cp
++; /* tl has comparison length */
tl1
= pop4(); /* tl1 is the element */
tcp
= pushsp(0); /* tcp pts to set */
tl2
= *pc
.usp
++; /* lower bound */
tl1
= IN(tl1
, tl2
, *pc
.usp
++, tcp
);
tcp
= (char *)pop4(); /* tcp = ptr to index var */
if (*tcp
< pop4()) { /* still going up */
*tcp
+= 1; /* inc index var */
pc
.cp
+= *pc
.sp
;/* return to top of loop */
pc
.sp
++; /* else fall through */
tsp
= (short *)pop4(); /* tsp = ptr to index var */
if (*tsp
< pop4()) { /* still going up */
*tsp
+= 1; /* inc index var */
pc
.cp
+= *pc
.sp
;/* return to top of loop */
pc
.sp
++; /* else fall through */
tlp
= (long *)pop4(); /* tlp = ptr to index var */
if (*tlp
< pop4()) { /* still going up */
*tlp
+= 1; /* inc index var */
pc
.cp
+= *pc
.sp
;/* return to top of loop */
pc
.sp
++; /* else fall through */
tcp
= (char *)pop4(); /* tcp = ptr to index var */
if (*tcp
> pop4()) { /* still going down */
*tcp
-= 1; /* dec index var */
pc
.cp
+= *pc
.sp
;/* return to top of loop */
pc
.sp
++; /* else fall through */
tsp
= (short *)pop4(); /* tsp = ptr to index var */
if (*tsp
> pop4()) { /* still going down */
*tsp
-= 1; /* dec index var */
pc
.cp
+= *pc
.sp
;/* return to top of loop */
pc
.sp
++; /* else fall through */
tlp
= (long *)pop4(); /* tlp = ptr to index var */
if (*tlp
> pop4()) { /* still going down */
*tlp
-= 1; /* dec index var */
pc
.cp
+= *pc
.sp
;/* return to top of loop */
pc
.sp
++; /* else fall through */
push2(READE(curfile
, base
+ *pc
.lp
++));
pushaddr(NAM(tl
, base
+ *pc
.lp
++));
push4(MAX(tl1
, tl
, *pc
.usp
++));
push4(tl1
< tl
? tl1
: tl
);
curfile
= UNIT(popaddr());
pushaddr(FNIL(popaddr()));
pushaddr(ACTFILE(curfile
));
tl
= *pc
.cp
++; /* tl = size of char array */
tcp
= popaddr(); /* tcp = addr of char array */
tl1
= pop4(); /* tl1 = argv subscript */
tl
= *pc
.cp
++; /* tl = size being disposed */
tcp
= popaddr(); /* ptr to ptr being disposed */
*(char **)tcp
= (char *)0;
tl
= *pc
.cp
++; /* tl = size being new'ed */
tcp
= popaddr(); /* ptr to ptr being new'ed */
push2(SUCC(tl1
, tl
, *pc
.sp
++));
push4(SUCC(tl1
, tl
, *pc
.sp
++));
push4(SUCC(tl1
, tl
, *pc
.lp
++));
push2(PRED(tl1
, tl
, *pc
.sp
++));
push4(PRED(tl1
, tl
, *pc
.sp
++));
push4(PRED(tl1
, tl
, *pc
.lp
++));