Merge aruba support
[openwrt/svn-archive/archive.git] / openwrt / target / linux / image / aruba / lzma-loader / src / print.c
1 /*
2 * Copyright (C) 2001 MontaVista Software Inc.
3 * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version.
9 *
10 */
11
12 #include "print.h"
13
14 /* macros */
15 #define IsDigit(x) ( ((x) >= '0') && ((x) <= '9') )
16 #define Ctod(x) ( (x) - '0')
17
18 /* forward declaration */
19 extern int PrintChar(char *, char, int, int);
20 extern int PrintString(char *, char *, int, int);
21 extern int PrintNum(char *, unsigned long, int, int, int, int, char, int);
22
23 /* private variable */
24 static const char theFatalMsg[] = "fatal error in lp_Print!";
25
26 /* -*-
27 * A low level printf() function.
28 */
29 void
30 lp_Print(void (*output)(void *, char *, int),
31 void * arg,
32 char *fmt,
33 va_list ap)
34 {
35
36 #define OUTPUT(arg, s, l) \
37 { if (((l) < 0) || ((l) > LP_MAX_BUF)) { \
38 (*output)(arg, (char*)theFatalMsg, sizeof(theFatalMsg)-1); for(;;); \
39 } else { \
40 (*output)(arg, s, l); \
41 } \
42 }
43
44 char buf[LP_MAX_BUF];
45
46 char c;
47 char *s;
48 long int num;
49
50 int longFlag;
51 int negFlag;
52 int width;
53 int prec;
54 int ladjust;
55 char padc;
56
57 int length;
58
59 for(;;) {
60 {
61 /* scan for the next '%' */
62 char *fmtStart = fmt;
63 while ( (*fmt != '\0') && (*fmt != '%')) {
64 fmt ++;
65 }
66
67 /* flush the string found so far */
68 OUTPUT(arg, fmtStart, fmt-fmtStart);
69
70 /* are we hitting the end? */
71 if (*fmt == '\0') break;
72 }
73
74 /* we found a '%' */
75 fmt ++;
76
77 /* check for long */
78 if (*fmt == 'l') {
79 longFlag = 1;
80 fmt ++;
81 } else {
82 longFlag = 0;
83 }
84
85 /* check for other prefixes */
86 width = 0;
87 prec = -1;
88 ladjust = 0;
89 padc = ' ';
90
91 if (*fmt == '-') {
92 ladjust = 1;
93 fmt ++;
94 }
95
96 if (*fmt == '0') {
97 padc = '0';
98 fmt++;
99 }
100
101 if (IsDigit(*fmt)) {
102 while (IsDigit(*fmt)) {
103 width = 10 * width + Ctod(*fmt++);
104 }
105 }
106
107 if (*fmt == '.') {
108 fmt ++;
109 if (IsDigit(*fmt)) {
110 prec = 0;
111 while (IsDigit(*fmt)) {
112 prec = prec*10 + Ctod(*fmt++);
113 }
114 }
115 }
116
117
118 /* check format flag */
119 negFlag = 0;
120 switch (*fmt) {
121 case 'b':
122 if (longFlag) {
123 num = va_arg(ap, long int);
124 } else {
125 num = va_arg(ap, int);
126 }
127 length = PrintNum(buf, num, 2, 0, width, ladjust, padc, 0);
128 OUTPUT(arg, buf, length);
129 break;
130
131 case 'd':
132 case 'D':
133 if (longFlag) {
134 num = va_arg(ap, long int);
135 } else {
136 num = va_arg(ap, int);
137 }
138 if (num < 0) {
139 num = - num;
140 negFlag = 1;
141 }
142 length = PrintNum(buf, num, 10, negFlag, width, ladjust, padc, 0);
143 OUTPUT(arg, buf, length);
144 break;
145
146 case 'o':
147 case 'O':
148 if (longFlag) {
149 num = va_arg(ap, long int);
150 } else {
151 num = va_arg(ap, int);
152 }
153 length = PrintNum(buf, num, 8, 0, width, ladjust, padc, 0);
154 OUTPUT(arg, buf, length);
155 break;
156
157 case 'u':
158 case 'U':
159 if (longFlag) {
160 num = va_arg(ap, long int);
161 } else {
162 num = va_arg(ap, int);
163 }
164 length = PrintNum(buf, num, 10, 0, width, ladjust, padc, 0);
165 OUTPUT(arg, buf, length);
166 break;
167
168 case 'x':
169 if (longFlag) {
170 num = va_arg(ap, long int);
171 } else {
172 num = va_arg(ap, int);
173 }
174 length = PrintNum(buf, num, 16, 0, width, ladjust, padc, 0);
175 OUTPUT(arg, buf, length);
176 break;
177
178 case 'X':
179 if (longFlag) {
180 num = va_arg(ap, long int);
181 } else {
182 num = va_arg(ap, int);
183 }
184 length = PrintNum(buf, num, 16, 0, width, ladjust, padc, 1);
185 OUTPUT(arg, buf, length);
186 break;
187
188 case 'c':
189 c = (char)va_arg(ap, int);
190 length = PrintChar(buf, c, width, ladjust);
191 OUTPUT(arg, buf, length);
192 break;
193
194 case 's':
195 s = (char*)va_arg(ap, char *);
196 length = PrintString(buf, s, width, ladjust);
197 OUTPUT(arg, buf, length);
198 break;
199
200 case '\0':
201 fmt --;
202 break;
203
204 default:
205 /* output this char as it is */
206 OUTPUT(arg, fmt, 1);
207 } /* switch (*fmt) */
208
209 fmt ++;
210 } /* for(;;) */
211
212 /* special termination call */
213 OUTPUT(arg, "\0", 1);
214 }
215
216
217 /* --------------- local help functions --------------------- */
218 int
219 PrintChar(char * buf, char c, int length, int ladjust)
220 {
221 int i;
222
223 if (length < 1) length = 1;
224 if (ladjust) {
225 *buf = c;
226 for (i=1; i< length; i++) buf[i] = ' ';
227 } else {
228 for (i=0; i< length-1; i++) buf[i] = ' ';
229 buf[length - 1] = c;
230 }
231 return length;
232 }
233
234 int
235 PrintString(char * buf, char* s, int length, int ladjust)
236 {
237 int i;
238 int len=0;
239 char* s1 = s;
240 while (*s1++) len++;
241 if (length < len) length = len;
242
243 if (ladjust) {
244 for (i=0; i< len; i++) buf[i] = s[i];
245 for (i=len; i< length; i++) buf[i] = ' ';
246 } else {
247 for (i=0; i< length-len; i++) buf[i] = ' ';
248 for (i=length-len; i < length; i++) buf[i] = s[i-length+len];
249 }
250 return length;
251 }
252
253 int
254 PrintNum(char * buf, unsigned long u, int base, int negFlag,
255 int length, int ladjust, char padc, int upcase)
256 {
257 /* algorithm :
258 * 1. prints the number from left to right in reverse form.
259 * 2. fill the remaining spaces with padc if length is longer than
260 * the actual length
261 * TRICKY : if left adjusted, no "0" padding.
262 * if negtive, insert "0" padding between "0" and number.
263 * 3. if (!ladjust) we reverse the whole string including paddings
264 * 4. otherwise we only reverse the actual string representing the num.
265 */
266
267 int actualLength =0;
268 char *p = buf;
269 int i;
270
271 do {
272 int tmp = u %base;
273 if (tmp <= 9) {
274 *p++ = '0' + tmp;
275 } else if (upcase) {
276 *p++ = 'A' + tmp - 10;
277 } else {
278 *p++ = 'a' + tmp - 10;
279 }
280 u /= base;
281 } while (u != 0);
282
283 if (negFlag) {
284 *p++ = '-';
285 }
286
287 /* figure out actual length and adjust the maximum length */
288 actualLength = p - buf;
289 if (length < actualLength) length = actualLength;
290
291 /* add padding */
292 if (ladjust) {
293 padc = ' ';
294 }
295 if (negFlag && !ladjust && (padc == '0')) {
296 for (i = actualLength-1; i< length-1; i++) buf[i] = padc;
297 buf[length -1] = '-';
298 } else {
299 for (i = actualLength; i< length; i++) buf[i] = padc;
300 }
301
302
303 /* prepare to reverse the string */
304 {
305 int begin = 0;
306 int end;
307 if (ladjust) {
308 end = actualLength - 1;
309 } else {
310 end = length -1;
311 }
312
313 while (end > begin) {
314 char tmp = buf[begin];
315 buf[begin] = buf[end];
316 buf[end] = tmp;
317 begin ++;
318 end --;
319 }
320 }
321
322 /* adjust the string pointer */
323 return length;
324 }