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>
22 void *finddevice(const char *name
);
23 int getprop(void *phandle
, const char *name
, void *buf
, int buflen
);
24 void chrpboot(int a1
, int a2
, void *prom
); /* in main.c */
26 void printk(char *fmt
, ...);
28 /* there is no convenient header to get this from... -- paulus */
29 extern unsigned long strlen(const char *);
32 write(void *handle
, void *ptr
, int nb
)
44 args
.service
= "write";
47 args
.ihandle
= handle
;
56 read(void *handle
, void *ptr
, int nb
)
68 args
.service
= "read";
71 args
.ihandle
= handle
;
87 args
.service
= "exit";
99 args
.service
= "enter";
104 finddevice(const char *name
)
114 args
.service
= "finddevice";
118 args
.phandle
= (void *) -1;
124 claim(unsigned long virt
, unsigned long size
, unsigned long align
)
136 args
.service
= "claim";
147 getprop(void *phandle
, const char *name
, void *buf
, int buflen
)
160 args
.service
= "getprop";
163 args
.phandle
= phandle
;
166 args
.buflen
= buflen
;
179 return write(f
, &ch
, 1) == 1? c
: -1;
185 return putc(c
, stdout
);
189 fputs(char *str
, void *f
)
193 return write(f
, str
, n
) == n
? 0: -1;
202 switch (read(stdin
, &ch
, 1)) {
206 printk("read(stdin) returned -1\r\n");
212 static char line
[256];
213 static char *lineptr
;
225 if (c
== -1 || c
== 4)
227 if (c
== '\r' || c
== '\n') {
235 if (lineptr
> line
) {
243 while (lineptr
> line
) {
251 if (lineptr
>= &line
[sizeof(line
) - 1])
259 lineleft
= lineptr
- line
;
270 /* String functions lifted from lib/vsprintf.c and lib/ctype.c */
271 unsigned char _ctype
[] = {
272 _C
,_C
,_C
,_C
,_C
,_C
,_C
,_C
, /* 0-7 */
273 _C
,_C
|_S
,_C
|_S
,_C
|_S
,_C
|_S
,_C
|_S
,_C
,_C
, /* 8-15 */
274 _C
,_C
,_C
,_C
,_C
,_C
,_C
,_C
, /* 16-23 */
275 _C
,_C
,_C
,_C
,_C
,_C
,_C
,_C
, /* 24-31 */
276 _S
|_SP
,_P
,_P
,_P
,_P
,_P
,_P
,_P
, /* 32-39 */
277 _P
,_P
,_P
,_P
,_P
,_P
,_P
,_P
, /* 40-47 */
278 _D
,_D
,_D
,_D
,_D
,_D
,_D
,_D
, /* 48-55 */
279 _D
,_D
,_P
,_P
,_P
,_P
,_P
,_P
, /* 56-63 */
280 _P
,_U
|_X
,_U
|_X
,_U
|_X
,_U
|_X
,_U
|_X
,_U
|_X
,_U
, /* 64-71 */
281 _U
,_U
,_U
,_U
,_U
,_U
,_U
,_U
, /* 72-79 */
282 _U
,_U
,_U
,_U
,_U
,_U
,_U
,_U
, /* 80-87 */
283 _U
,_U
,_U
,_P
,_P
,_P
,_P
,_P
, /* 88-95 */
284 _P
,_L
|_X
,_L
|_X
,_L
|_X
,_L
|_X
,_L
|_X
,_L
|_X
,_L
, /* 96-103 */
285 _L
,_L
,_L
,_L
,_L
,_L
,_L
,_L
, /* 104-111 */
286 _L
,_L
,_L
,_L
,_L
,_L
,_L
,_L
, /* 112-119 */
287 _L
,_L
,_L
,_P
,_P
,_P
,_P
,_C
, /* 120-127 */
288 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
289 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
290 _S
|_SP
,_P
,_P
,_P
,_P
,_P
,_P
,_P
,_P
,_P
,_P
,_P
,_P
,_P
,_P
,_P
, /* 160-175 */
291 _P
,_P
,_P
,_P
,_P
,_P
,_P
,_P
,_P
,_P
,_P
,_P
,_P
,_P
,_P
,_P
, /* 176-191 */
292 _U
,_U
,_U
,_U
,_U
,_U
,_U
,_U
,_U
,_U
,_U
,_U
,_U
,_U
,_U
,_U
, /* 192-207 */
293 _U
,_U
,_U
,_U
,_U
,_U
,_U
,_P
,_U
,_U
,_U
,_U
,_U
,_U
,_U
,_L
, /* 208-223 */
294 _L
,_L
,_L
,_L
,_L
,_L
,_L
,_L
,_L
,_L
,_L
,_L
,_L
,_L
,_L
,_L
, /* 224-239 */
295 _L
,_L
,_L
,_L
,_L
,_L
,_L
,_P
,_L
,_L
,_L
,_L
,_L
,_L
,_L
,_L
}; /* 240-255 */
297 size_t strnlen(const char * s
, size_t count
)
301 for (sc
= s
; count
-- && *sc
!= '\0'; ++sc
)
306 unsigned long simple_strtoul(const char *cp
,char **endp
,unsigned int base
)
308 unsigned long result
= 0,value
;
315 if ((*cp
== 'x') && isxdigit(cp
[1])) {
321 while (isxdigit(*cp
) &&
322 (value
= isdigit(*cp
) ? *cp
-'0' : toupper(*cp
)-'A'+10) < base
) {
323 result
= result
*base
+ value
;
331 long simple_strtol(const char *cp
,char **endp
,unsigned int base
)
334 return -simple_strtoul(cp
+1,endp
,base
);
335 return simple_strtoul(cp
,endp
,base
);
338 static int skip_atoi(const char **s
)
343 i
= i
*10 + *((*s
)++) - '0';
347 #define ZEROPAD 1 /* pad with zero */
348 #define SIGN 2 /* unsigned/signed long */
349 #define PLUS 4 /* show plus */
350 #define SPACE 8 /* space if plus */
351 #define LEFT 16 /* left justified */
352 #define SPECIAL 32 /* 0x */
353 #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */
355 static char * number(char * str
, long num
, int base
, int size
, int precision
, int type
)
358 const char *digits
="0123456789abcdefghijklmnopqrstuvwxyz";
362 digits
= "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
365 if (base
< 2 || base
> 36)
367 c
= (type
& ZEROPAD
) ? '0' : ' ';
374 } else if (type
& PLUS
) {
377 } else if (type
& SPACE
) {
382 if (type
& SPECIAL
) {
391 else while (num
!= 0) {
392 tmp
[i
++] = digits
[num
% base
];
398 if (!(type
&(ZEROPAD
+LEFT
)))
403 if (type
& SPECIAL
) {
414 while (i
< precision
--)
423 /* Forward decl. needed for IP address printing stuff... */
424 int sprintf(char * buf
, const char *fmt
, ...);
426 int vsprintf(char *buf
, const char *fmt
, va_list args
)
434 int flags
; /* flags to number() */
436 int field_width
; /* width of output field */
437 int precision
; /* min. # of digits for integers; max
438 number of chars for from string */
439 int qualifier
; /* 'h', 'l', or 'L' for integer fields */
440 /* 'z' support added 23/7/1999 S.H. */
441 /* 'z' changed to 'Z' --davidm 1/25/99 */
444 for (str
=buf
; *fmt
; ++fmt
) {
453 ++fmt
; /* this also skips first '%' */
455 case '-': flags
|= LEFT
; goto repeat
;
456 case '+': flags
|= PLUS
; goto repeat
;
457 case ' ': flags
|= SPACE
; goto repeat
;
458 case '#': flags
|= SPECIAL
; goto repeat
;
459 case '0': flags
|= ZEROPAD
; goto repeat
;
462 /* get field width */
465 field_width
= skip_atoi(&fmt
);
466 else if (*fmt
== '*') {
468 /* it's the next argument */
469 field_width
= va_arg(args
, int);
470 if (field_width
< 0) {
471 field_width
= -field_width
;
476 /* get the precision */
481 precision
= skip_atoi(&fmt
);
482 else if (*fmt
== '*') {
484 /* it's the next argument */
485 precision
= va_arg(args
, int);
491 /* get the conversion qualifier */
493 if (*fmt
== 'h' || *fmt
== 'l' || *fmt
== 'L' || *fmt
=='Z') {
504 while (--field_width
> 0)
506 *str
++ = (unsigned char) va_arg(args
, int);
507 while (--field_width
> 0)
512 s
= va_arg(args
, char *);
516 len
= strnlen(s
, precision
);
519 while (len
< field_width
--)
521 for (i
= 0; i
< len
; ++i
)
523 while (len
< field_width
--)
528 if (field_width
== -1) {
529 field_width
= 2*sizeof(void *);
533 (unsigned long) va_arg(args
, void *), 16,
534 field_width
, precision
, flags
);
539 if (qualifier
== 'l') {
540 long * ip
= va_arg(args
, long *);
542 } else if (qualifier
== 'Z') {
543 size_t * ip
= va_arg(args
, size_t *);
546 int * ip
= va_arg(args
, int *);
555 /* integer number formats - set up the flags and "break" */
580 if (qualifier
== 'l') {
581 num
= va_arg(args
, unsigned long);
583 num
= (signed long) num
;
584 } else if (qualifier
== 'Z') {
585 num
= va_arg(args
, size_t);
586 } else if (qualifier
== 'h') {
587 num
= (unsigned short) va_arg(args
, int);
589 num
= (signed short) num
;
591 num
= va_arg(args
, unsigned int);
593 num
= (signed int) num
;
595 str
= number(str
, num
, base
, field_width
, precision
, flags
);
601 int sprintf(char * buf
, const char *fmt
, ...)
607 i
=vsprintf(buf
,fmt
,args
);
612 static char sprint_buf
[1024];
615 printk(char *fmt
, ...)
621 n
= vsprintf(sprint_buf
, fmt
, args
);
623 write(stdout
, sprint_buf
, n
);
627 printf(char *fmt
, ...)
633 n
= vsprintf(sprint_buf
, fmt
, args
);
635 write(stdout
, sprint_buf
, n
);