xref: /original-bsd/usr.bin/f77/libI77/fmtlib.c (revision a910c8b7)
1 /*
2 char id_fmtlib[] = "@(#)fmtlib.c	1.3";
3  *
4  * integer to ascii conversion
5  *
6  * This code has been rearranged to produce optimized runtime code.
7  */
8 
9 #include "fio.h"
10 
11 static char	_digit[] = "0123456789abcdefghijklmnopqrstuvwxyz";
12 static char	_icv_buf[MAXINTLENGTH+1];
13 #define		_mask	0x7fffffff
14 
15 char *
16 icvt(value, ndigit, sign)
17 long	value;
18 int	*ndigit;
19 int	*sign;
20 {
21 	register long	val = value;
22 	register long	rad = radix;
23 	register char	*b = &_icv_buf[MAXINTLENGTH];
24 	register char	*d = _digit;
25 	register long	tmp1;
26 	register int	tmp2;
27 	long	rem;
28 	long	kludge;
29 
30 	if (val == 0)
31 	{
32 		*--b = '0';
33 		*sign = 0;
34 		*ndigit = 1;
35 		return(b);
36 	}
37 
38 	if (signit && (*sign = (val < 0)))	/* signed conversion */
39 	{
40 		/*
41 		 * It is necessary to do the first divide
42 		 * before the absolute value, for the case -2^31
43 		 *
44 		 * This is actually what is being done...
45 		 * tmp1 = (int)(val % rad);
46 		 * val /= rad;
47 		 * val = -val
48 		 * *--b = d[-tmp1];
49 		 */
50 		tmp1 = val / rad;
51 		*--b = d[(tmp1 * rad) - val];
52 		val = -tmp1;
53 	}
54 	else				/* unsigned conversion */
55 	{
56 		*sign = 0;
57 		if (val < 0)
58 		{	/* ALL THIS IS TO SIMULATE UNSIGNED LONG MOD & DIV */
59 			kludge = _mask - (rad - 1);
60 			val &= _mask;
61 			/*
62 			 * This is really what's being done...
63 			 * rem = (kludge % rad) + (val % rad);
64 			 * val = (kludge / rad) + (val / rad) + (rem / rad) + 1;
65 			 * *--b = d[rem % rad];
66 			 */
67 			tmp1 = kludge / rad;
68 			tmp2 = val / rad;
69 			rem = (kludge - (tmp1 * rad)) + (val - (tmp2 * rad));
70 			val = ++tmp1 + tmp2;
71 			tmp1 = rem / rad;
72 			val += tmp1;
73 			*--b = d[rem - (tmp1 * rad)];
74 		}
75 	}
76 
77 	while (val)
78 	{
79 		/*
80 		 * This is really what's being done ...
81 		 * *--b = d[val % rad];
82 		 * val /= rad;
83 		 */
84 		tmp1 = val / rad;
85 		*--b = d[val - (tmp1 * rad)];
86 		val = tmp1;
87 	}
88 
89 	*ndigit = (&_icv_buf[MAXINTLENGTH] - b);
90 	return(b);
91 }
92