/* xlclose - create a function closure */ LVAL xlclose(name,type,fargs,body,env,fenv) LVAL name,type,fargs,body,env,fenv; { LVAL closure,key,arg,def,svar,new,last; char keyname[STRMAX+2]; /* protect some pointers */ xlsave1(closure); /* create the closure object */ closure = newclosure(name,type,env,fenv); setlambda(closure,fargs); setbody(closure,body); /* handle each required argument */ last = NIL; while (consp(fargs) && (arg = car(fargs)) && !iskey(arg)) { /* make sure the argument is a symbol */ if (!symbolp(arg)) badarglist(); /* create a new argument list entry */ new = cons(arg,NIL); /* link it into the required argument list */ if (last) rplacd(last,new); else setargs(closure,new); last = new; /* move the formal argument list pointer ahead */ fargs = cdr(fargs); } /* check for the '&optional' keyword */ if (consp(fargs) && car(fargs) == lk_optional) { fargs = cdr(fargs); /* handle each optional argument */ last = NIL; while (consp(fargs) && (arg = car(fargs)) && !iskey(arg)) { /* get the default expression and specified-p variable */ def = svar = NIL; if (consp(arg)) { if (def = cdr(arg)) if (consp(def)) { if (svar = cdr(def)) if (consp(svar)) { svar = car(svar); if (!symbolp(svar)) badarglist(); } else badarglist(); def = car(def); } else badarglist(); arg = car(arg); } /* make sure the argument is a symbol */ if (!symbolp(arg)) badarglist(); /* create a fully expanded optional expression */ new = cons(cons(arg, cons(def, cons(svar,NIL))), NIL); /* link it into the optional argument list */ if (last) rplacd(last,new); else setoargs(closure,new); last = new; /* move the formal argument list pointer ahead */ fargs = cdr(fargs); } } /* check for the '&rest' keyword */ if (consp(fargs) && car(fargs) == lk_rest) { fargs = cdr(fargs); /* get the &rest argument */ if (consp(fargs) && (arg = car(fargs)) && !iskey(arg) && symbolp(arg)) setrest(closure,arg); else badarglist(); /* move the formal argument list pointer ahead */ fargs = cdr(fargs); } /* check for the '&key' keyword */ if (consp(fargs) && car(fargs) == lk_key) { fargs = cdr(fargs); /* handle each key argument */ last = NIL; while (consp(fargs) && (arg = car(fargs)) && !iskey(arg)) { /* get the default expression and specified-p variable */ def = svar = NIL; if (consp(arg)) { if (def = cdr(arg)) if (consp(def)) { if (svar = cdr(def)) if (consp(svar)) { svar = car(svar); if (!symbolp(svar)) badarglist(); } else badarglist(); def = car(def); } else badarglist(); arg = car(arg); } /* get the keyword and the variable */ if (consp(arg)) { key = car(arg); if (!symbolp(key)) badarglist(); if (arg = cdr(arg)) if (consp(arg)) arg = car(arg); else badarglist(); } else if (symbolp(arg)) { strcpy(keyname,":"); strcat(keyname,getstring(getpname(arg))); key = xlenter(keyname); } /* make sure the argument is a symbol */ if (!symbolp(arg)) badarglist(); /* create a fully expanded key expression */ new = cons(cons(key, cons(arg, cons(def, cons(svar, NIL)))), NIL); /* link it into the optional argument list */ if (last) rplacd(last,new); else setkargs(closure,new); last = new; /* move the formal argument list pointer ahead */ fargs = cdr(fargs); } } /* check for the '&allow-other-keys' keyword */ if (consp(fargs) && car(fargs) == lk_allow_other_keys) fargs = cdr(fargs); /* this is the default anyway */ /* check for the '&aux' keyword */ if (consp(fargs) && car(fargs) == lk_aux) { fargs = cdr(fargs); /* handle each aux argument */ last = NIL; while (consp(fargs) && (arg = car(fargs)) && !iskey(arg)) { /* get the initial value */ def = NIL; if (consp(arg)) { if (def = cdr(arg)) if (consp(def)) def = car(def); else badarglist(); arg = car(arg); } /* make sure the argument is a symbol */ if (!symbolp(arg)) badarglist(); /* create a fully expanded aux expression */ new = cons(cons(arg, cons(def, NIL)), NIL); /* link it into the aux argument list */ if (last) rplacd(last,new); else setaargs(closure,new); last = new; /* move the formal argument list pointer ahead */ fargs = cdr(fargs); } } /* make sure this is the end of the formal argument list */ if (fargs) badarglist(); /* restore the stack */ xlpop(); /* return the new closure */ return (closure); }