static char *sccsid
= "@(#)lam8.c 34.5 11/7/80";
/* various functions from the c math library */
double sin(),cos(),asin(),acos(),atan2(),sqrt(), log(), exp();
chkarg(1,"Math functions");
switch(TYPE(handy
=lbot
->val
)) {
case INT
: res
= func((double)handy
->i
);
case DOUB
: res
= func(handy
->r
);
default: error("Non fixnum or flonum to math function",FALSE
);
/* although we call this atan, it is really atan2 to the c-world,
that is, it takes two args
switch(TYPE(arg
=lbot
->val
)) {
case INT
: arg1v
= (double) arg
->i
;
case DOUB
: arg1v
= arg
->r
;
default: error("Non fixnum or flonum arg to atan2",FALSE
);
switch(TYPE(arg
= (lbot
+1)->val
)) {
case INT
: res
= atan2(arg1v
,(double) arg
->i
);
case DOUB
: res
= atan2(arg1v
, arg
->r
);
default: error("Non fixnum or flonum to atan2",FALSE
);
/* (random) returns a fixnum in the range -2**30 to 2**30 -1
(random fixnum) returns a fixnum in the range 0 to fixnum-1
curval
= rand(); /* get numb from 0 to 2**31-1 */
if(np
==lbot
) return(inewint(curval
-(int)pow((double)2,(double)30)));
if((TYPE(lbot
->val
) != INT
)
|| (lbot
->val
->i
<= 0)) errorh(Vermisc
,"random: non fixnum arg:",
nil
, FALSE
, 0, lbot
->val
);
return(inewint(curval
% lbot
->val
->i
));
if(work
==nil
|| (TYPE(work
)!=ATOM
))
register double *handy
, *base
;
register struct argent
*argp
, *lbot
, *np
;
lispval result
; int type
;
count
= 2 * (((int) np
) - (int) lbot
);
base
= handy
= (double *) alloca(count
);
for(argp
= lbot
; argp
< np
; argp
++) {
while((type
= TYPE(argp
->val
))!=DOUB
&& type
!=INT
)
argp
->val
= (lispval
) errorh(Vermisc
,"%%machine-polyev:non-real arg",nil
,TRUE
,73,lbot
,argp
->val
);
if(TYPE(argp
->val
)==INT
) {
count
= count
/sizeof(double) - 2;
asm("polyd (r9),r11,8(r9)");
unsigned short f1
:7,expt
:8,sign
:1;
unsigned short f2
,f3p1
:14,f3p2
:2,f4
;
unsigned long g4
:16,g3p1
:14;
unsigned long g3p2
:2,g2
:16,g1
:7,hide
:1;
register struct argent
*lbot
,np
;
workbuf
[1] = workbuf
[0] = 0;
work
= lbot
->val
; /* Unfold mantissa */
rqp2
= (qp2
) workbuf
+ 1;
workbuf
[0] = (- workbuf
[0]);
if(workbuf
[1] = (- workbuf
[1]) & 0xC0000000)
/* calcuate exponent and adjustment */
exponent
= -129 - 55 + (int) rdp
->expt
;
register lispval result
, handy
;
register struct argent
*lbot
,*np
;
chkarg(1,"Decompose-float");
while(TYPE(lbot
->val
)!=DOUB
)
lbot
->val
= error("Decompose-float: Non-real argument",TRUE
);
np
++->val
= result
= handy
= newdot();
handy
->d
.car
= inewint(exponent
);
handy
= handy
->d
.cdr
= newdot();
handy
= handy
->d
.car
= newsdot();
handy
= handy
->s
.CDR
= newsdot();
register lispval result
, handy
;
register struct argent
*lbot
,*np
;
long disk_addr
, offset
, whence
;
chkarg(3,"fseek"); /* Make sure there are three arguments*/
f
= lbot
->val
->p
; /* Get first argument into f */
if (TYPE(lbot
->val
)!=PORT
) /* Check type of first */
error("fseek: First argument must be a port.",FALSE
);
offset
= lbot
[1].val
->i
; /* Get second argument */
if (TYPE(lbot
[1].val
)!=INT
)
error("fseek: Second argument must be an integer.",FALSE
);
whence
= lbot
[2].val
->i
; /* Get last arg */
if (TYPE(lbot
[2].val
)!=INT
)
error("fseek: Third argument must be an integer.",FALSE
);
if (fseek(f
, offset
, whence
) == -1)
error("fseek: Illegal parameters.",FALSE
);
retp
= inewint(ftell(f
));
/* function hashtabstat : return list of number of members in each bucket */
register lispval handy
,cur
;
register struct atom
*pnt
;
for(i
= 0; i
< hashtop
; i
++)
for(cnt
= 0; pnt
!= (struct atom
*) CNIL
; pnt
=pnt
->hshlnk
, cnt
++);
cur
->d
.car
= inewint(cnt
);
this routine should only be called by the unwind protect simulation
It is called after an unwind-protect frame has been entered and
evalated and we want to get on with the error or throw
We only handle the case where there are 0 to 2 extra arguments to the
lispval type
,messg
,valret
,contuab
,uniqid
,datum1
,datum2
;
if(lbot
-np
==0) protect(nil
);
if((handy
= lbot
->val
) == nil
) return(nil
);
if(handy
->d
.car
== tatom
)
{ /* continuaing a throw */
Idothrow(handy
->d
.cdr
->d
.car
, handy
->d
.cdr
->d
.cdr
->d
.car
);
error("ctcherr: throw label gone!",FALSE
);
/* decode the arg list */
errorh(type
,messg
->a
.pname
,valret
,contuab
->i
,uniqid
->i
);
errorh(type
,messg
->a
.pname
,valret
,contuab
->i
,uniqid
->i
,datum1
);
/* if two or more extra args, just use first 2 */
errorh(type
,messg
->a
.pname
,valret
,contuab
->i
,uniqid
->i
,datum1
,datum2
);
* Create a hunk of size 2 . <fixnum> must be between 0 and 6.
register int hsize
, hcntr
;
if (TYPE(lbot
->val
)==INT
)
hsize
= lbot
->val
->i
; /* size of hunk (0-6) */
if ((hsize
>= 0) && (hsize
<= 6))
hsize
= 2 << hsize
; /* size of hunk (2-128) */
for (hcntr
= 0; hcntr
< hsize
; hcntr
++)
result
->h
.hunk
[hcntr
] = hunkfree
;
error("*makhunk: Illegal hunk size", FALSE
);
error("*makhunk: First arg must be an fixnum",FALSE
);
* (cxr '<fixnum> '<hunk>)
* Returns the <fixnum>'th element of <hunk>
if (TYPE(lbot
->val
)!=INT
)
error("cxr: First arg must be a fixnum", FALSE
);
if (! HUNKP(lbot
[1].val
))
error("cxr: Second arg must be a hunk", FALSE
);
if ( (lbot
->val
->i
>= 0) &&
(lbot
->val
->i
< (2 << HUNKSIZE(lbot
[1].val
))) )
temp
= lbot
[1].val
->h
.hunk
[lbot
->val
->i
];
error("cxr: Arg outside of hunk range",
error("cxr: Arg outside of hunk range", FALSE
);
* (rplacx '<fixnum> '<hunk> '<expr>)
* Replaces the <fixnum>'th element of <hunk> with <expr>.
if (TYPE(lbot
->val
)!=INT
)
error("rplacx: First arg must be a fixnum", FALSE
);
if (! HUNKP(lbot
[1].val
))
error("rplacx: Second arg must be a hunk", FALSE
);
if ( (lbot
->val
->i
>= 0) &&
(lbot
->val
->i
< (2 << HUNKSIZE(lbot
[1].val
))) )
if (*(handy
= &(lbot
[1].val
->h
.hunk
[lbot
->val
->i
]))
error("rplacx: Arg outside hunk range", FALSE
);
error("rplacx: Arg outside hunk range", FALSE
);
* (*rplacx '<fixnum> '<hunk> '<expr>)
* Replaces the <fixnum>'th element of <hunk> with <expr>. This is the
* same as (rplacx ...) except with this function you can replace EMPTY's.
if (TYPE(lbot
->val
)!=INT
)
error("*rplacx: First arg must be a fixnum", FALSE
);
if (! HUNKP(lbot
[1].val
))
error("*rplacx: Second arg must be a hunk", FALSE
);
if ( (lbot
->val
->i
>= 0) &&
(lbot
->val
->i
< (2 << HUNKSIZE(lbot
[1].val
))) )
lbot
[1].val
->h
.hunk
[lbot
->val
->i
] = lbot
[2].val
;
error("*rplacx: Arg outside hunk range", FALSE
);
* Returns the size of <hunk>
size
= 2 << HUNKSIZE(lbot
->val
);
for (i
= size
-1; i
>= 0; i
--)
if (lbot
->val
->h
.hunk
[i
] != hunkfree
)
error("hunksize: First argument must me a hunk", FALSE
);
* (fileopen filename mode)
* open a file for read, write, or append the arguments can be either
register struct argent
*lbot
, *np
;
namech
= (char *) verify(name
,"fileopen:args must be atoms or strings");
modech
= (char *) verify(mode
,"fileopen:args must be atoms or strings");
while (modech
[0] != 'r' && modech
[0] != 'w' && modech
[0] != 'a')
mode
= errorh(Vermisc
,"Modes are only r, w, a.",nil
,TRUE
,31,(char *) 0);
modech
= (char *) verify(mode
,"fileopen:args must be atoms or strings");
while ((port
= fopen(namech
, modech
)) == NULL
)
name
= errorh(Vermisc
,"Unable to open file.",nil
,TRUE
,31,name
);
namech
= (char *) verify(name
,"fileopen:args must be atoms or strings");
/* xports is a FILE *, cc complains about adding pointers */
return( (lispval
) (xports
+ (port
- _iob
)));
* (*mod '<number> '<modulus>)
* This function returns <number> mod <modulus> (for balanced modulus).
* It is used in vaxima as a speed enhancement.
register int mod_div_2
, number
, modulus
;
if ((TYPE(lbot
->val
) == INT
) && (TYPE(lbot
[1].val
) == INT
))
modulus
= lbot
[1].val
->i
;
number
= lbot
->val
->i
% modulus
;
if (number
< (-mod_div_2
))
return( inewint(number
) );
error("*mod: Arguments must be fixnums", FALSE
);
register struct argent
*mylbot
= lbot
;
if((TYPE(mylbot
->val
) != INT
) || (TYPE(mylbot
[1].val
) != INT
))
nil
,FALSE
,0,mylbot
->val
,mylbot
[1].val
);
shift
= mylbot
[1].val
->i
;
if(shift
< -32 || shift
> 32)
val
= val
<< shift
; /* do the shift */
if((val
< 0) && (shift
< 0))
{ /* special case: the vax doesn't have a logical shift
instruction, so we must zero out the ones which
will propogate from the sign position
return(inewint ( val
& ~(0x80000000 << (shift
+1))));
else return( inewint(val
));
register rot
,val
; /* these must be the first registers */
register struct argent
*mylbot
= lbot
;
if((TYPE(mylbot
->val
) != INT
) || (TYPE(mylbot
[1].val
) != INT
))
nil
,FALSE
,0,mylbot
->val
,mylbot
[1].val
);
rot
= rot
% 32 ; /* bring it down below one byte in size */
asm(" rotl r11,r10,r10 "); /* rotate val by rot and put back in val */
/*----------------- vms routines to simulate dumplisp -------------------- */
extern char firstalloc
[];
extern char zfreespace
[];
#define roundup(a,b) (((a-1)|(b-1))+1)
filnm
= (char *) verify(lbot
->val
, "savelisp: non atom arg");
if((fp
=creat(filnm
,0666)) < 0)
errorh(Vermisc
,"savelisp: can't open file",nil
,FALSE
,0,
start
= roundup((int)firstalloc
,PAGSIZ
);
num
= roundup(((int)lsbrkpnt
)-NBPG
-start
,PAGSIZ
);
if((num
= write(fp
,start
,num
)) <= 0)
error("savelisp: write failed ",FALSE
);
printf(" %x bytes written from %x to %x \n",num
,start
,start
+num
-1);
filnm
= (char *) verify(lbot
->val
,"restorelisp: non atom arg");
if((fp
=open(filnm
,0)) < 0)
errorh(Vermisc
,"restorelisp: can't open file",nil
,FALSE
,0,
start
= roundup((int)firstalloc
,PAGSIZ
);
if((num
= vread(fp
,start
,((int)&end
)-start
)) <= 0)
error("restorelisp: read failed " ,FALSE
);
printf(" %x bytes read into %x to %x\n",num
,start
,start
+num
-1);
xcycle
= 0; /* indicate no saved pages to xsbrk */
reset(BRRETB
); /* reset */
/*----------------------------------------------------------- */
* (getaddress '|_entry1| 'fncname1 '|_entry2| 'fncname2 ...)
* binds value of symbol |_entry1| to function defition of atom fncname1, etc.
* returns fnc-binding of fncname1.
register struct argent
*mlbot
= lbot
;
register int numberofargs
, i
;
register struct argent
*lbot
, *np
;
struct nlist NTABLE
[100];
if(np
-lbot
== 2) protect(nil
); /* allow 2 args */
numberofargs
= (np
- lbot
)/3;
if(numberofargs
* 3 != np
-lbot
)
error("getaddress: arguments must come in triples ",FALSE
);
for ( i
=0; i
<numberofargs
; i
++,mlbot
+= 3) {
mlbot
[0].val
= verify(mlbot
[0].val
,"Incorrect entry specification for binding");
NTABLE
[i
].n_un
.n_name
= (char *) mlbot
[0].val
;
while(TYPE(mlbot
[1].val
) != ATOM
)
mlbot
[1].val
= errorh(Vermisc
,
"Bad associated atom name for binding",
nil
,TRUE
,0,mlbot
[1].val
);
mlbot
[2].val
= dispget(mlbot
[2].val
,"getaddress: Incorrect discipline specification ",Vsubrou
->a
.pname
);
NTABLE
[(numberofargs
)].n_un
.n_name
= "";
strcpyn(ostabf
,gstab(),128);
if ( nlist(ostabf
,NTABLE
) == -1 ) {
errorh(Vermisc
,"Getaddress: Bad file",nil
,FALSE
,0,inewstr(ostabf
));
for (i
=0,mlbot
=lbot
+1; i
<numberofargs
; i
++,mlbot
+=3) {
if ( NTABLE
[i
].n_value
== 0 )
fprintf(stderr
,"Undefined symbol: %s\n",
work
->bcd
.entry
= (lispval (*) ())NTABLE
[i
].n_value
;
work
->bcd
.discipline
= mlbot
[1].val
;
mlbot
->val
->a
.fnbnd
= work
;
return(lbot
[1].val
->a
.fnbnd
);
/* very temporary function to test the validity of the bind stack */
register struct nament
*npt
;
for(npt
=orgbnp
; npt
< bnp
; npt
++)
{ if((int) npt
->atm
< (int) in2
) asm(" halt ");
* formatted printer for lisp data
* use: (cprintf formatstring datum [port])
if(np
-lbot
== 2) protect(nil
); /* write to standard output port */
fstrng
= (char *)verify(lbot
->val
,"cprintf: first arg not string or symbol");
p
= okport(lbot
[2].val
,okport(Vpoport
->a
.clb
,poport
));
switch(TYPE(v
=lbot
[1].val
)) {
case INT
: fprintf(p
,fstrng
,v
->i
);
case DOUB
: fprintf(p
,fstrng
,v
->r
);
case ATOM
: fprintf(p
,fstrng
,v
->a
.pname
);
case STRNG
:fprintf(p
,fstrng
,v
);
default: error("cprintf: Illegal second argument",FALSE
);
name
= (char *)verify(lbot
->val
,"probef: not symbol or string arg ");
if(access(name
,0) == 0) return(tatom
);
register lispval index
,length
;
int restofstring
= FALSE
;
case 2: restofstring
= TRUE
;
default: chkarg(3,"substring");
name
= (char *)verify(lbot
[0].val
,"substring: not symbol or string arg ");
while (TYPE(index
= lbot
[1].val
) != INT
)
{ lbot
[1].val
= errorh(Vermisc
,"substring: non integer index ",nil
,
if(ind
< 0) ind
= len
+1 + ind
;
if(ind
< 1 || ind
> len
) return(nil
); /*index out of bounds*/
if(restofstring
) return((lispval
)inewstr(name
+ind
-1));
while (TYPE(length
= lbot
[2].val
) != INT
)
{ lbot
[2].val
= errorh(Vermisc
,"substring: not integer length ",nil
,
if((reallen
= length
->i
) < 0 || (reallen
+ ind
) > len
)
return((lispval
)inewstr(name
+ind
-1));
strncpy(strbuf
,name
+ind
-1,reallen
);
return((lispval
)newstr());
register int len
,ind
,reallen
;
int restofstring
= FALSE
;
if((np
-lbot
) == 2) restofstring
= TRUE
;
else { chkarg(3,"substringn");}
name
= (char *) verify(lbot
[0].val
,"substringn: non symbol or string arg ");
while (TYPE(index
= lbot
[1].val
) != INT
)
{ lbot
[1].val
= errorh(Vermisc
,"substringn: non integer index ",nil
,
while (TYPE(length
= lbot
[2].val
) != INT
)
{ lbot
[2].val
= errorh(Vermisc
,"substringn: not integer length ",
if(ind
< 0) ind
= len
+ 1 + ind
;
if( ind
< 1 || ind
> len
) return(nil
);
return((lispval
)inewint(*(name
+ ind
- 1)));
char *pnt
= name
+ ind
- 1;
char *last
= name
+ len
-1;
protect(cur
= start
= newdot());
cur
->d
.car
= inewint(*pnt
);
while(++pnt
<= last
&& --reallen
!= 0)
cur
->d
.car
= inewint(*pnt
);