Root/target/linux/generic-2.6/image/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 */
19extern int PrintChar(char *, char, int, int);
20extern int PrintString(char *, char *, int, int);
21extern int PrintNum(char *, unsigned long, int, int, int, int, char, int);
22
23/* private variable */
24static const char theFatalMsg[] = "fatal error in lp_Print!";
25
26/* -*-
27 * A low level printf() function.
28 */
29void
30lp_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 --------------------- */
218int
219PrintChar(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
234int
235PrintString(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
253int
254PrintNum(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}
325

Archive Download this file



interactive