2 * Copyright (C) Paul Mackerras 1997.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
10 #include <linux/types.h>
11 #include <linux/string.h>
12 #include <linux/ctype.h>
14 extern __u32
__div64_32(unsigned long long *dividend
, __u32 divisor
);
16 /* The unnecessary pointer compare is there
17 * to check for type safety (n must be 64bit)
19 # define do_div(n,base) ({ \
20 __u32 __base = (base); \
22 (void)(((typeof((n)) *)0) == ((unsigned long long *)0)); \
23 if (((n) >> 32) == 0) { \
24 __rem = (__u32)(n) % __base; \
25 (n) = (__u32)(n) / __base; \
27 __rem = __div64_32(&(n), __base); \
39 void *finddevice(const char *name
);
40 int getprop(void *phandle
, const char *name
, void *buf
, int buflen
);
41 void chrpboot(int a1
, int a2
, void *prom
); /* in main.c */
43 int printf(char *fmt
, ...);
45 /* there is no convenient header to get this from... -- paulus */
46 extern unsigned long strlen(const char *);
49 write(void *handle
, void *ptr
, int nb
)
61 args
.service
= "write";
64 args
.ihandle
= handle
;
73 read(void *handle
, void *ptr
, int nb
)
85 args
.service
= "read";
88 args
.ihandle
= handle
;
104 args
.service
= "exit";
116 args
.service
= "enter";
121 finddevice(const char *name
)
131 args
.service
= "finddevice";
135 args
.phandle
= (void *) -1;
141 claim(unsigned long virt
, unsigned long size
, unsigned long align
)
153 args
.service
= "claim";
164 getprop(void *phandle
, const char *name
, void *buf
, int buflen
)
177 args
.service
= "getprop";
180 args
.phandle
= phandle
;
183 args
.buflen
= buflen
;
196 return write(f
, &ch
, 1) == 1? c
: -1;
202 return putc(c
, stdout
);
206 fputs(char *str
, void *f
)
210 return write(f
, str
, n
) == n
? 0: -1;
219 switch (read(stdin
, &ch
, 1)) {
223 printf("read(stdin) returned -1\r\n");
229 static char line
[256];
230 static char *lineptr
;
242 if (c
== -1 || c
== 4)
244 if (c
== '\r' || c
== '\n') {
252 if (lineptr
> line
) {
260 while (lineptr
> line
) {
268 if (lineptr
>= &line
[sizeof(line
) - 1])
276 lineleft
= lineptr
- line
;
287 /* String functions lifted from lib/vsprintf.c and lib/ctype.c */
288 unsigned char _ctype
[] = {
289 _C
,_C
,_C
,_C
,_C
,_C
,_C
,_C
, /* 0-7 */
290 _C
,_C
|_S
,_C
|_S
,_C
|_S
,_C
|_S
,_C
|_S
,_C
,_C
, /* 8-15 */
291 _C
,_C
,_C
,_C
,_C
,_C
,_C
,_C
, /* 16-23 */
292 _C
,_C
,_C
,_C
,_C
,_C
,_C
,_C
, /* 24-31 */
293 _S
|_SP
,_P
,_P
,_P
,_P
,_P
,_P
,_P
, /* 32-39 */
294 _P
,_P
,_P
,_P
,_P
,_P
,_P
,_P
, /* 40-47 */
295 _D
,_D
,_D
,_D
,_D
,_D
,_D
,_D
, /* 48-55 */
296 _D
,_D
,_P
,_P
,_P
,_P
,_P
,_P
, /* 56-63 */
297 _P
,_U
|_X
,_U
|_X
,_U
|_X
,_U
|_X
,_U
|_X
,_U
|_X
,_U
, /* 64-71 */
298 _U
,_U
,_U
,_U
,_U
,_U
,_U
,_U
, /* 72-79 */
299 _U
,_U
,_U
,_U
,_U
,_U
,_U
,_U
, /* 80-87 */
300 _U
,_U
,_U
,_P
,_P
,_P
,_P
,_P
, /* 88-95 */
301 _P
,_L
|_X
,_L
|_X
,_L
|_X
,_L
|_X
,_L
|_X
,_L
|_X
,_L
, /* 96-103 */
302 _L
,_L
,_L
,_L
,_L
,_L
,_L
,_L
, /* 104-111 */
303 _L
,_L
,_L
,_L
,_L
,_L
,_L
,_L
, /* 112-119 */
304 _L
,_L
,_L
,_P
,_P
,_P
,_P
,_C
, /* 120-127 */
305 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
306 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
307 _S
|_SP
,_P
,_P
,_P
,_P
,_P
,_P
,_P
,_P
,_P
,_P
,_P
,_P
,_P
,_P
,_P
, /* 160-175 */
308 _P
,_P
,_P
,_P
,_P
,_P
,_P
,_P
,_P
,_P
,_P
,_P
,_P
,_P
,_P
,_P
, /* 176-191 */
309 _U
,_U
,_U
,_U
,_U
,_U
,_U
,_U
,_U
,_U
,_U
,_U
,_U
,_U
,_U
,_U
, /* 192-207 */
310 _U
,_U
,_U
,_U
,_U
,_U
,_U
,_P
,_U
,_U
,_U
,_U
,_U
,_U
,_U
,_L
, /* 208-223 */
311 _L
,_L
,_L
,_L
,_L
,_L
,_L
,_L
,_L
,_L
,_L
,_L
,_L
,_L
,_L
,_L
, /* 224-239 */
312 _L
,_L
,_L
,_L
,_L
,_L
,_L
,_P
,_L
,_L
,_L
,_L
,_L
,_L
,_L
,_L
}; /* 240-255 */
314 size_t strnlen(const char * s
, size_t count
)
318 for (sc
= s
; count
-- && *sc
!= '\0'; ++sc
)
323 unsigned long simple_strtoul(const char *cp
,char **endp
,unsigned int base
)
325 unsigned long result
= 0,value
;
332 if ((*cp
== 'x') && isxdigit(cp
[1])) {
338 while (isxdigit(*cp
) &&
339 (value
= isdigit(*cp
) ? *cp
-'0' : toupper(*cp
)-'A'+10) < base
) {
340 result
= result
*base
+ value
;
348 long simple_strtol(const char *cp
,char **endp
,unsigned int base
)
351 return -simple_strtoul(cp
+1,endp
,base
);
352 return simple_strtoul(cp
,endp
,base
);
355 static int skip_atoi(const char **s
)
360 i
= i
*10 + *((*s
)++) - '0';
364 #define ZEROPAD 1 /* pad with zero */
365 #define SIGN 2 /* unsigned/signed long */
366 #define PLUS 4 /* show plus */
367 #define SPACE 8 /* space if plus */
368 #define LEFT 16 /* left justified */
369 #define SPECIAL 32 /* 0x */
370 #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
372 static char * number(char * str
, unsigned long long num
, int base
, int size
, int precision
, int type
)
375 const char *digits
="0123456789abcdefghijklmnopqrstuvwxyz";
379 digits
= "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
382 if (base
< 2 || base
> 36)
384 c
= (type
& ZEROPAD
) ? '0' : ' ';
387 if ((signed long long)num
< 0) {
389 num
= - (signed long long)num
;
391 } else if (type
& PLUS
) {
394 } else if (type
& SPACE
) {
399 if (type
& SPECIAL
) {
408 else while (num
!= 0) {
409 tmp
[i
++] = digits
[do_div(num
, base
)];
414 if (!(type
&(ZEROPAD
+LEFT
)))
419 if (type
& SPECIAL
) {
430 while (i
< precision
--)
439 /* Forward decl. needed for IP address printing stuff... */
440 int sprintf(char * buf
, const char *fmt
, ...);
442 int vsprintf(char *buf
, const char *fmt
, va_list args
)
445 unsigned long long num
;
450 int flags
; /* flags to number() */
452 int field_width
; /* width of output field */
453 int precision
; /* min. # of digits for integers; max
454 number of chars for from string */
455 int qualifier
; /* 'h', 'l', or 'L' for integer fields */
456 /* 'z' support added 23/7/1999 S.H. */
457 /* 'z' changed to 'Z' --davidm 1/25/99 */
460 for (str
=buf
; *fmt
; ++fmt
) {
469 ++fmt
; /* this also skips first '%' */
471 case '-': flags
|= LEFT
; goto repeat
;
472 case '+': flags
|= PLUS
; goto repeat
;
473 case ' ': flags
|= SPACE
; goto repeat
;
474 case '#': flags
|= SPECIAL
; goto repeat
;
475 case '0': flags
|= ZEROPAD
; goto repeat
;
478 /* get field width */
481 field_width
= skip_atoi(&fmt
);
482 else if (*fmt
== '*') {
484 /* it's the next argument */
485 field_width
= va_arg(args
, int);
486 if (field_width
< 0) {
487 field_width
= -field_width
;
492 /* get the precision */
497 precision
= skip_atoi(&fmt
);
498 else if (*fmt
== '*') {
500 /* it's the next argument */
501 precision
= va_arg(args
, int);
507 /* get the conversion qualifier */
509 if (*fmt
== 'h' || *fmt
== 'l' || *fmt
== 'L' || *fmt
=='Z') {
520 while (--field_width
> 0)
522 *str
++ = (unsigned char) va_arg(args
, int);
523 while (--field_width
> 0)
528 s
= va_arg(args
, char *);
532 len
= strnlen(s
, precision
);
535 while (len
< field_width
--)
537 for (i
= 0; i
< len
; ++i
)
539 while (len
< field_width
--)
544 if (field_width
== -1) {
545 field_width
= 2*sizeof(void *);
549 (unsigned long) va_arg(args
, void *), 16,
550 field_width
, precision
, flags
);
555 if (qualifier
== 'l') {
556 long * ip
= va_arg(args
, long *);
558 } else if (qualifier
== 'Z') {
559 size_t * ip
= va_arg(args
, size_t *);
562 int * ip
= va_arg(args
, int *);
571 /* integer number formats - set up the flags and "break" */
596 if (qualifier
== 'l') {
597 num
= va_arg(args
, unsigned long);
599 num
= (signed long) num
;
600 } else if (qualifier
== 'Z') {
601 num
= va_arg(args
, size_t);
602 } else if (qualifier
== 'h') {
603 num
= (unsigned short) va_arg(args
, int);
605 num
= (signed short) num
;
607 num
= va_arg(args
, unsigned int);
609 num
= (signed int) num
;
611 str
= number(str
, num
, base
, field_width
, precision
, flags
);
617 int sprintf(char * buf
, const char *fmt
, ...)
623 i
=vsprintf(buf
,fmt
,args
);
628 static char sprint_buf
[1024];
631 printf(char *fmt
, ...)
637 n
= vsprintf(sprint_buf
, fmt
, args
);
639 write(stdout
, sprint_buf
, n
);