source: vendor/bash/3.1/lib/sh/fmtulong.c

Last change on this file was 3228, checked in by bird, 18 years ago

bash 3.1

File size: 3.9 KB
Line 
1/* fmtulong.c -- Convert unsigned long int to string. */
2
3/* Copyright (C) 1998-2002 Free Software Foundation, Inc.
4
5 This file is part of GNU Bash, the Bourne Again SHell.
6
7 Bash is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
11
12 Bash is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License along
18 with Bash; see the file COPYING. If not, write to the Free Software
19 Foundation, 59 Temple Place, Suite 330, Boston, MA 02111 USA. */
20
21#ifdef HAVE_CONFIG_H
22# include <config.h>
23#endif
24
25#if defined (HAVE_UNISTD_H)
26# include <unistd.h>
27#endif
28
29#if defined (HAVE_LIMITS_H)
30# include <limits.h>
31#endif
32
33#include <bashansi.h>
34#ifdef HAVE_STDDEF_H
35# include <stddef.h>
36#endif
37
38#ifdef HAVE_STDINT_H
39# include <stdint.h>
40#endif
41#ifdef HAVE_INTTYPES_H
42# include <inttypes.h>
43#endif
44#include <chartypes.h>
45#include <errno.h>
46
47#include <bashintl.h>
48
49#include "stdc.h"
50
51#include <typemax.h>
52
53#ifndef errno
54extern int errno;
55#endif
56
57#define x_digs "0123456789abcdef"
58#define X_digs "0123456789ABCDEF"
59
60/* XXX -- assumes uppercase letters, lowercase letters, and digits are
61 contiguous */
62#define FMTCHAR(x) \
63 ((x) < 10) ? (x) + '0' \
64 : (((x) < 36) ? (x) - 10 + 'a' \
65 : (((x) < 62) ? (x) - 36 + 'A' \
66 : (((x) == 62) ? '@' : '_')))
67
68#ifndef FL_PREFIX
69# define FL_PREFIX 0x01 /* add 0x, 0X, or 0 prefix as appropriate */
70# define FL_ADDBASE 0x02 /* add base# prefix to converted value */
71# define FL_HEXUPPER 0x04 /* use uppercase when converting to hex */
72# define FL_UNSIGNED 0x08 /* don't add any sign */
73#endif
74
75#ifndef LONG
76# define LONG long
77# define UNSIGNED_LONG unsigned long
78#endif
79
80/* `unsigned long' (or unsigned long long) to string conversion for a given
81 base. The caller passes the output buffer and the size. This should
82 check for buffer underflow, but currently does not. */
83char *
84fmtulong (ui, base, buf, len, flags)
85 UNSIGNED_LONG ui;
86 int base;
87 char *buf;
88 size_t len;
89 int flags;
90{
91 char *p;
92 int sign;
93 LONG si;
94
95 if (base == 0)
96 base = 10;
97
98 if (base < 2 || base > 64)
99 {
100#if 1
101 strncpy (buf, _("invalid base"), len - 1);
102 buf[len] = '\0';
103 errno = EINVAL;
104 return (p = buf);
105#else
106 base = 10;
107#endif
108 }
109
110 sign = 0;
111 if ((flags & FL_UNSIGNED) == 0 && (LONG)ui < 0)
112 {
113 ui = -ui;
114 sign = '-';
115 }
116
117 p = buf + len - 2;
118 p[1] = '\0';
119
120 /* handle common cases explicitly */
121 switch (base)
122 {
123 case 10:
124 if (ui < 10)
125 {
126 *p-- = TOCHAR (ui);
127 break;
128 }
129 /* Favor signed arithmetic over unsigned arithmetic; it is faster on
130 many machines. */
131 if ((LONG)ui < 0)
132 {
133 *p-- = TOCHAR (ui % 10);
134 si = ui / 10;
135 }
136 else
137 si = ui;
138 do
139 *p-- = TOCHAR (si % 10);
140 while (si /= 10);
141 break;
142
143 case 8:
144 do
145 *p-- = TOCHAR (ui & 7);
146 while (ui >>= 3);
147 break;
148
149 case 16:
150 do
151 *p-- = (flags & FL_HEXUPPER) ? X_digs[ui & 15] : x_digs[ui & 15];
152 while (ui >>= 4);
153 break;
154
155 case 2:
156 do
157 *p-- = TOCHAR (ui & 1);
158 while (ui >>= 1);
159 break;
160
161 default:
162 do
163 *p-- = FMTCHAR (ui % base);
164 while (ui /= base);
165 break;
166 }
167
168 if ((flags & FL_PREFIX) && (base == 8 || base == 16))
169 {
170 if (base == 16)
171 {
172 *p-- = (flags & FL_HEXUPPER) ? 'X' : 'x';
173 *p-- = '0';
174 }
175 else if (p[1] != '0')
176 *p-- = '0';
177 }
178 else if ((flags & FL_ADDBASE) && base != 10)
179 {
180 *p-- = '#';
181 *p-- = TOCHAR (base % 10);
182 if (base > 10)
183 *p-- = TOCHAR (base / 10);
184 }
185
186 if (sign)
187 *p-- = '-';
188
189 return (p + 1);
190}
Note: See TracBrowser for help on using the repository browser.