����8-10 linux/kernel/vsprintf.c
1 /*
2 * linux/kernel/vsprintf.c
3 *
4 * (C) 1991 Linus Torvalds
5 */
6
7 /* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */
8 /*
9 * Wirzenius wrote this portably, Torvalds fucked it up :-)
10 */
// Lars Wirzenius��Linus�ĺ��ѣ���Helsinki��ѧʱ��ͬ��һ��칫�ҡ���1991���ļ�����Linux
// ʱ��Linus��ʱ��C���Ի����Ǻ���Ϥ��������ʹ�ÿɱ�����б��������ܡ����Lars Wirzenius
// ��Ϊ����д����������ں���ʾ��Ϣ�Ĵ��롣������(1998��)��������δ�������һ��bug��ֱ��
// 1994������˷��֣������Ծ��������bug����ʹ��*��Ϊ��������ʱ�����ǵ���ָ�����������
// ���ˡ��ڱ����������bug����Ȼ���ڣ�130�У��� ���ĸ�����ҳ��http://liw.iki.fi/liw/
11
12 #include <stdarg.h> // ������ͷ�ļ����Ժ����ʽ������������б�����Ҫ˵����-��
// ����(va_list)��������(va_start, va_arg��va_end)������
// vsprintf��vprintf��vfprintf������
13 #include <string.h> // �ַ���ͷ�ļ�����Ҫ������һЩ�й��ַ���������Ƕ�뺯����
14
15 /* we use this so that we can do without the ctype library */
/* ����ʹ������Ķ��壬�������ǾͿ��Բ�ʹ��ctype���� */
16 #define is_digit(c) ((c) >= '0' && (c) <= '9') // �ж��ַ�c�Ƿ�Ϊ�����ַ���
17
// �ú������ַ����ִ�ת�������������������ִ�ָ���ָ�룬�����ǽ����ֵ������ָ�뽫ǰ�ơ�
18 static int skip_atoi(const char **s)
19 {
20 int i=0;
21
22 while (is_digit(**s))
23 i = i*10 + *((*s)++) - '0';
24 return i;
25 }
26
// ���ﶨ��ת�����͵ĸ��ַ��ų�����
27 #define ZEROPAD 1 /* pad with zero */ /* ����� */
28 #define SIGN 2 /* unsigned/signed long */ /* ����/���ų����� */
29 #define PLUS 4 /* show plus */ /* ��ʾ�� */
30 #define SPACE 8 /* space if plus */ /* ���Ǽӣ����ÿո� */
31 #define LEFT 16 /* left justified */ /* ����� */
32 #define SPECIAL 32 /* 0x */ /* 0x */
33 #define SMALL 64 /* use 'abcdef' instead of 'ABCDEF' */ /* ʹ��Сд��ĸ */
34
// �����������룺nΪ��������baseΪ�����������nΪ�̣���������ֵΪ������
// �μ�4.5.3���й�Ƕ�������Ϣ��
35 #define do_div(n,base) ({ \
36 int __res; \
37 __asm__("divl %4":"=a" (n),"=d" (__res):"0" (n),"1" (0),"r" (base)); \
38 __res; })
39
// ������ת��Ϊָ�����Ƶ��ַ�����
// ���룺num-������base-���ƣ�size-�ַ������ȣ�precision-���ֳ���(����)��type-����ѡ�
// ���������ת�����ַ�����ָ����ַ���ĩ�˺����ָ�롣
40 static char * number(char * str, int num, int base, int size, int precision
41 ,int type)
42 {
43 char c,sign,tmp[36];
44 const char *digits="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
45 int i;
46
// �������typeָ����Сд��ĸ������Сд��ĸ����
// �������ָ��Ҫ�����������߽磩�������������е������־��
// ������ƻ���С��2�����36�����˳�������Ҳ��������ֻ�ܴ���������2-32֮�������
47 if (type&SMALL) digits="0123456789abcdefghijklmnopqrstuvwxyz";
48 if (type&LEFT) type &= ~ZEROPAD;
49 if (base<2 || base>36)
50 return 0;
// �������ָ��Ҫ���㣬�����ַ�����c='0'������c���ڿո��ַ���
// �������ָ���Ǵ�������������ֵnumС��0�����÷��ű���sign=���ţ���ʹnumȡ����ֵ��
// �����������ָ���ǼӺţ�����sign=�Ӻţ����������ʹ��ո��־��sign=�ո�����0��
51 c = (type & ZEROPAD) ? '0' : ' ' ;
52 if (type&SIGN && num<0) {
53 sign='-';
54 num = -num;
55 } else
56 sign=(type&PLUS) ? '+' : ((type&SPACE) ? ' ' : 0);
// �������ţ������ֵ��1��������ָ��������ת���������ʮ�����ƿ����ټ���2λ(����0x)��
// ���ڰ˽��ƿ��ȼ�1�����ڰ˽���ת�����ǰ��һ���㣩��
57 if (sign) size--;
58 if (type&SPECIAL)
59 if (base==16) size -= 2;
60 else if (base==8) size--;
// �����ֵnumΪ0������ʱ�ַ���='0'��������ݸ����Ļ�������ֵnumת�����ַ���ʽ��
61 i=0;
62 if (num==0)
63 tmp[i++]='0';
64 else while (num!=0)
65 tmp[i++]=digits[do_div(num,base)];
// ����ֵ�ַ��������ھ���ֵ����ֵ��չΪ���ָ���ֵ��
// ����ֵsize��ȥ���ڴ����ֵ�ַ��ĸ�����
66 if (i>precision) precision=i;
67 size -= precision;
// ������������ʼ�γ�����Ҫ��ת�����������ʱ�����ַ���str�С�
// ��������û������(ZEROPAD)�����루���������־������str������
// ���ʣ�����ֵָ���Ŀո��������������λ���������š�
68 if (!(type&(ZEROPAD+LEFT)))
69 while(size-->0)
70 *str++ = ' ';
71 if (sign)
72 *str++ = sign;
// ������ָ��������ת��������ڰ˽���ת�����ͷһλ����һ��'0'��������ʮ����������'0x'��
73 if (type&SPECIAL)
74 if (base==8)
75 *str++ = '0';
76 else if (base==16) {
77 *str++ = '0';
78 *str++ = digits[33]; // 'X'��'x'
79 }
// ��������û������������룩��־������ʣ������д��c�ַ���'0'��ո���51�С�
80 if (!(type&LEFT))
81 while(size-->0)
82 *str++ = c;
// ��ʱi������ֵnum�����ָ����������ָ���С�ھ���ֵ����str�з��루����ֵ-i����'0'��
83 while(i<precision--)
84 *str++ = '0';
// ����ֵת���õ������ַ�����str�С���i����
85 while(i-->0)
86 *str++ = tmp[i];
// ������ֵ�Դ����㣬���ʾ���ͱ�־���������־������ʣ������з���ո�
87 while(size-->0)
88 *str++ = ' ';
89 return str; // ����ת���õ�ָ���ַ���ĩ�˺��ָ�롣
90 }
91
// ���溯������ʽ��������ַ����С�
// Ϊ�������ں���ʹ�ø�ʽ���������Linus���ں�ʵ���˸�C��������
// ���в���fmt�Ǹ�ʽ�ַ�����args�Ǹ����仯��ֵ��buf������ַ�����������
// ��μ��������б�����йظ�ʽת���ַ��Ľ��ܡ�
92 int vsprintf(char *buf, const char *fmt, va_list args)
93 {
94 int len;
95 int i;
96 char * str; // ���ڴ��ת�������е��ַ�����
97 char *s;
98 int *ip;
99
100 int flags; /* flags to number() */
101 /* number()����ʹ�õı�־ */
102 int field_width; /* width of output field */
/* ����ֶο���*/
103 int precision; /* min. # of digits for integers; max
104 number of chars for from string */
/* min. �������ָ�����max. �ַ������ַ����� */
105 int qualifier; /* 'h', 'l', or 'L' for integer fields */
106 /* 'h', 'l',��'L'���������ֶ� */
// ���Ƚ��ַ�ָ��ָ��buf��Ȼ��ɨ���ʽ�ַ������Ը�����ʽת��ָʾ������Ӧ�Ĵ�����
107 for (str=buf ; *fmt ; ++fmt) {
// ��ʽת��ָʾ�ַ�������'%'��ʼ�������fmt��ʽ�ַ�����ɨ��'%'��Ѱ�Ҹ�ʽת���ַ����Ŀ�ʼ��
// ���Ǹ�ʽָʾ��һ���ַ��������δ���str��
108 if (*fmt != '%') {
109 *str++ = *fmt;
110 continue;
111 }
112
// ����ȡ�ø�ʽָʾ�ַ����еı�־������־��������flags�����С�
113 /* process flags */
114 flags = 0;
115 repeat:
116 ++fmt; /* this also skips first '%' */
117 switch (*fmt) {
118 case '-': flags |= LEFT; goto repeat; // ���������
119 case '+': flags |= PLUS; goto repeat; // �żӺš�
120 case ' ': flags |= SPACE; goto repeat; // �ſո�
121 case '#': flags |= SPECIAL; goto repeat; // ������ת����
122 case '': flags |= ZEROPAD; goto repeat; // Ҫ����(��'0')��
123 }
124
// ȡ��ǰ�����ֶο�����ֵ������field_width�����С����������������ֵ��ֱ��ȡ��Ϊ����ֵ��
// ��������������ַ�'*'����ʾ��һ������ָ�����ȡ���˵���va_argȡ����ֵ������ʱ����ֵ
// С��0����ø�����ʾ����б�־��'-'��־�����룩����˻����ڱ�־����������ñ�־����
// ���ֶο���ֵȡΪ�����ֵ��
125 /* get field width */
126 field_width = -1;
127 if (is_digit(*fmt))
128 field_width = skip_atoi(&fmt);
129 else if (*fmt == '*') {
130 /* it's the next argument */ // �����и�bug��Ӧ����++fmt;
131 field_width = va_arg(args, int);
132 if (field_width < 0) {
133 field_width = -field_width;
134 flags |= LEFT;
135 }
136 }
137
// ������δ��룬ȡ��ʽת�����ľ���������precision�����С�������ʼ�ı�־��'.'��
// �䴦���������������������ơ����������������ֵ��ֱ��ȡ��Ϊ����ֵ���������������
// �ַ�'*'����ʾ��һ������ָ�����ȡ���˵���va_argȡ����ֵ������ʱ����ֵС��0����
// �ֶξ���ֵȡΪ0��
138 /* get the precision */
139 precision = -1;
140 if (*fmt == '.') {
141 ++fmt;
142 if (is_digit(*fmt))
143 precision = skip_atoi(&fmt);
144 else if (*fmt == '*') {
145 /* it's the next argument */ // ͬ������ҲӦ����++fmt;
146 precision = va_arg(args, int);
147 }
148 if (precision < 0)
149 precision = 0;
150 }
151
// ������δ�������������η������������qualifer��������h,l,L�ĺ���μ��б����˵������
152 /* get the conversion qualifier */
153 qualifier = -1;
154 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
155 qualifier = *fmt;
156 ++fmt;
157 }
158
// �������ת��ָʾ����
159 switch (*fmt) {
// ���ת��ָʾ����'c'�����ʾ��Ӧ����Ӧ���ַ�����ʱ�����־������������룬����ֶ�ǰ��
// ����'������ֵ-1'���ո��ַ���Ȼ���ٷ�������ַ��������������0�����ʾΪ���룬����
// �����ַ���������'����ֵ-1'���ո��ַ���
160 case 'c':
161 if (!(flags & LEFT))
162 while (--field_width > 0)
163 *str++ = ' ';
164 *str++ = (unsigned char) va_arg(args, int);
165 while (--field_width > 0)
166 *str++ = ' ';
167 break;
168
// ���ת��ָʾ����'s'�����ʾ��Ӧ�������ַ���������ȡ�����ַ����ij��ȣ����䳬���˾�����ֵ��
// ����չ������=�ַ������ȡ���ʱ�����־������������룬����ֶ�ǰ����'����ֵ-�ַ�������'
// ���ո��ַ���Ȼ���ٷ�������ַ����������������0�����ʾΪ���룬���ڲ����ַ�������
// ����'����ֵ-�ַ�������'���ո��ַ���
169 case 's':
170 s = va_arg(args, char *);
171 len = strlen(s);
172 if (precision < 0)
173 precision = len;
174 else if (len > precision)
175 len = precision;
176
177 if (!(flags & LEFT))
178 while (len < field_width--)
179 *str++ = ' ';
180 for (i = 0; i < len; ++i)
181 *str++ = *s++;
182 while (len < field_width--)
183 *str++ = ' ';
184 break;
185
// �����ʽת������'o'����ʾ�轫��Ӧ�IJ���ת���ɰ˽��������ַ���������number()����������
186 case 'o':
187 str = number(str, va_arg(args, unsigned long), 8,
188 field_width, precision, flags);
189 break;
190
// �����ʽת������'p'����ʾ��Ӧ������һ��ָ�����͡���ʱ���ò���û�����ÿ�������Ĭ�Ͽ���
// Ϊ8��������Ҫ���㡣Ȼ�����number()�������д�����
191 case 'p':
192 if (field_width == -1) {
193 field_width = 8;
194 flags |= ZEROPAD;
195 }
196 str = number(str,
197 (unsigned long) va_arg(args, void *), 16,
198 field_width, precision, flags);
199 break;
200
// ����ʽת��ָʾ��'x'��'X'�����ʾ��Ӧ������Ҫ��ӡ��ʮ�������������'x'��ʾ��Сд��ĸ��ʾ��
201 case 'x':
202 flags |= SMALL;
203 case 'X':
204 str = number(str, va_arg(args, unsigned long), 16,
205 field_width, precision, flags);
206 break;
207
// �����ʽת���ַ���'d','i'��'u'�����ʾ��Ӧ������������'d', 'i'�������������������Ҫ����
// �����ű�־��'u'��������������
208 case 'd':
209 case 'i':
210 flags |= SIGN;
211 case 'u':
212 str = number(str, va_arg(args, unsigned long), 10,
213 field_width, precision, flags);
214 break;
215
// ����ʽת��ָʾ����'n'�����ʾҪ�ѵ�ĿǰΪֹת������ַ������浽��Ӧ����ָ��ָ����λ���С�
// ��������va_arg()ȡ�øò���ָ�룬Ȼ���Ѿ�ת���õ��ַ��������ָ����ָ��λ�á�
216 case 'n':
217 ip = va_arg(args, int *);
218 *ip = (str - buf);
219 break;
220
// ����ʽת��������'%'�����ʾ��ʽ�ַ����д���ֱ�ӽ�һ��'%'д��������С�
// �����ʽת������λ�ô������ַ�����Ҳֱ�ӽ����ַ�д��������У������ص�107�м�������
// ��ʽ�ַ����������ʾ�Ѿ���������ʽ�ַ����Ľ�β�������˳�ѭ����
221 default:
222 if (*fmt != '%')
223 *str++ = '%';
224 if (*fmt)
225 *str++ = *fmt;
226 else
227 --fmt;
228 break;
229 }
230 }
231 *str = '\0'; // �����ת���õ��ַ�����β������null��
232 return str-buf; // ����ת���õ��ַ�������ֵ��
233 }
234