henesyinit from p9f47575dc5 years agoHistory
433 lines · 7.8 KB · C
RawDownload
#include <u.h>#include <libc.h>#include "system.h"# include "stdio.h"# include "defines.h"# include "object.h"# include "path.h"#ifndef Plan9#include "njerq.h"#endif# include "graphics.h"# include "dict.h" static	struct	object	stack[EXEC_STACK_LIMIT] ;static	int		stacktop ; voidexecstackinit(void){ 	stack[0] = makefile(stdin,AC_READONLY,XA_EXECUTABLE) ;	currentfile = stdin;	stacktop = 1 ;} voidexec_invalid(char *mem_bound){	int	i ; 	for ( i=0 ; i<stacktop ; i++ )		invalid(stack[i],mem_bound) ;} voidexecpush(struct object object){	if ( stacktop == EXEC_STACK_LIMIT )		pserror("execstackoverflow", "execpush") ;	stack[stacktop++] = object ; } voidexecute(void){	int		old_stacktop ;	register struct	object	object ;	int	offset ;	FILE	*sp ; 	old_stacktop = stacktop ;	while ( stacktop >= old_stacktop ){		if(prolog){			if(pageflag==1 || skipflag==2)			if(pageno != page || skipflag){				skiptopage();				pageflag=0;				/*pageflag++;*/				skipflag = 0;			}		}		object = stack[stacktop-1] ;		if ( object.xattr == XA_LITERAL ){			push(object) ;			stacktop-- ;		}		else switch(object.type){		case OB_ARRAY :			switch(object.value.v_array.length){			case 0 :				stacktop-- ;				break ;			case 1 :				if(object.value.v_array.object[0].type ==				 OB_ARRAY&&object.value.v_array.object[0].xattr ==				 XA_EXECUTABLE){					push(object.value.v_array.object[0]) ;					stacktop-- ;				}				else stack[stacktop-1]=object.value.v_array.object[0];				break ;			default :				stack[stacktop-1].value.v_array.object++ ;				stack[stacktop-1].value.v_array.length-- ;				if(stack[stacktop-1].value.v_array.object[-1].type				   == OB_ARRAY  &&				   stack[stacktop-1].value.v_array.object[-1].xattr				   == XA_EXECUTABLE)				  push(stack[stacktop-1].value.v_array.object[-1]);				else execpush(stack[stacktop-1].value.v_array.object[-1]) ;				break ;			}			break ; 		case OB_FILE :			if(restart){				prolog=1;				restart=0;			}			object = scanner(stack[stacktop-1].value.v_file.fp) ;			if ( object.type == OB_NONE ){				fclose(stack[stacktop-1].value.v_file.fp) ;				stacktop-- ;			}			else{				if ( object.type == OB_ARRAY  &&				    object.xattr == XA_EXECUTABLE )					push(object) ;				else execpush(object) ;			}			break ; 		case OB_BOOLEAN :		case OB_DICTIONARY :		case OB_FONTID :		case OB_INT :		case OB_MARK :		case OB_REAL :		case OB_SAVE :			push(object) ;			stacktop-- ;			break ; 		case OB_NAME :			stack[stacktop-1] = dictstackget(object,"undefined:execute") ;			break ; 		case OB_OPERATOR :			stacktop-- ;			(*object.value.v_operator)() ;			break ;  		case OB_NULL :			break ; 		case OB_STRING :			sp = sopen(stack[stacktop-1].value.v_string) ;			object = scanner(sp) ;			if ( object.type == OB_NONE ){				f_close(sp) ;				stacktop-- ;			}			else {				offset = stell(sp) ;				stack[stacktop-1].value.v_string.chars += offset ;				stack[stacktop-1].value.v_string.length -= offset ;					if ( object.type == OB_ARRAY  &&				    object.xattr == XA_EXECUTABLE )					push(object) ;				else execpush(object) ;			}			break ; 		default :		fprintf(stderr,"execute type %d\n",object.type);			error("bad case in execute") ;		}	}} voidexecOP(void){	struct object object;	object = pop();	execpush(object) ;} voidarrayforall(void){ 	if ( stack[stacktop-1].value.v_array.length == 0 )		stacktop -= 3 ;	else {		stack[stacktop-1].value.v_array.object++ ;		stack[stacktop-1].value.v_array.length-- ;		push(stack[stacktop-1].value.v_array.object[-1]) ;		stacktop++ ;		execpush(stack[stacktop-3]) ;	}} voidstringforall(void){ 	if ( stack[stacktop-1].value.v_string.length == 0 )		stacktop -= 3 ;	else {		stack[stacktop-1].value.v_string.chars++ ;		stack[stacktop-1].value.v_string.length-- ;		push(makeint((int)stack[stacktop-1].value.v_string.chars[-1])) ;		stacktop++ ;		execpush(stack[stacktop-3]) ;	}} voiddictforall(void){ 	if ( stack[stacktop-1].value.v_int == stack[stacktop-2].value.v_dict->cur )		stacktop -= 4 ;	else {	 push(stack[stacktop-2].value.v_dict->dictent[stack[stacktop-1].value.v_int].key) ;	 push(stack[stacktop-2].value.v_dict->dictent[stack[stacktop-1].value.v_int].value) ;		stack[stacktop-1].value.v_int++ ;		stacktop++ ;		execpush(stack[stacktop-4]) ;	}} voidxfor(void){	enum	bool	up ;	struct object object; 	push(stack[stacktop-2]) ;	push(makeint(0)) ;	gtOP() ;	object = pop();	up = object.value.v_boolean ;	push(stack[stacktop-1]) ;	push(stack[stacktop-3]) ;	if ( up == TRUE )		gtOP() ;	else		ltOP() ;	object = pop();	if ( object.value.v_boolean == TRUE )		stacktop -= 5 ;	else {		push(stack[stacktop-1]) ;		push(stack[stacktop-1]) ;		push(stack[stacktop-2]) ;		addOP() ;		stack[stacktop-1] = pop() ;		stacktop++ ;		execpush(stack[stacktop-5]) ;	}} voidxrepeat(void){ 	if ( stack[stacktop-1].value.v_int-- == 0 )		stacktop -= 3 ;	else {		stacktop++ ;		execpush(stack[stacktop-3]) ;	}} voidxloop(void){ 	stacktop++ ;	execpush(stack[stacktop-2]) ;} voidexecstackOP(void){	int		i ;	struct	object	array ; 	array = pop() ;	if ( array.type != OB_ARRAY )		pserror("typecheck", "execstack") ;	if ( array.value.v_array.length < stacktop )		pserror("rangecheck", "execstack") ;	for ( i=0 ; i<stacktop ; i++ ){		SAVEITEM(array.value.v_array.object[i]) ;		array.value.v_array.object[i] = stack[i] ;	}	array.value.v_array.length = stacktop ;	push(array) ;} voidexitOP(void){	int		i ; 	for ( i=stacktop-1 ; i>=0 ; i-- ){		if ( stack[i].type == OB_FILE )			pserror("invalidexit", "exit") ;		if ( stack[i].type == OB_OPERATOR )			if ( (void (*)(void))stack[i].value.v_operator == loopnoop )				break ;			else if ( (void (*)(void))stack[i].value.v_operator == xstopped )				pserror("invalidexit", "exit") ;	}	if ( i >= 0 )		stacktop = i ;	else {		fprintf(stderr,"i=%d\n",i);		warning("no enclosing looping context") ;		execpush(makeoperator(quitOP)) ;	}} voidloopnoop(void){	error("loopnoop executed") ;} voidquitOP(void){	error("quit") ;} voidcountexecstackOP(void){	push(makeint(stacktop)) ;} voidxpathforall(void){	struct	element	*p, *next ;	struct	object	proc ; 	p = (struct element *)stack[stacktop-1].value.v_pointer ;	if ( p == NULL )		stacktop -= 6 ;	else {			switch(p->type){		case PA_MOVETO :			proc = stack[stacktop-2] ;			push(makereal(p->ppoint.x)) ;			push(makereal(p->ppoint.y)) ;			itransformOP() ;			next = p->next ;			break ; 		case PA_LINETO :			proc = stack[stacktop-3] ;			push(makereal(p->ppoint.x)) ;			push(makereal(p->ppoint.y)) ;			itransformOP() ;			next = p->next ;			break ; 		case PA_CURVETO :			proc = stack[stacktop-4] ;			push(makereal(p->ppoint.x)) ;			push(makereal(p->ppoint.y)) ;			itransformOP() ;			push(makereal(p->next->ppoint.x)) ;			push(makereal(p->next->ppoint.y)) ;			itransformOP() ;			push(makereal(p->next->next->ppoint.x)) ;			push(makereal(p->next->next->ppoint.y)) ;			itransformOP() ;			next = p->next->next->next ;			break ; 		case PA_CLOSEPATH :			proc = stack[stacktop-5] ;			next = p->next ;			break ; 		default :			error("bad case in xpathforall") ;		}		stack[stacktop-1].value.v_pointer = (char *)next ;		stacktop++ ;		execpush(proc) ;	}} voidcurrentfileOP(void){	int		i ;	for ( i=stacktop-1 ; i>=0 ; i-- )		if ( stack[i].type == OB_FILE )			break ;	if ( i < 0 )		push(makefile(NULL,AC_NONE,XA_LITERAL)) ;	else		push(stack[i]) ;} voidstoppedOP(void){ 	execpush(makeoperator(xstopped)) ;	execpush(pop()) ;} voidxstopped(void){ 	push(false) ;} voidstopOP(void){	int		i ; 	for ( i=stacktop-1 ; i>=0 ; i-- ){		if ( stack[i].type == OB_OPERATOR  &&		  (void (*)(void))stack[i].value.v_operator == xstopped )			break ;		if ( stack[i].type == OB_FILE )			fclose(stack[i].value.v_file.fp) ;	}	if ( i < 0 )		execpush(makeoperator(quitOP)) ;	else {		push(true) ;		stacktop = i ;	}} voidstartOP(void){}