/* xdrfuns.c Copyright (C) 1995 NAG Ltd */ /* * Functions to support reading and writing of objects in XDR format. * * Version 1.0 September 1995 * * Author: Mike Dewar * */ /* Signature: 4bbe58eb 08-Apr-2002 */ #include <stdio.h> #ifdef AIX3 #include <sys/select.h> #endif /* * What I really mean here is ifdef(UNIX), but we don't know that until * machine.h is included. To simplify matters I'll just check to see if * we seem to be flagged as some version of Windows, or if we are * are using a Windows compiler... Including machine.h earlier causes * some problems on the RS6000. This latter issue is what really needs * mending but I do not have an RS6000 at hand to try just now... * [ACN updating some comments of MCD] */ /* My changed version: */ #ifndef _WINDOWS #ifndef WINDOWS_NT #ifndef __WATCOMC__ #include <rpc/rpc.h> #endif #endif #endif #include <stdarg.h> #include <ctype.h> /* These are defined by the rpc code on the alpha */ #define int32 csl_int32 #define int64 csl_int64 #include "machine.h" #include "tags.h" #include "cslerror.h" #include "externs.h" #include "entries.h" #include "stream.h" #include "arith.h" #ifdef UNIX Lisp_Object LxdrOpen(Lisp_Object nil, Lisp_Object f, Lisp_Object d) { XDR xdrs; Lisp_Object lxdr; /* * First argument must be an open stream. Since CCL streams are all * bi-directional we get the intended direction from the second argument. */ if (!is_stream(f)) return aerror("xdrOpen"); xdrstdio_create(&xdrs,stream_file(f),(d == lisp_true)?XDR_ENCODE:XDR_DECODE); /* Copy the XDR structure into a string to avoid alignment problems. */ lxdr = Lsmkvect(nil,fixnum_of_int(sizeof(XDR))); memcpy(&celt(lxdr,0),&xdrs,sizeof(XDR)); return onevalue(lxdr); } #define XW(x,u) ( (!x) ? aerror1("Bad XDR write for: ",u) : u ) Lisp_Object LxdrWrite(Lisp_Object nil, Lisp_Object lxdr,Lisp_Object u) { XDR xdrs; /* Copy the XDR structure out of a CCL string. */ memcpy(&xdrs,&celt(lxdr,0),sizeof(XDR)); /* * We include the bignum case since fixnums in CCL are 28 bits and we would * like to support 32 bit integers here. */ if (is_fixnum(u) ) { int32 temp = int_of_fixnum(u); return XW(xdr_int(&xdrs,&temp), u); } else if (is_float(u) ) { double temp = float_of_number(u); return XW(xdr_double(&xdrs,&temp), u); } else if (is_numbers(u) && is_bignum(u) ) { int32 temp=thirty_two_bits(u); return XW(xdr_int(&xdrs,&temp), u); } else if (is_vector(u) && type_of_header(vechdr(u)) == TYPE_STRING) { int32 len = length_of_header(vechdr(u))-4; char *temp=&celt(u,0); return XW(xdr_string(&xdrs,&temp,len),u); } else if (is_vector(u) ) { int32 count, len = thirty_two_bits(Llength(nil,u)); Lisp_Object v = elt(u,0); /* * Mimic the way that xdr_array works by writing the length of the * array first. */ if (!xdr_int(&xdrs,&len)) aerror1("XDR Error writing length of:",u); /* * Although Common Lisp Vectors are not homogeneous, C vectors are, * so we will assume that u is homogeneous and only test the type * of the first element. */ if (is_float(v) ) { double temp; for (count=0 ; count < len ; ++count) { temp = float_of_number(elt(u,count)); if (!xdr_double(&xdrs,&temp)) aerror1("Bad XDR write for Double-Float vector element: ",v); } return(u); } else if (is_fixnum(v) || ( is_numbers(v) && is_bignum(v) ) ) { int32 temp; for (count=0 ; count < len ; ++count) { temp = thirty_two_bits(elt(u,count)); if (!xdr_int(&xdrs,&temp)) aerror1("Bad XDR write for integer vector element: ",v); } return(u); } else aerror1("XDR cannot handle a vector containing:",v); } else aerror1("XDR cannot handle:",u); } /* This checks a 32 bit integer's value and returns it as either a fixnum or a bignum. */ #define int2ccl(i) (i > -268435455 && i < 268435456) ? fixnum_of_int(i) : make_one_word_bignum(i) Lisp_Object LxdrRead(Lisp_Object nil, Lisp_Object lxdr,Lisp_Object u) { XDR xdrs; int temp; /* Copy the XDR structure out of a CCL string. */ memcpy(&xdrs,&celt(lxdr,0),sizeof(XDR)); if (is_fixnum(u) || (is_numbers(u) && is_bignum(u) ) ) { int32 temp; if (!xdr_int(&xdrs,&temp)) aerror("Integer XDR read"); return onevalue(int2ccl(temp)); } else if (is_float(u) ) { double temp; if (!xdr_double(&xdrs,&temp)) aerror("Double-Float XDR read"); return onevalue(make_boxfloat(temp,TYPE_DOUBLE_FLOAT)); } else if (is_vector(u) && type_of_header(vechdr(u)) == TYPE_STRING) { char *temp=NULL; /* Value for maximum length of a string is fairly arbitrary! */ if (!xdr_string(&xdrs,&temp,16777216)) aerror("String XDR read"); return onevalue(make_string(temp)); } else if (is_vector(u) ) { int32 count, len; Lisp_Object new, v = elt(u,0); /* xdr_array writes the length of the array first. */ if (!xdr_int(&xdrs,&len)) aerror1("XDR Error reading length of:",u); /* Create the new vector */ new = getvector(TAG_VECTOR, TYPE_SIMPLE_VEC, 4*len+4); /* vectors must pad to an even number of words */ if ((len & 1) == 0) elt(new,len) = nil; /* * Although Common Lisp Vectors are not homogeneous, C vectors are, * so we will assume that u is homogeneous and only test the type * of the first element. */ if (is_float(v) ) { double temp; for (count=0 ; count < len ; ++count) { if (!xdr_double(&xdrs,&temp)) aerror("Double-Float vector XDR read"); elt(new,count) = make_boxfloat(temp,TYPE_DOUBLE_FLOAT); } } else if ( is_fixnum(v) || ( is_numbers(v) && is_bignum(v) )) { int32 temp; for (count=0 ; count < len ; ++count) { if (!xdr_int(&xdrs,&temp)) aerror("Integer vector XDR read"); elt(new,count) = int2ccl(temp); } } else aerror1("XDR cannot handle a vector containing:",v); return onevalue(new); } else aerror1("XDR cannot handle:",u); } #else /* UNIX */ Lisp_Object LxdrOpen(Lisp_Object nil, Lisp_Object f, Lisp_Object d) { aerror("Attempt to call xdr-open on non-Unix platform"); return nil; } Lisp_Object LxdrWrite(Lisp_Object nil, Lisp_Object lxdr, Lisp_Object u) { aerror("Attempt to call xdr-write on non-Unix platform"); return nil; } Lisp_Object LxdrRead(Lisp_Object nil, Lisp_Object lxdr, Lisp_Object u) { aerror("Attempt to call xdr-read on non-Unix platform"); return nil; } #endif /* UNIX */ setup_type const xdr_setup[] = { {"xdr-open", too_few_2, LxdrOpen, wrong_no_2}, {"xdr-write", too_few_2, LxdrWrite, wrong_no_2}, {"xdr-read", too_few_2, LxdrRead, wrong_no_2}, {NULL, 0, 0, 0} };