Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/alpha/boot/stdio.c
26424 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* Copyright (C) Paul Mackerras 1997.
4
*/
5
#include <linux/string.h>
6
#include <linux/stdarg.h>
7
8
size_t strnlen(const char * s, size_t count)
9
{
10
const char *sc;
11
12
for (sc = s; count-- && *sc != '\0'; ++sc)
13
/* nothing */;
14
return sc - s;
15
}
16
17
# define do_div(n, base) ({ \
18
unsigned int __base = (base); \
19
unsigned int __rem; \
20
__rem = ((unsigned long long)(n)) % __base; \
21
(n) = ((unsigned long long)(n)) / __base; \
22
__rem; \
23
})
24
25
26
static int skip_atoi(const char **s)
27
{
28
int i, c;
29
30
for (i = 0; '0' <= (c = **s) && c <= '9'; ++*s)
31
i = i*10 + c - '0';
32
return i;
33
}
34
35
#define ZEROPAD 1 /* pad with zero */
36
#define SIGN 2 /* unsigned/signed long */
37
#define PLUS 4 /* show plus */
38
#define SPACE 8 /* space if plus */
39
#define LEFT 16 /* left justified */
40
#define SPECIAL 32 /* 0x */
41
#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
42
43
static char * number(char * str, unsigned long long num, int base, int size, int precision, int type)
44
{
45
char c, sign, tmp[66];
46
const char *digits = "0123456789abcdefghijklmnopqrstuvwxyz";
47
int i;
48
49
if (type & LARGE)
50
digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
51
if (type & LEFT)
52
type &= ~ZEROPAD;
53
if (base < 2 || base > 36)
54
return 0;
55
c = (type & ZEROPAD) ? '0' : ' ';
56
sign = 0;
57
if (type & SIGN) {
58
if ((signed long long)num < 0) {
59
sign = '-';
60
num = - (signed long long)num;
61
size--;
62
} else if (type & PLUS) {
63
sign = '+';
64
size--;
65
} else if (type & SPACE) {
66
sign = ' ';
67
size--;
68
}
69
}
70
if (type & SPECIAL) {
71
if (base == 16)
72
size -= 2;
73
else if (base == 8)
74
size--;
75
}
76
i = 0;
77
if (num == 0)
78
tmp[i++]='0';
79
else while (num != 0) {
80
tmp[i++] = digits[do_div(num, base)];
81
}
82
if (i > precision)
83
precision = i;
84
size -= precision;
85
if (!(type&(ZEROPAD+LEFT)))
86
while (size-- > 0)
87
*str++ = ' ';
88
if (sign)
89
*str++ = sign;
90
if (type & SPECIAL) {
91
if (base==8)
92
*str++ = '0';
93
else if (base == 16) {
94
*str++ = '0';
95
*str++ = digits[33];
96
}
97
}
98
if (!(type & LEFT))
99
while (size-- > 0)
100
*str++ = c;
101
while (i < precision--)
102
*str++ = '0';
103
while (i-- > 0)
104
*str++ = tmp[i];
105
while (size-- > 0)
106
*str++ = ' ';
107
return str;
108
}
109
110
int vsprintf(char *buf, const char *fmt, va_list args)
111
{
112
int len;
113
unsigned long long num;
114
int i, base;
115
char * str;
116
const char *s;
117
118
int flags; /* flags to number() */
119
120
int field_width; /* width of output field */
121
int precision; /* min. # of digits for integers; max
122
number of chars for from string */
123
int qualifier; /* 'h', 'l', or 'L' for integer fields */
124
/* 'z' support added 23/7/1999 S.H. */
125
/* 'z' changed to 'Z' --davidm 1/25/99 */
126
127
128
for (str = buf ; *fmt ; ++fmt) {
129
if (*fmt != '%') {
130
*str++ = *fmt;
131
continue;
132
}
133
134
/* process flags */
135
flags = 0;
136
repeat:
137
++fmt; /* this also skips first '%' */
138
switch (*fmt) {
139
case '-': flags |= LEFT; goto repeat;
140
case '+': flags |= PLUS; goto repeat;
141
case ' ': flags |= SPACE; goto repeat;
142
case '#': flags |= SPECIAL; goto repeat;
143
case '0': flags |= ZEROPAD; goto repeat;
144
}
145
146
/* get field width */
147
field_width = -1;
148
if ('0' <= *fmt && *fmt <= '9')
149
field_width = skip_atoi(&fmt);
150
else if (*fmt == '*') {
151
++fmt;
152
/* it's the next argument */
153
field_width = va_arg(args, int);
154
if (field_width < 0) {
155
field_width = -field_width;
156
flags |= LEFT;
157
}
158
}
159
160
/* get the precision */
161
precision = -1;
162
if (*fmt == '.') {
163
++fmt;
164
if ('0' <= *fmt && *fmt <= '9')
165
precision = skip_atoi(&fmt);
166
else if (*fmt == '*') {
167
++fmt;
168
/* it's the next argument */
169
precision = va_arg(args, int);
170
}
171
if (precision < 0)
172
precision = 0;
173
}
174
175
/* get the conversion qualifier */
176
qualifier = -1;
177
if (*fmt == 'l' && *(fmt + 1) == 'l') {
178
qualifier = 'q';
179
fmt += 2;
180
} else if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L'
181
|| *fmt == 'Z') {
182
qualifier = *fmt;
183
++fmt;
184
}
185
186
/* default base */
187
base = 10;
188
189
switch (*fmt) {
190
case 'c':
191
if (!(flags & LEFT))
192
while (--field_width > 0)
193
*str++ = ' ';
194
*str++ = (unsigned char) va_arg(args, int);
195
while (--field_width > 0)
196
*str++ = ' ';
197
continue;
198
199
case 's':
200
s = va_arg(args, char *);
201
if (!s)
202
s = "<NULL>";
203
204
len = strnlen(s, precision);
205
206
if (!(flags & LEFT))
207
while (len < field_width--)
208
*str++ = ' ';
209
for (i = 0; i < len; ++i)
210
*str++ = *s++;
211
while (len < field_width--)
212
*str++ = ' ';
213
continue;
214
215
case 'p':
216
if (field_width == -1) {
217
field_width = 2*sizeof(void *);
218
flags |= ZEROPAD;
219
}
220
str = number(str,
221
(unsigned long) va_arg(args, void *), 16,
222
field_width, precision, flags);
223
continue;
224
225
226
case 'n':
227
if (qualifier == 'l') {
228
long * ip = va_arg(args, long *);
229
*ip = (str - buf);
230
} else if (qualifier == 'Z') {
231
size_t * ip = va_arg(args, size_t *);
232
*ip = (str - buf);
233
} else {
234
int * ip = va_arg(args, int *);
235
*ip = (str - buf);
236
}
237
continue;
238
239
case '%':
240
*str++ = '%';
241
continue;
242
243
/* integer number formats - set up the flags and "break" */
244
case 'o':
245
base = 8;
246
break;
247
248
case 'X':
249
flags |= LARGE;
250
case 'x':
251
base = 16;
252
break;
253
254
case 'd':
255
case 'i':
256
flags |= SIGN;
257
case 'u':
258
break;
259
260
default:
261
*str++ = '%';
262
if (*fmt)
263
*str++ = *fmt;
264
else
265
--fmt;
266
continue;
267
}
268
if (qualifier == 'l') {
269
num = va_arg(args, unsigned long);
270
if (flags & SIGN)
271
num = (signed long) num;
272
} else if (qualifier == 'q') {
273
num = va_arg(args, unsigned long long);
274
if (flags & SIGN)
275
num = (signed long long) num;
276
} else if (qualifier == 'Z') {
277
num = va_arg(args, size_t);
278
} else if (qualifier == 'h') {
279
num = (unsigned short) va_arg(args, int);
280
if (flags & SIGN)
281
num = (signed short) num;
282
} else {
283
num = va_arg(args, unsigned int);
284
if (flags & SIGN)
285
num = (signed int) num;
286
}
287
str = number(str, num, base, field_width, precision, flags);
288
}
289
*str = '\0';
290
return str-buf;
291
}
292
293
int sprintf(char * buf, const char *fmt, ...)
294
{
295
va_list args;
296
int i;
297
298
va_start(args, fmt);
299
i = vsprintf(buf, fmt, args);
300
va_end(args);
301
return i;
302
}
303
304