xdrfuns.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. /* xdrfuns.c Copyright (C) 1995 NAG Ltd */
  2. /*
  3. * Functions to support reading and writing of objects in XDR format.
  4. *
  5. * Version 1.0 September 1995
  6. *
  7. * Author: Mike Dewar
  8. *
  9. */
  10. /* Signature: 4bbe58eb 08-Apr-2002 */
  11. #include <stdio.h>
  12. #ifdef AIX3
  13. #include <sys/select.h>
  14. #endif
  15. /*
  16. * What I really mean here is ifdef(UNIX), but we don't know that until
  17. * machine.h is included. To simplify matters I'll just check to see if
  18. * we seem to be flagged as some version of Windows, or if we are
  19. * are using a Windows compiler... Including machine.h earlier causes
  20. * some problems on the RS6000. This latter issue is what really needs
  21. * mending but I do not have an RS6000 at hand to try just now...
  22. * [ACN updating some comments of MCD]
  23. */
  24. /* My changed version: */
  25. #ifndef _WINDOWS
  26. #ifndef WINDOWS_NT
  27. #ifndef __WATCOMC__
  28. #include <rpc/rpc.h>
  29. #endif
  30. #endif
  31. #endif
  32. #include <stdarg.h>
  33. #include <ctype.h>
  34. /* These are defined by the rpc code on the alpha */
  35. #define int32 csl_int32
  36. #define int64 csl_int64
  37. #include "machine.h"
  38. #include "tags.h"
  39. #include "cslerror.h"
  40. #include "externs.h"
  41. #include "entries.h"
  42. #include "stream.h"
  43. #include "arith.h"
  44. #ifdef UNIX
  45. Lisp_Object LxdrOpen(Lisp_Object nil, Lisp_Object f, Lisp_Object d)
  46. {
  47. XDR xdrs;
  48. Lisp_Object lxdr;
  49. /*
  50. * First argument must be an open stream. Since CCL streams are all
  51. * bi-directional we get the intended direction from the second argument.
  52. */
  53. if (!is_stream(f)) return aerror("xdrOpen");
  54. xdrstdio_create(&xdrs,stream_file(f),(d == lisp_true)?XDR_ENCODE:XDR_DECODE);
  55. /* Copy the XDR structure into a string to avoid alignment problems. */
  56. lxdr = Lsmkvect(nil,fixnum_of_int(sizeof(XDR)));
  57. memcpy(&celt(lxdr,0),&xdrs,sizeof(XDR));
  58. return onevalue(lxdr);
  59. }
  60. #define XW(x,u) ( (!x) ? aerror1("Bad XDR write for: ",u) : u )
  61. Lisp_Object LxdrWrite(Lisp_Object nil, Lisp_Object lxdr,Lisp_Object u)
  62. {
  63. XDR xdrs;
  64. /* Copy the XDR structure out of a CCL string. */
  65. memcpy(&xdrs,&celt(lxdr,0),sizeof(XDR));
  66. /*
  67. * We include the bignum case since fixnums in CCL are 28 bits and we would
  68. * like to support 32 bit integers here.
  69. */
  70. if (is_fixnum(u) )
  71. { int32 temp = int_of_fixnum(u);
  72. return XW(xdr_int(&xdrs,&temp), u);
  73. }
  74. else if (is_float(u) )
  75. { double temp = float_of_number(u);
  76. return XW(xdr_double(&xdrs,&temp), u);
  77. }
  78. else if (is_numbers(u) && is_bignum(u) )
  79. { int32 temp=thirty_two_bits(u);
  80. return XW(xdr_int(&xdrs,&temp), u);
  81. }
  82. else if (is_vector(u) && type_of_header(vechdr(u)) == TYPE_STRING)
  83. { int32 len = length_of_header(vechdr(u))-4;
  84. char *temp=&celt(u,0);
  85. return XW(xdr_string(&xdrs,&temp,len),u);
  86. }
  87. else if (is_vector(u) )
  88. { int32 count, len = thirty_two_bits(Llength(nil,u));
  89. Lisp_Object v = elt(u,0);
  90. /*
  91. * Mimic the way that xdr_array works by writing the length of the
  92. * array first.
  93. */
  94. if (!xdr_int(&xdrs,&len)) aerror1("XDR Error writing length of:",u);
  95. /*
  96. * Although Common Lisp Vectors are not homogeneous, C vectors are,
  97. * so we will assume that u is homogeneous and only test the type
  98. * of the first element.
  99. */
  100. if (is_float(v) )
  101. { double temp;
  102. for (count=0 ; count < len ; ++count)
  103. { temp = float_of_number(elt(u,count));
  104. if (!xdr_double(&xdrs,&temp))
  105. aerror1("Bad XDR write for Double-Float vector element: ",v);
  106. }
  107. return(u);
  108. }
  109. else if (is_fixnum(v) || ( is_numbers(v) && is_bignum(v) ) )
  110. { int32 temp;
  111. for (count=0 ; count < len ; ++count)
  112. { temp = thirty_two_bits(elt(u,count));
  113. if (!xdr_int(&xdrs,&temp))
  114. aerror1("Bad XDR write for integer vector element: ",v);
  115. }
  116. return(u);
  117. }
  118. else
  119. aerror1("XDR cannot handle a vector containing:",v);
  120. }
  121. else
  122. aerror1("XDR cannot handle:",u);
  123. }
  124. /* This checks a 32 bit integer's value and returns it as either a fixnum
  125. or a bignum. */
  126. #define int2ccl(i) (i > -268435455 && i < 268435456) ? fixnum_of_int(i) : make_one_word_bignum(i)
  127. Lisp_Object LxdrRead(Lisp_Object nil, Lisp_Object lxdr,Lisp_Object u)
  128. {
  129. XDR xdrs;
  130. int temp;
  131. /* Copy the XDR structure out of a CCL string. */
  132. memcpy(&xdrs,&celt(lxdr,0),sizeof(XDR));
  133. if (is_fixnum(u) || (is_numbers(u) && is_bignum(u) ) )
  134. { int32 temp;
  135. if (!xdr_int(&xdrs,&temp)) aerror("Integer XDR read");
  136. return onevalue(int2ccl(temp));
  137. }
  138. else if (is_float(u) )
  139. { double temp;
  140. if (!xdr_double(&xdrs,&temp)) aerror("Double-Float XDR read");
  141. return onevalue(make_boxfloat(temp,TYPE_DOUBLE_FLOAT));
  142. }
  143. else if (is_vector(u) && type_of_header(vechdr(u)) == TYPE_STRING)
  144. { char *temp=NULL;
  145. /* Value for maximum length of a string is fairly arbitrary! */
  146. if (!xdr_string(&xdrs,&temp,16777216)) aerror("String XDR read");
  147. return onevalue(make_string(temp));
  148. }
  149. else if (is_vector(u) )
  150. { int32 count, len;
  151. Lisp_Object new, v = elt(u,0);
  152. /* xdr_array writes the length of the array first. */
  153. if (!xdr_int(&xdrs,&len)) aerror1("XDR Error reading length of:",u);
  154. /* Create the new vector */
  155. new = getvector(TAG_VECTOR, TYPE_SIMPLE_VEC, 4*len+4);
  156. /* vectors must pad to an even number of words */
  157. if ((len & 1) == 0) elt(new,len) = nil;
  158. /*
  159. * Although Common Lisp Vectors are not homogeneous, C vectors are,
  160. * so we will assume that u is homogeneous and only test the type
  161. * of the first element.
  162. */
  163. if (is_float(v) )
  164. { double temp;
  165. for (count=0 ; count < len ; ++count)
  166. { if (!xdr_double(&xdrs,&temp)) aerror("Double-Float vector XDR read");
  167. elt(new,count) = make_boxfloat(temp,TYPE_DOUBLE_FLOAT);
  168. }
  169. }
  170. else if ( is_fixnum(v) || ( is_numbers(v) && is_bignum(v) ))
  171. { int32 temp;
  172. for (count=0 ; count < len ; ++count)
  173. { if (!xdr_int(&xdrs,&temp)) aerror("Integer vector XDR read");
  174. elt(new,count) = int2ccl(temp);
  175. }
  176. }
  177. else
  178. aerror1("XDR cannot handle a vector containing:",v);
  179. return onevalue(new);
  180. }
  181. else
  182. aerror1("XDR cannot handle:",u);
  183. }
  184. #else /* UNIX */
  185. Lisp_Object LxdrOpen(Lisp_Object nil, Lisp_Object f, Lisp_Object d)
  186. {
  187. aerror("Attempt to call xdr-open on non-Unix platform");
  188. return nil;
  189. }
  190. Lisp_Object LxdrWrite(Lisp_Object nil, Lisp_Object lxdr, Lisp_Object u)
  191. {
  192. aerror("Attempt to call xdr-write on non-Unix platform");
  193. return nil;
  194. }
  195. Lisp_Object LxdrRead(Lisp_Object nil, Lisp_Object lxdr, Lisp_Object u)
  196. {
  197. aerror("Attempt to call xdr-read on non-Unix platform");
  198. return nil;
  199. }
  200. #endif /* UNIX */
  201. setup_type const xdr_setup[] =
  202. {
  203. {"xdr-open", too_few_2, LxdrOpen, wrong_no_2},
  204. {"xdr-write", too_few_2, LxdrWrite, wrong_no_2},
  205. {"xdr-read", too_few_2, LxdrRead, wrong_no_2},
  206. {NULL, 0, 0, 0}
  207. };