(root)/
glibc-2.38/
sunrpc/
xdr_float.c
       1  /*
       2   * xdr_float.c, Generic XDR routines implementation.
       3   *
       4   * Copyright (c) 2010, Oracle America, Inc.
       5   *
       6   * Redistribution and use in source and binary forms, with or without
       7   * modification, are permitted provided that the following conditions are
       8   * met:
       9   *
      10   *     * Redistributions of source code must retain the above copyright
      11   *       notice, this list of conditions and the following disclaimer.
      12   *     * Redistributions in binary form must reproduce the above
      13   *       copyright notice, this list of conditions and the following
      14   *       disclaimer in the documentation and/or other materials
      15   *       provided with the distribution.
      16   *     * Neither the name of the "Oracle America, Inc." nor the names of its
      17   *       contributors may be used to endorse or promote products derived
      18   *       from this software without specific prior written permission.
      19   *
      20   *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      21   *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      22   *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
      23   *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
      24   *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
      25   *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      26   *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
      27   *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      28   *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
      29   *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
      30   *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      31   *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      32   *
      33   * These are the "floating point" xdr routines used to (de)serialize
      34   * most common data items.  See xdr.h for more info on the interface to
      35   * xdr.
      36   */
      37  
      38  #include <stdio.h>
      39  #include <endian.h>
      40  
      41  #include <rpc/types.h>
      42  #include <rpc/xdr.h>
      43  #include <shlib-compat.h>
      44  
      45  /*
      46   * NB: Not portable.
      47   * This routine works on Suns (Sky / 68000's) and Vaxen.
      48   */
      49  
      50  #define LSW	(__FLOAT_WORD_ORDER == __BIG_ENDIAN)
      51  
      52  #ifdef vax
      53  
      54  /* What IEEE single precision floating point looks like on a Vax */
      55  struct	ieee_single {
      56  	unsigned int	mantissa: 23;
      57  	unsigned int	exp     : 8;
      58  	unsigned int	sign    : 1;
      59  };
      60  
      61  /* Vax single precision floating point */
      62  struct	vax_single {
      63  	unsigned int	mantissa1 : 7;
      64  	unsigned int	exp       : 8;
      65  	unsigned int	sign      : 1;
      66  	unsigned int	mantissa2 : 16;
      67  };
      68  
      69  #define VAX_SNG_BIAS	0x81
      70  #define IEEE_SNG_BIAS	0x7f
      71  
      72  static struct sgl_limits {
      73  	struct vax_single s;
      74  	struct ieee_single ieee;
      75  } sgl_limits[2] = {
      76  	{{ 0x7f, 0xff, 0x0, 0xffff },	/* Max Vax */
      77  	{ 0x0, 0xff, 0x0 }},		/* Max IEEE */
      78  	{{ 0x0, 0x0, 0x0, 0x0 },	/* Min Vax */
      79  	{ 0x0, 0x0, 0x0 }}		/* Min IEEE */
      80  };
      81  #endif /* vax */
      82  
      83  bool_t
      84  xdr_float (XDR *xdrs, float *fp)
      85  {
      86  #ifdef vax
      87  	struct ieee_single is;
      88  	struct vax_single vs, *vsp;
      89  	struct sgl_limits *lim;
      90  	int i;
      91  #endif
      92  	switch (xdrs->x_op) {
      93  
      94  	case XDR_ENCODE:
      95  #ifdef vax
      96  		vs = *((struct vax_single *)fp);
      97  		for (i = 0, lim = sgl_limits;
      98  			i < sizeof(sgl_limits)/sizeof(struct sgl_limits);
      99  			i++, lim++) {
     100  			if ((vs.mantissa2 == lim->s.mantissa2) &&
     101  				(vs.exp == lim->s.exp) &&
     102  				(vs.mantissa1 == lim->s.mantissa1)) {
     103  				is = lim->ieee;
     104  				goto shipit;
     105  			}
     106  		}
     107  		is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS;
     108  		is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2;
     109  	shipit:
     110  		is.sign = vs.sign;
     111  		return (XDR_PUTLONG(xdrs, (long *)&is));
     112  #else
     113  		if (sizeof(float) == sizeof(long))
     114  			return (XDR_PUTLONG(xdrs, (long *)fp));
     115  		else if (sizeof(float) == sizeof(int)) {
     116  			long tmp = *(int *)fp;
     117  			return (XDR_PUTLONG(xdrs, &tmp));
     118  		}
     119  		break;
     120  #endif
     121  
     122  	case XDR_DECODE:
     123  #ifdef vax
     124  		vsp = (struct vax_single *)fp;
     125  		if (!XDR_GETLONG(xdrs, (long *)&is))
     126  			return (FALSE);
     127  		for (i = 0, lim = sgl_limits;
     128  			i < sizeof(sgl_limits)/sizeof(struct sgl_limits);
     129  			i++, lim++) {
     130  			if ((is.exp == lim->ieee.exp) &&
     131  				(is.mantissa == lim->ieee.mantissa)) {
     132  				*vsp = lim->s;
     133  				goto doneit;
     134  			}
     135  		}
     136  		vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS;
     137  		vsp->mantissa2 = is.mantissa;
     138  		vsp->mantissa1 = (is.mantissa >> 16);
     139  	doneit:
     140  		vsp->sign = is.sign;
     141  		return (TRUE);
     142  #else
     143  		if (sizeof(float) == sizeof(long))
     144  			return (XDR_GETLONG(xdrs, (long *)fp));
     145  		else if (sizeof(float) == sizeof(int)) {
     146  			long tmp;
     147  			if (XDR_GETLONG(xdrs, &tmp)) {
     148  				*(int *)fp = tmp;
     149  				return (TRUE);
     150  			}
     151  		}
     152  		break;
     153  #endif
     154  
     155  	case XDR_FREE:
     156  		return (TRUE);
     157  	}
     158  	return (FALSE);
     159  }
     160  libc_hidden_nolink_sunrpc (xdr_float, GLIBC_2_0)
     161  
     162  /*
     163   * This routine works on Suns (Sky / 68000's) and Vaxen.
     164   */
     165  
     166  #ifdef vax
     167  /* What IEEE double precision floating point looks like on a Vax */
     168  struct	ieee_double {
     169  	unsigned int	mantissa1 : 20;
     170  	unsigned int	exp       : 11;
     171  	unsigned int	sign      : 1;
     172  	unsigned int	mantissa2 : 32;
     173  };
     174  
     175  /* Vax double precision floating point */
     176  struct  vax_double {
     177  	unsigned int	mantissa1 : 7;
     178  	unsigned int	exp       : 8;
     179  	unsigned int	sign      : 1;
     180  	unsigned int	mantissa2 : 16;
     181  	unsigned int	mantissa3 : 16;
     182  	unsigned int	mantissa4 : 16;
     183  };
     184  
     185  #define VAX_DBL_BIAS	0x81
     186  #define IEEE_DBL_BIAS	0x3ff
     187  #define MASK(nbits)	((1 << nbits) - 1)
     188  
     189  static struct dbl_limits {
     190  	struct	vax_double d;
     191  	struct	ieee_double ieee;
     192  } dbl_limits[2] = {
     193  	{{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff },	/* Max Vax */
     194  	{ 0x0, 0x7ff, 0x0, 0x0 }},			/* Max IEEE */
     195  	{{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},		/* Min Vax */
     196  	{ 0x0, 0x0, 0x0, 0x0 }}				/* Min IEEE */
     197  };
     198  
     199  #endif /* vax */
     200  
     201  
     202  bool_t
     203  xdr_double (XDR *xdrs, double *dp)
     204  {
     205  #ifdef vax
     206  	struct	ieee_double id;
     207  	struct	vax_double vd;
     208  	register struct dbl_limits *lim;
     209  	int i;
     210  #endif
     211  
     212  	switch (xdrs->x_op) {
     213  
     214  	case XDR_ENCODE:
     215  #ifdef vax
     216  		vd = *((struct vax_double *)dp);
     217  		for (i = 0, lim = dbl_limits;
     218  			i < sizeof(dbl_limits)/sizeof(struct dbl_limits);
     219  			i++, lim++) {
     220  			if ((vd.mantissa4 == lim->d.mantissa4) &&
     221  				(vd.mantissa3 == lim->d.mantissa3) &&
     222  				(vd.mantissa2 == lim->d.mantissa2) &&
     223  				(vd.mantissa1 == lim->d.mantissa1) &&
     224  				(vd.exp == lim->d.exp)) {
     225  				id = lim->ieee;
     226  				goto shipit;
     227  			}
     228  		}
     229  		id.exp = vd.exp - VAX_DBL_BIAS + IEEE_DBL_BIAS;
     230  		id.mantissa1 = (vd.mantissa1 << 13) | (vd.mantissa2 >> 3);
     231  		id.mantissa2 = ((vd.mantissa2 & MASK(3)) << 29) |
     232  				(vd.mantissa3 << 13) |
     233  				((vd.mantissa4 >> 3) & MASK(13));
     234  	shipit:
     235  		id.sign = vd.sign;
     236  		dp = (double *)&id;
     237  #endif
     238  		if (2*sizeof(long) == sizeof(double)) {
     239  			long *lp = (long *)dp;
     240  			return (XDR_PUTLONG(xdrs, lp+!LSW) &&
     241  				XDR_PUTLONG(xdrs, lp+LSW));
     242  		} else if (2*sizeof(int) == sizeof(double)) {
     243  			int *ip = (int *)dp;
     244  			long tmp[2];
     245  			tmp[0] = ip[!LSW];
     246  			tmp[1] = ip[LSW];
     247  			return (XDR_PUTLONG(xdrs, tmp) &&
     248  				XDR_PUTLONG(xdrs, tmp+1));
     249  		}
     250  		break;
     251  
     252  	case XDR_DECODE:
     253  #ifdef vax
     254  		lp = (long *)&id;
     255  		if (!XDR_GETLONG(xdrs, lp++) || !XDR_GETLONG(xdrs, lp))
     256  			return (FALSE);
     257  		for (i = 0, lim = dbl_limits;
     258  			i < sizeof(dbl_limits)/sizeof(struct dbl_limits);
     259  			i++, lim++) {
     260  			if ((id.mantissa2 == lim->ieee.mantissa2) &&
     261  				(id.mantissa1 == lim->ieee.mantissa1) &&
     262  				(id.exp == lim->ieee.exp)) {
     263  				vd = lim->d;
     264  				goto doneit;
     265  			}
     266  		}
     267  		vd.exp = id.exp - IEEE_DBL_BIAS + VAX_DBL_BIAS;
     268  		vd.mantissa1 = (id.mantissa1 >> 13);
     269  		vd.mantissa2 = ((id.mantissa1 & MASK(13)) << 3) |
     270  				(id.mantissa2 >> 29);
     271  		vd.mantissa3 = (id.mantissa2 >> 13);
     272  		vd.mantissa4 = (id.mantissa2 << 3);
     273  	doneit:
     274  		vd.sign = id.sign;
     275  		*dp = *((double *)&vd);
     276  		return (TRUE);
     277  #else
     278  		if (2*sizeof(long) == sizeof(double)) {
     279  			long *lp = (long *)dp;
     280  			return (XDR_GETLONG(xdrs, lp+!LSW) &&
     281  				XDR_GETLONG(xdrs, lp+LSW));
     282  		} else if (2*sizeof(int) == sizeof(double)) {
     283  			int *ip = (int *)dp;
     284  			long tmp[2];
     285  			if (XDR_GETLONG(xdrs, tmp+!LSW) &&
     286  			    XDR_GETLONG(xdrs, tmp+LSW)) {
     287  				ip[0] = tmp[0];
     288  				ip[1] = tmp[1];
     289  				return (TRUE);
     290  			}
     291  		}
     292  		break;
     293  #endif
     294  
     295  	case XDR_FREE:
     296  		return (TRUE);
     297  	}
     298  	return (FALSE);
     299  }
     300  libc_hidden_nolink_sunrpc (xdr_double, GLIBC_2_0)