⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xlobj.c

📁 Audacity是一款用於錄音和編輯聲音的、免費的開放源碼軟體。它可以執行於Mac OS X、Microsoft Windows、GNU/Linux和其它作業系統
💻 C
字号:
/* xlobj - xlisp object functions *//*	Copyright (c) 1985, by David Michael Betz        All Rights Reserved        Permission is granted for unrestricted non-commercial use	*//* CHANGE LOG * -------------------------------------------------------------------- * 28Apr03  dm  eliminate some compiler warnings */#include "xlisp.h"/* external variables */extern LVAL s_stdout,s_lambda;/* local variables */static LVAL s_self,k_new,k_isnew;static LVAL class,object;/* instance variable numbers for the class 'Class' */#define MESSAGES	0	/* list of messages */#define IVARS		1	/* list of instance variable names */#define CVARS		2	/* list of class variable names */#define CVALS		3	/* list of class variable values */#define SUPERCLASS	4	/* pointer to the superclass */#define IVARCNT		5	/* number of class instance variables */#define IVARTOTAL	6	/* total number of instance variables *//* number of instance variables for the class 'Class' */#define CLASSSIZE	7/* forward declarations */FORWARD LOCAL LVAL entermsg(LVAL cls, LVAL msg);FORWARD LOCAL LVAL xsendmsg(LVAL obj, LVAL cls, LVAL sym);FORWARD LOCAL LVAL evmethod(LVAL obj, LVAL msgcls, LVAL method);FORWARD LOCAL int getivcnt(LVAL cls, int ivar);FORWARD LOCAL int listlength(LVAL list);/* xsend - send a message to an object */LVAL xsend(void){    LVAL obj;    obj = xlgaobject();    return (xsendmsg(obj,getclass(obj),xlgasymbol()));}/* xsendsuper - send a message to the superclass of an object */LVAL xsendsuper(void){    LVAL env,p;    for (env = xlenv; env; env = cdr(env))        if ((p = car(env)) && objectp(car(p)))            return (xsendmsg(car(p),                            getivar(cdr(p),SUPERCLASS),                            xlgasymbol()));    xlfail("not in a method");    return NULL; /* never called */}/* xlclass - define a class */LVAL xlclass(char *name, int vcnt){    LVAL sym,cls;    /* create the class */    sym = xlenter(name);    cls = newobject(class,CLASSSIZE);    setvalue(sym,cls);    /* set the instance variable counts */    setivar(cls,IVARCNT,cvfixnum((FIXTYPE)vcnt));    setivar(cls,IVARTOTAL,cvfixnum((FIXTYPE)vcnt));    /* set the superclass to 'Object' */    setivar(cls,SUPERCLASS,object);    /* return the new class */    return (cls);}/* xladdivar - enter an instance variable */void xladdivar(LVAL cls, char *var){    setivar(cls,IVARS,cons(xlenter(var),getivar(cls,IVARS)));}/* xladdmsg - add a message to a class */void xladdmsg(LVAL cls, char *msg, int offset){    extern FUNDEF funtab[];    LVAL mptr;    /* enter the message selector */    mptr = entermsg(cls,xlenter(msg));    /* store the method for this message */    rplacd(mptr,cvsubr(funtab[offset].fd_subr,funtab[offset].fd_type,offset));}/* xlobgetvalue - get the value of an instance variable */int xlobgetvalue(LVAL pair, LVAL sym, LVAL *pval){    LVAL cls,names;    int ivtotal,n;    /* find the instance or class variable */    for (cls = cdr(pair); objectp(cls); cls = getivar(cls,SUPERCLASS)) {        /* check the instance variables */        names = getivar(cls,IVARS);        ivtotal = getivcnt(cls,IVARTOTAL);        for (n = ivtotal - getivcnt(cls,IVARCNT); n < ivtotal; ++n) {            if (car(names) == sym) {                *pval = getivar(car(pair),n);                return (TRUE);            }            names = cdr(names);        }        /* check the class variables */        names = getivar(cls,CVARS);        for (n = 0; consp(names); ++n) {            if (car(names) == sym) {                *pval = getelement(getivar(cls,CVALS),n);                return (TRUE);            }            names = cdr(names);        }    }    /* variable not found */    return (FALSE);}/* xlobsetvalue - set the value of an instance variable */int xlobsetvalue(LVAL pair, LVAL sym, LVAL val){    LVAL cls,names;    int ivtotal,n;    /* find the instance or class variable */    for (cls = cdr(pair); objectp(cls); cls = getivar(cls,SUPERCLASS)) {        /* check the instance variables */        names = getivar(cls,IVARS);        ivtotal = getivcnt(cls,IVARTOTAL);        for (n = ivtotal - getivcnt(cls,IVARCNT); n < ivtotal; ++n) {            if (car(names) == sym) {                setivar(car(pair),n,val);                return (TRUE);            }            names = cdr(names);        }        /* check the class variables */        names = getivar(cls,CVARS);        for (n = 0; consp(names); ++n) {            if (car(names) == sym) {                setelement(getivar(cls,CVALS),n,val);                return (TRUE);            }            names = cdr(names);        }    }    /* variable not found */    return (FALSE);}/* obisnew - default 'isnew' method */LVAL obisnew(void){    LVAL self;    self = xlgaobject();    xllastarg();    return (self);}/* obclass - get the class of an object */LVAL obclass(void){    LVAL self;    self = xlgaobject();    xllastarg();    return (getclass(self));}/* obshow - show the instance variables of an object */LVAL obshow(void){    LVAL self,fptr,cls,names;    int ivtotal,n;    /* get self and the file pointer */    self = xlgaobject();    fptr = (moreargs() ? xlgetfile() : getvalue(s_stdout));    xllastarg();    /* get the object's class */    cls = getclass(self);    /* print the object and class */    xlputstr(fptr,"Object is ");    xlprint(fptr,self,TRUE);    xlputstr(fptr,", Class is ");    xlprint(fptr,cls,TRUE);    xlterpri(fptr);    /* print the object's instance variables */    for (; cls; cls = getivar(cls,SUPERCLASS)) {        names = getivar(cls,IVARS);        ivtotal = getivcnt(cls,IVARTOTAL);        for (n = ivtotal - getivcnt(cls,IVARCNT); n < ivtotal; ++n) {            xlputstr(fptr,"  ");            xlprint(fptr,car(names),TRUE);            xlputstr(fptr," = ");            xlprint(fptr,getivar(self,n),TRUE);            xlterpri(fptr);            names = cdr(names);        }    }    /* return the object */    return (self);}/* clnew - create a new object instance */LVAL clnew(void){    LVAL self;    self = xlgaobject();    return (newobject(self,getivcnt(self,IVARTOTAL)));}/* clisnew - initialize a new class */LVAL clisnew(void){    LVAL self,ivars,cvars,super;    int n;    /* get self, the ivars, cvars and superclass */    self = xlgaobject();    ivars = xlgalist();    cvars = (moreargs() ? xlgalist() : NIL);    super = (moreargs() ? xlgaobject() : object);    xllastarg();    /* store the instance and class variable lists and the superclass */    setivar(self,IVARS,ivars);    setivar(self,CVARS,cvars);    setivar(self,CVALS,(cvars ? newvector(listlength(cvars)) : NIL));    setivar(self,SUPERCLASS,super);    /* compute the instance variable count */    n = listlength(ivars);    setivar(self,IVARCNT,cvfixnum((FIXTYPE)n));    n += getivcnt(super,IVARTOTAL);    setivar(self,IVARTOTAL,cvfixnum((FIXTYPE)n));    /* return the new class object */    return (self);}/* clanswer - define a method for answering a message */LVAL clanswer(void){    LVAL self,msg,fargs,code,mptr;    /* message symbol, formal argument list and code */    self = xlgaobject();    msg = xlgasymbol();    fargs = xlgalist();    code = xlgalist();    xllastarg();    /* make a new message list entry */    mptr = entermsg(self,msg);    /* setup the message node */    xlprot1(fargs);    fargs = cons(s_self,fargs); /* add 'self' as the first argument */    rplacd(mptr,xlclose(msg,s_lambda,fargs,code,NIL,NIL));    xlpop();    /* return the object */    return (self);}/* entermsg - add a message to a class */LOCAL LVAL entermsg(LVAL cls, LVAL msg){    LVAL lptr,mptr;    /* lookup the message */    for (lptr = getivar(cls,MESSAGES); lptr; lptr = cdr(lptr))        if (car(mptr = car(lptr)) == msg)            return (mptr);    /* allocate a new message entry if one wasn't found */    xlsave1(mptr);    mptr = consa(msg);    setivar(cls,MESSAGES,cons(mptr,getivar(cls,MESSAGES)));    xlpop();    /* return the symbol node */    return (mptr);}/* xsendmsg - send a message to an object */LOCAL LVAL xsendmsg(LVAL obj, LVAL cls, LVAL sym){    LVAL msg=NULL,msgcls,method,val,p;    /* look for the message in the class or superclasses */    for (msgcls = cls; msgcls; ) {        /* lookup the message in this class */        for (p = getivar(msgcls,MESSAGES); p; p = cdr(p))            if ((msg = car(p)) && car(msg) == sym)                goto send_message;        /* look in class's superclass */        msgcls = getivar(msgcls,SUPERCLASS);    }    /* message not found */    xlerror("no method for this message",sym);send_message:    /* insert the value for 'self' (overwrites message selector) */    *--xlargv = obj;    ++xlargc;        /* invoke the method */    if ((method = cdr(msg)) == NULL)        xlerror("bad method",method);    switch (ntype(method)) {    case SUBR:        val = (*getsubr(method))();        break;    case CLOSURE:        if (gettype(method) != s_lambda)            xlerror("bad method",method);        val = evmethod(obj,msgcls,method);        break;    default:        xlerror("bad method",method);    }    /* after creating an object, send it the ":isnew" message */    if (car(msg) == k_new && val) {        xlprot1(val);        xsendmsg(val,getclass(val),k_isnew);        xlpop();    }        /* return the result value */    return (val);}/* evmethod - evaluate a method */LOCAL LVAL evmethod(LVAL obj, LVAL msgcls, LVAL method){    LVAL oldenv,oldfenv,cptr,name,val=NULL;    XLCONTEXT cntxt;    /* protect some pointers */    xlstkcheck(3);    xlsave(oldenv);    xlsave(oldfenv);    xlsave(cptr);    /* create an 'object' stack entry and a new environment frame */    oldenv = xlenv;    oldfenv = xlfenv;    xlenv = cons(cons(obj,msgcls),closure_getenv(method));    xlenv = xlframe(xlenv);    xlfenv = getfenv(method);    /* bind the formal parameters */    xlabind(method,xlargc,xlargv);    /* setup the implicit block */    if ((name = getname(method)))        xlbegin(&cntxt,CF_RETURN,name);    /* execute the block */    if (name && setjmp(cntxt.c_jmpbuf))        val = xlvalue;    else        for (cptr = getbody(method); consp(cptr); cptr = cdr(cptr))            val = xleval(car(cptr));    /* finish the block context */    if (name)        xlend(&cntxt);    /* restore the environment */    xlenv = oldenv;    xlfenv = oldfenv;    /* restore the stack */    xlpopn(3);    /* return the result value */    return (val);}/* getivcnt - get the number of instance variables for a class */LOCAL int getivcnt(LVAL cls, int ivar){    LVAL cnt;    if ((cnt = getivar(cls,ivar)) == NIL || !fixp(cnt))        xlfail("bad value for instance variable count");    return ((int)getfixnum(cnt));}/* listlength - find the length of a list */LOCAL int listlength(LVAL list){    int len;    for (len = 0; consp(list); len++)        list = cdr(list);    return (len);}/* obsymbols - initialize symbols */void obsymbols(void){    /* enter the object related symbols */    s_self  = xlenter("SELF");    k_new   = xlenter(":NEW");    k_isnew = xlenter(":ISNEW");    /* get the Object and Class symbol values */    object = getvalue(xlenter("OBJECT"));    class  = getvalue(xlenter("CLASS"));}/* xloinit - object function initialization routine */void xloinit(void){    /* create the 'Class' object */    class = xlclass("CLASS",CLASSSIZE);    setelement(class,0,class);    /* create the 'Object' object */    object = xlclass("OBJECT",0);    /* finish initializing 'class' */    setivar(class,SUPERCLASS,object);    xladdivar(class,"IVARTOTAL");	/* ivar number 6 */    xladdivar(class,"IVARCNT");		/* ivar number 5 */    xladdivar(class,"SUPERCLASS");	/* ivar number 4 */    xladdivar(class,"CVALS");		/* ivar number 3 */    xladdivar(class,"CVARS");		/* ivar number 2 */    xladdivar(class,"IVARS");		/* ivar number 1 */    xladdivar(class,"MESSAGES");	/* ivar number 0 */    xladdmsg(class,":NEW",FT_CLNEW);    xladdmsg(class,":ISNEW",FT_CLISNEW);    xladdmsg(class,":ANSWER",FT_CLANSWER);    /* finish initializing 'object' */    setivar(object,SUPERCLASS,NIL);    xladdmsg(object,":ISNEW",FT_OBISNEW);    xladdmsg(object,":CLASS",FT_OBCLASS);    xladdmsg(object,":SHOW",FT_OBSHOW);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -