static char *sccsid
= "@(#)lam1.c 35.3 7/8/81";
/**************************************************************************/
/* contents: LISP functions coded in C */
/* These include LISP primitives, numeric and boolean functions and */
/* predicates, some list-processing functions, i/o support functions */
/* and control flow functions (e.g. cont, break). */
/* There are two types of functions: lambda (prefixed "L") and nlambda */
/* Lambda's all call chkarg to insure that at least the minimum number */
/* of necessary arguments are on the namestack. */
/* All functions take their arguments from the namestack in a read- */
/* only manner, and return their results via the normal C value */
register lispval temp
, result
;
if (((typ
= TYPE(temp
)) == DTPR
) || (typ
== ATOM
) || HUNKP(temp
))
result
= inewint(temp
->i
);
} else if(Schainp
!=nil
&& typ
==ATOM
)
return(error("Bad arg to car",FALSE
));
register lispval temp
, result
;
if(temp
==nil
) return (nil
);
if (((typ
= TYPE(temp
)) == DTPR
) || HUNKP(temp
))
if(temp
->s
.CDR
==0) return(nil
);
errorh(Vermisc
,"Fell of the end of a bignum",nil
,FALSE
,5,lbot
->val
);
} else if(Schainp
!=nil
&& typ
==ATOM
)
return(error("Bad arg to cdr", FALSE
));
register lispval temp
, temp2
;
if ((typ
== DTPR
) || HUNKP(temp
))
errorh(Vermisc
,"Fell of the end of a bignum",nil
,FALSE
,5,lbot
->val
);
if(Schainp
!=nil
&& typ
==ATOM
)
return(errorh(Vermisc
,"Bad arg to cdr",nil
,FALSE
,5,temp
));
if ((typ
== DTPR
) || HUNKP(temp
))
temp2
= inewint(temp
->i
), temp
= temp2
;
else if(Schainp
!=nil
&& typ
==ATOM
)
return(errorh(Vermisc
,"Bad arg to car",nil
,FALSE
,5,temp
));
{ return(cxxr(0,2)); } /* cddr */
{ return(cxxr(1,2)); } /* caddr */
{ return(cxxr(0,3)); } /* cdddr */
{ return(cxxr(1,3)); } /* cadddr */
{ return(cxxr(0,4)); } /* cddddr */
{ return(cxxr(1,4)); } /* caddddr */
* Returns the num'th element of the list, by doing a caddddd...ddr
* where there are num-1 d's. If num<=0 or greater than the length of
* the list, we return nil.
if( TYPE(temp
= lbot
->val
) != INT
)
return (error ("First arg to nthelem must be a fixnum",FALSE
));
i
= temp
->i
; /* pick up the first arg */
++lbot
; /* fix lbot for call to cxxr() 'cadddd..r' */
register struct argent
*argp
= lbot
;
register lispval retp
, handy
;
error("First arg to scons must be an int.",FALSE
);
retp
->s
.CDR
= (lispval
) 0;
error("Currently you may only link sdots to sdots.",FALSE
);
register lispval handy
,newp
;
chkarg(1,"Bignum-to-lisp");
handy
= error(Vermisc
,"Non bignum argument to Bignum-to-list",
protect(newp
= newdot());
newp
->d
.car
= inewint(handy
->s
.I
);
if(handy
->s
.CDR
==nil
) break;
register struct argent
*argp
;
retp
->d
.car
= ((argp
= lbot
) -> val
);
retp
->d
.cdr
= argp
[1].val
;
{ register struct argent
*argp
;
register int typ
; register lispval first
, second
;
first
= error("Attempt to rplac[ad] nil.",TRUE
);
if (((typ
= TYPE(first
)) == DTPR
) || (typ
== ATOM
) || HUNKP(first
)) {
if(typ
!=INT
) error("Rplacca of a bignum will only replace INTS",FALSE
);
first
->s
.CDR
= (lispval
) 0;
return(error("Bad arg to rpla",FALSE
));
register struct argent
*mynp
= lbot
+ AD
;
if(mynp
->val
==(mynp
+1)->val
) return(tatom
);
return ((lbot
->val
== nil
) ? tatom
: nil
);
/* Lreturn **************************************************************/
/* Returns the first argument - which is nill if not specified. */
if(lbot
==np
) protect (nil
);
Inonlocalgo(C_RET
,lbot
->val
,nil
);
name
= verify(name
,"infile: file name must be atom or string");
/* return nil if file couldnt be opened
if ((port = fopen((char *)name,"r")) == NULL) return(nil); */
if ((port
= fopen((char *)name
,"r")) == NULL
) {
name
= errorh(Vermisc
,"Unable to open file for reading.",nil
,TRUE
,31,name
);
ioname
[PN(port
)] = (lispval
) inewstr(name
); /* remember name */
/* outfile - open a file for writing.
* 27feb81 [jkf] - modifed to accept two arguments, the second one being a
* string or atom, which if it begins with an `a' tells outfile to open the
FILE *port
; register lispval name
;
char *mode
="w"; /* mode is w for create new file, a for append */
if(lbot
+1== np
) protect(nil
);
given
= (char *)verify((lbot
+1)->val
,"Illegal file open mode.");
if(*given
== 'a') mode
= "a";
name
= verify(name
,"Please supply atom or string name for port.");
if ((port
= fopen(name
,mode
)) == NULL
) {
name
= errorh(Vermisc
,"Unable to open file for writing.",nil
,TRUE
,31,name
);
ioname
[PN(port
)] = (lispval
) inewstr(name
);
if(lbot
==np
) handy
= nil
;
port
= okport(handy
,okport(Vpoport
->a
.clb
,stdout
));
if((TYPE(port
))==PORT
) fclose(port
->p
);
ioname
[PN(port
->p
)] = nil
;
if(lbot
==np
) handy
= nil
;
port
= okport(handy
,okport(Vpoport
->a
.clb
,stdout
));
value
= port
->_ptr
- port
->_base
;
if(lbot
==np
) handy
= nil
;
port
= okport(handy
, okport(Vpoport
->a
.clb
,stdout
));
if(port
->_flag
& _IOWRT
) {
if(! port
->_flag
& _IOREAD
) return(nil
);
port
->_ptr
= port
->_base
;
if(gtty(iodes
,&arg
) != -1) stty(iodes
,&arg
);
return((lispval
)(xports
+ (port
- _iob
)));
/* added for the benefit of mapping functions. */
register struct argent
*ulim
, *namptr
;
register lispval temp
, result
;
temp
= result
= (lispval
) np
;
temp
= temp
->l
= newdot();
temp
->d
.car
= (namptr
++)->val
;
switch(TYPE(lbot
->val
)) {
case INT
: case DOUB
: case SDOT
:
register struct argent
*lb
= lbot
;
if(TYPE(lb
->val
)==DTPR
|| (HUNKP(lb
->val
)))
switch(TYPE(lbot
->val
)) {
return(typred(DTPR
, lbot
->val
));
return(typred(BCD
, lbot
->val
));
return(typred(PORT
, lbot
->val
));
return(typred(ARRAY
, lbot
->val
));
* Returns t if g_arg1 is a hunk, otherwise returns nil.
return(tatom
); /* If a hunk, return t */
return(nil
); /* else nil */
case ATOM
: return(varble
->a
.clb
= lbot
[1].val
);
case VALUE
: return(varble
->l
= lbot
[1].val
);
error("IMPROPER USE OF SET",FALSE
);
register lispval first
, second
;
register struct argent
*lbot
, *np
;
lispval
Lsub(),Lzerop(), *stack(), unstack(), *sp();
lispval
*oldsp
; int mustloop
= FALSE
, result
;
if(lbot
->val
==lbot
[1].val
) return(tatom
);
for((oldsp
=sp(), stack(lbot
->val
,lbot
[1].val
));
first
= unstack(); second
= unstack();
if(first
==second
) continue;
type1
=TYPE(first
); type2
=TYPE(second
);
if((type1
==SDOT
&&type2
==INT
)||(type1
==INT
&&type2
==SDOT
))
stack(first
->d
.cdr
,second
->d
.cdr
);
first
= first
->d
.car
; second
= second
->d
.car
;
if(TYPE(lbot
->val
)!=INT
|| lbot
->val
->i
!=0)
if(strcmp(first
,second
)!=0)
if( lbot
[1].val
== lbot
->val
) return(tatom
);
if(Iequal(lbot
[1].val
,lbot
->val
)) return(tatom
); else return(nil
);
register lispval first
, second
;
register struct argent
*lbot
, *np
;
if((type1
==SDOT
&&type2
==INT
)||(type1
==INT
&&type2
==SDOT
))
Iequal(first
->d
.car
,second
->d
.car
) &&
Iequal(first
->d
.cdr
,second
->d
.cdr
) );
return(first
->r
==second
->r
);
return( (first
->i
==second
->i
));
return(TYPE(lbot
->val
)==INT
&& lbot
->val
->i
==0);
return( first
->l
==second
->l
);
return(strcmp(first
,second
)==0);
register lispval first
, second
;
register struct argent
*lbot
, *np
;
lispval
Lsub(),Lzerop(), *stack(), unstack(), *sp();
lispval
*oldsp
; int mustloop
= FALSE
, result
;
if(lbot
->val
==lbot
[1].val
) return(tatom
);
for((oldsp
=sp(), stack(lbot
->val
,lbot
[1].val
));
first
= unstack(); second
= unstack();
if(first
==second
) continue;
type1
=TYPE(first
); type2
=TYPE(second
);
if((type1
==SDOT
&&type2
==INT
)||(type1
==INT
&&type2
==SDOT
))
stack(first
->d
.cdr
,second
->d
.cdr
);
first
= first
->d
.car
; second
= second
->d
.car
;
if(TYPE(lbot
->val
)!=INT
|| lbot
->val
->i
!=0)
if(strcmp(first
,second
)!=0)
* (print 'expression ['port]) prints the given expression to the given
* port or poport if no port is given. The amount of structure
* printed is a function of global lisp variables prinlevel and
extern int prinlevel
,prinlength
;
handy
= nil
; /* port is optional, default nil */
case 2: handy
= lbot
[1].val
;
default: argerr("print");
chkrtab(Vreadtable
->a
.clb
);
if(TYPE(Vprinlevel
->a
.clb
) == INT
)
prinlevel
= Vprinlevel
->a
.clb
->i
;
if(TYPE(Vprinlength
->a
.clb
) == INT
)
prinlength
= Vprinlength
->a
.clb
->i
;
printr(lbot
->val
,okport(handy
,okport(Vpoport
->a
.clb
,poport
)));
/* patom does not use prinlevel or prinlength
* form is (patom 'value ['port])
extern int prinlevel
,prinlength
;
handy
= nil
; /* port is optional, default nil */
case 2: handy
= lbot
[1].val
;
default: argerr("patom");
temp
= Vreadtable
->a
.clb
;
port
= okport(handy
, okport(Vpoport
->a
.clb
,stdout
));
if ((typ
= TYPE((temp
= (lbot
)->val
))) == ATOM
)
fputs(temp
->a
.pname
, port
);
* (pntlen thing) returns the length it takes to print out
return(inewint(Ipntlen()));
loop
: switch(TYPE(temp
)) {
sprintf(strbuf
,"%d",temp
->i
);
sprintf(strbuf
,"%g",temp
->r
);
temp
= error("Non atom or number to pntlen\n",TRUE
);