- 浏览: 237769 次
- 性别:
- 来自: 南京
-
最新评论
-
baby8117628:
vc下mp3 IDv1和IDV2的读取 -
gezexu:
你好,我按照你的步骤一步步进行但是安装libvorbis的时候 ...
linux如何搭建强大的FFMPEG环境 -
ini_always:
帅哥,转载也把格式做好点,另外出处也要注明一下吧。。。
MP3文件格式解析
梗概
这一节新增的文件有:
stdarg.h 用来处理可变参数
ctype.h 判断变量一些属性。比如一个字符是不是大写,是不是数字
string.h string.c 常用的关于字符串的操作
vsprintf.h vsprintf.c 该节的主要文件用来实现格式化输出
改变的文件有:
test.c 主要用来测试 printk函数
正文
大家上程序设计课程写的第一个程序应该是hello world吧,它仅仅是用printf函数打印一条问候语句,是的,非常简单。但是想在内核中用printf可就没那么容易了,因为内核程序根本就不能使用C库函数,但是printf函数却又非常重要。怎么办?大家应该还记得上一节写的vga驱动,用它直接打印不就得了。醒醒吧,printf可没那么简单,它不仅要能打印字符串,还要控制格式,就像这样: printf("Tinux is %d years old.", 2)。cons_write函数可不会把%d替换成数字2。看来还是要自己动手,才能丰衣足食了。
本节目标就是实现printf函数,不过我给它取了另一个名字叫printk,以表明它是用在内核当中的printf函数。另外还会有些附带的函数产品,像strcpy,memcpy等字符串操作函数,sprintf,vsprintf等底层打印函数。printk函数就是靠vsprintf实现的。
可变参数的头文件 stdarg.h
请拿出你的C语言参考书,看一下printf函数的声明: int printf(const char *format, ...);
是的,这就是传说中的变长参数。我在这里只提供变长参数的大概知识,详情请看变长参数的实现。变长参数涉及一个自定义的数据类型va_list,和三个宏定义va_start, va_arg, va_end。他们都定义在头文件stdarg.h中,我是直接通过gcc内置宏定义的,与链接给出的文章不同,因为那篇文章是为了讲解变长参数,真正实现时用gcc内置宏就可以了,相当于gcc内置宏为我们做好了定义,这样正确率更高,要知道调试OS Kernel可是相当烦。
stdarg.h
1 #ifndef __STDARG_H__
2 #define __STDARG_H__
3
4 #define va_list __builtin_va_list
5 #define va_start(ap, last) __builtin_va_start (ap, last)
6 #define va_arg(ap, type) __builtin_va_arg (ap, type)
7 #define va_end(ap) __builtin_va_end (ap)
8
9 #endif
10
C类型头文件 ctype.h
里面都是些常用宏,比如 islower(c)判断c是不是小写字母,isdigit(c)判断c是不是十进制数码,isxdigit(c)判断c是不是十六进制数码
isspace(c)判断c是不是空白字符
ctype.h
1 #ifndef __CTYPE_H__
2 #define __CTYPE_H__
3
4 #define islower(c) (((c) >= 'a') && ((c) <= 'z'))
5 #define isupper(c) (((c) >= 'A') && ((c) <= 'Z'))
6 #define isalpha(c) (islower (c) || isupper (c))
7 #define isdigit(c) (((c) >= '0') && ((c) <= '9'))
8 #define isalnum(c) (isalpha (c) || isdigit (c))
9 #define ispunct(c) \
10 ((((c) >= 0x21) && ((c) <= 0x2f)) || \
11 (((c) >= 0x3a) && ((c) <= 0x40)) || \
12 (((c) >= 0x5b) && ((c) <= 0x60)) || \
13 (((c) >= 0x7b) && ((c) <= 0x7e)))
14 #define isgraph(c) (((c) >= 0x21) && ((c) <= 0x7e))
15 #define isspace(c) ((((c) >= 0x09) && ((c) <= 0x0d)) || ((c) == ' '))
16 #define isprint(c) (((c) >= 0x20) && ((c) <= 0x7e))
17 #define iscntrl(c) (((c) <= 0x1f) || ((c) == 0x7f))
18 #define isxdigit(c) \
19 (isdigit (c) || (((c) >= 'a') && ((c) <= 'f')) || \
20 (((c) >= 'A') && ((c) <= 'F')))
21
22 #define tolower(c) (isupper (c) ? (c)+'a'-'A' : (c))
23 #define toupper(c) (islower (c) ? (c)+'A'-'a' : (c))
24
25 #endif
26
字符串处理 string.h string.c
关于 memcpy函数和mememove函数的区别请自行Google
string.h
1 #ifndef __STRING_H__
2 #define __STRING_H__
3
4 #include "types.h"
5
6 void *memcpy (void *dest, const void *src, size_t n);
7 void *memmove (void *dest, const void *src, size_t n);
8 char *strcpy (char *dest, const char *src);
9 char *strncpy (char *dest, const char *src, size_t n);
10 int strcmp (const char *s1, const char *s2);
11 int strncmp (const char *s1, const char *s2, size_t n);
12 int strlen (const char *s);
13
14 #endif
string.c
1 #include "types.h"
2 #include "string.h"
3
4 void *memcpy (void *dest, const void *src, size_t n) {
5 int i;
6 for (i = 0; i < (int)n; i++) *(char *)(dest + i) = *(char *)(src + i);
7 return dest;
8 }
9
10 void *memmove (void *dest, const void *src, size_t n) {
11 int i;
12 if (src > dest)
13 for (i = 0; i < (int)n; i++)
14 *(char *)(dest + i) = *(char *)(src + i);
15 if (src < dest)
16 for (i = (int)(n - 1); i >= 0; i--)
17 *(char *)(dest + i) = *(char *)(src + i);
18 return dest;
19 }
20
21 char *strcpy (char *dest, const char *src) {
22 int i = 0;
23 do { dest[i] = src[i]; } while (src[i++] != 0);
24 return dest;
25 }
26
27 char *strncpy (char *dest, const char *src, size_t n) {
28 int i = 0;
29 while ((i < (int)n) && (src[i] != 0)) { dest[i] = src[i]; i++; }
30 while (i < (int)n) dest[i++] = 0;
31 return dest;
32 }
33
34 int strcmp (const char *s1, const char *s2) {
35 int i = 0;
36 while ((s1[i] == s2[i]) && (s1[i] != 0)) i++;
37 return s1[i] - s2[i];
38 }
39
40 int strncmp (const char *s1, const char *s2, size_t n) {
41 int i = 0;
42 while ((i < (int)n) && (s1[i] == s2[i]) && (s1[i] != 0)) i++;
43 return (i == (int)n) ? 0 : s1[i] - s2[i];
44 }
45
46 int strlen (const char *s) {
47 int i = 0;
48 while (s[i] != 0) i++;
49 return i;
50 }
51
打印函数 vsprintf.h vsprintf.c
vsprintf.h
1 #ifndef __VSPRINTF_H__
2 #define __VSPRINTF_H__
3
4 #include "stdarg.h"
5
6 int sprintf(char *str, const char *format, ); // 将输出重定向到缓冲区 str
7 int vsprintf (char *str, const char *format, va_list ap); // 这是一个中转函数,真正完成格式化功能
8 int printk(const char *format, ); // 和 printf一样
9
10 #endif
vsprintf.c
1 #include "types.h"
2 #include "ctype.h"
3 #include "console.h"
4 #include "stdarg.h"
5 #include "string.h"
6 #include "vsprintf.h"
7
8 /* flags */
9 #define LEFT 0x01
10 #define PLUS 0x02
11 #define SPACE 0x04
12 #define SPECIAL 0x08
13 #define ZERO 0x10
14 #define SIGN 0x20 /* signed if set */
15 #define SMALL 0x40 /* 'abcdef' if set, 'ABCDEF' otherwise */
16
17 int32_t get_wide (const char **s);
18 void number_to_string (long num, int32_t base, int32_t flags, int32_t wide, int32_t precision, char **s);
19
20 int sprintf(char *str, const char *format,) {
21 va_list args;
22 int32_t res;
23 va_start (args, format);
24 res = vsprintf(str, format, args);
25 va_end (args);
26 return res;
27 }
28
29 int32_t vsprintf (char *str, const char *format, va_list ap) {
30 char c;
31 char *start = str;
32 int32_t flags;
33 int32_t wide;
34 int32_t precision;
35 int32_t qualifier;
36 char *s;
37 int32_t i, len, base;
38
39 while ((c = *format++) != 0) {
40 if (c != '%') { *str++ = c; continue; }
41 if (*format == '%') { *str++ = '%'; format++; continue; }
42
43 /* get flags */
44 flags = 0;
45 while (1) {
46 if (*format == '-') { flags |= LEFT; format++; continue; }
47 if (*format == '+') { flags |= PLUS; format++; continue; }
48 if (*format == ' ') { flags |= SPACE; format++; continue; }
49 if (*format == '#') { flags |= SPECIAL; format++; continue; }
50 if (*format == '0') { flags |= ZERO ; format++; continue; }
51 break;
52 }
53
54 /* get wide */
55 wide = -1;
56 if (isdigit (*format)) wide = get_wide ((const char **)(&format));
57 else if (*format == '*') { wide = va_arg (ap, int32_t); format++; }
58
59 /* get precision */
60 precision = -1;
61 if (*format == '.') {
62 format++;
63 if (isdigit (*format))
64 precision = get_wide ((const char **)(&format));
65 else if (*format == '*') {
66 precision = va_arg (ap, int32_t);
67 format++;
68 }
69 else precision = 0;
70 }
71
72 /* get qualifier */
73 qualifier = -1;
74 if ((*format == 'h') || (*format == 'l')) qualifier = *format++;
75
76 /* get format */
77 switch (*format++) {
78 case 'i':
79 case 'd':
80 flags |= SIGN;
81 if (precision != -1) flags &= ~ZERO;
82 switch (qualifier) {
83 case 'h':
84 number_to_string ((short) va_arg (ap, int32_t), 10, flags,
85 wide, precision, &str);
86 break;
87 case 'l':
88 number_to_string (va_arg (ap, long), 10, flags,
89 wide, precision, &str);
90 break;
91 default:
92 number_to_string (va_arg (ap, int32_t), 10, flags,
93 wide, precision, &str);
94 break;
95 }
96 break;
97
98 case 'u':
99 base = 10;
100 goto num_to_str_without_sign;
101
102 case 'o':
103 base = 8;
104 goto num_to_str_without_sign;
105
106 case 'x':
107 flags |= SMALL;
108 case 'X':
109 base = 16;
110
111 num_to_str_without_sign:
112 flags &= (~PLUS & ~SPACE);
113 if (precision != -1) flags &= ~ZERO;
114 switch (qualifier) {
115 case 'h':
116 number_to_string ((unsigned short) va_arg (ap, int32_t), \
117 base, flags, wide, precision, &str);
118 break;
119 case 'l':
120 number_to_string ((unsigned long) va_arg (ap, long), \
121 base, flags, wide, precision, &str);
122 break;
123 default:
124 number_to_string((uint32_t)va_arg (ap, int32_t), \
125 base, flags, wide, precision, &str);
126 break;
127 }
128 break;
129
130 case 's':
131 s = va_arg (ap, char *);
132 len = strlen (s);
133 if ((precision >= 0) && (len > precision)) len = precision;
134
135 /* rigth justified : pad with spaces */
136 if (!(flags & LEFT)) while (len < wide--) *str++ = ' ';
137 for (i = 0; i < len; i++) *str++ = *s++;
138 /* left justified : pad with spaces */
139 while (len < wide--) *str++ = ' ';
140 break;
141
142 case 'c':
143 /* rigth justified : pad with spaces */
144 if (!(flags & LEFT)) while (1 < wide--) *str++ = ' ';
145 *str++ = (unsigned char) va_arg (ap, int32_t);
146 /* left justified : pad with spaces */
147 while (1 < wide--) *str++ = ' ';
148 break;
149
150 default:
151 return -1;
152 }
153 }
154 *str = 0;
155
156 return (int32_t)(str-start);
157 }
158
159 int32_t printk(const char *format, )
160 {
161 char buff[1024];
162 char *str = buff;
163 va_list args;
164 int32_t res;
165 va_start (args, format);
166 res = vsprintf (str, format, args);
167 va_end (args);
168 cons_write(buff);
169 return res;
170 }
171
172 int32_t get_wide (const char **s) {
173 int32_t res = 0;
174 while (isdigit (**s)) res = 10*res + *((*s)++) - '0';
175 return res;
176 }
177
178 #define LONG_STRSIZE_BASE_2 32
179
180 void number_to_string (long num, int32_t base, int32_t flags, int32_t wide, int32_t precision, char **s) {
181 char sign; /* sign printed : '+', '-', ' ', or 0 (no sign) */
182 int32_t num_cpy = num;
183 unsigned long ul_num = (unsigned long) num; /* for unsigned format */
184
185 /* string representation of num (reversed) */
186 char tmp[LONG_STRSIZE_BASE_2];
187 int32_t i = 0; /* number of figures in tmp */
188
189 const char *digits = "0123456789ABCDEF";
190 if (flags & SMALL) digits = "0123456789abcdef";
191
192 if ((base < 2) || (base > 16)) return;
193
194 if ((flags & SIGN) && (num < 0)) { sign = '-'; num = -num; }
195 else sign = (flags & PLUS) ? '+' : ((flags & SPACE) ? ' ' : 0);
196 if (sign) wide--;
197
198 if (flags & SPECIAL) {
199 if ((base == 16) && (num != 0)) wide -= 2; /* '0x' or '0X' */
200 if (base ==
{ wide--; precision--; } /* '0' */
201 }
202
203 if (num == 0) tmp[i++] = '0';
204 /* signed format */
205 if (flags & SIGN) {
206 while (num != 0) {
207 tmp[i++] = digits[num % base];
208 num = num / base;
209 }
210 }
211 /* unsigned format */
212 else {
213 while (ul_num != 0) {
214 tmp[i++] = digits[ul_num % base];
215 ul_num = ul_num / base;
216 }
217 }
218
219 if (i > precision) precision = i;
220 wide -= precision;
221
222 /* wide = number of padding chars */
223 /* precision = number of figures after the sign and the special chars */
224
225 /* right justified and no zeropad : pad with spaces */
226 if (!(flags & (LEFT + ZERO))) while (wide-- > 0) *((*s)++) = ' ';
227
228 if (sign) *((*s)++) = sign;
229 if ((flags & SPECIAL) && (num_cpy != 0)) {
230 if (base ==
*((*s)++) = '0';
231 if (base == 16) {
232 *((*s)++) = '0';
233 if (flags & SMALL) *((*s)++) = 'x';
234 else *((*s)++) = 'X';
235 }
236 }
237
238 /* rigth justified and zeropad : pad with 0 */
239 if (!(flags & LEFT)) while (wide-- > 0) *((*s)++) = '0';
240
241 /* print num */
242 while (i < precision--) *((*s)++) = '0';
243 while (i-- > 0) *((*s)++) = tmp[i];
244
245 /* left justfied : pad with spaces */
246 while (wide-- > 0) *((*s)++) = ' ';
247 }
248
这一节的程序和上节的一样,起基础作用,并没有关系到进程,内存管理等OS核心理论。但是它们的正确与否至关重要,这也是OS研究的繁琐之处,想要一探它的奥秘还必须先做一些杂七杂八的玩意儿。
测试程序 test.c
让该程序做一些算术题目,并格式化输出结果
test.c
1 #include "console.h"
2 #include "vsprintf.h"
3
4 int test(void)
5 {
6 int a = 32;
7 int b = 68;
8 cons_clear();
9 printk("\n\n");
10 printk(" November 8, 2009\n");
11 printk("Hi,John\n\n");
12 printk("Now, I am capable of caculating math expressions,\n");
13 printk("and what's more, showing the results to our friends.\n");
14 printk("Look!\n\n");
15 printk(" %d + %d = %d \n",a, b, a+b);
16 printk(" 0x%x + 0x%x = 0x%x \n",a,b,a+b);
17 printk(" Your Tinux\n");
18 return 0;
19 }
运行结果如下:
PS: 此节的程序几乎全部来自CROCOS, 这是个开源OS项目, 它的新颖之处在于OS开发方式, 先像开发用户程序一样开发OS组件,最后再移到真实的硬件环境中。
若有兴趣,请访问 http://crocos.sourceforge.net/
这一节新增的文件有:
stdarg.h 用来处理可变参数
ctype.h 判断变量一些属性。比如一个字符是不是大写,是不是数字
string.h string.c 常用的关于字符串的操作
vsprintf.h vsprintf.c 该节的主要文件用来实现格式化输出
改变的文件有:
test.c 主要用来测试 printk函数
正文
大家上程序设计课程写的第一个程序应该是hello world吧,它仅仅是用printf函数打印一条问候语句,是的,非常简单。但是想在内核中用printf可就没那么容易了,因为内核程序根本就不能使用C库函数,但是printf函数却又非常重要。怎么办?大家应该还记得上一节写的vga驱动,用它直接打印不就得了。醒醒吧,printf可没那么简单,它不仅要能打印字符串,还要控制格式,就像这样: printf("Tinux is %d years old.", 2)。cons_write函数可不会把%d替换成数字2。看来还是要自己动手,才能丰衣足食了。
本节目标就是实现printf函数,不过我给它取了另一个名字叫printk,以表明它是用在内核当中的printf函数。另外还会有些附带的函数产品,像strcpy,memcpy等字符串操作函数,sprintf,vsprintf等底层打印函数。printk函数就是靠vsprintf实现的。
可变参数的头文件 stdarg.h
请拿出你的C语言参考书,看一下printf函数的声明: int printf(const char *format, ...);
是的,这就是传说中的变长参数。我在这里只提供变长参数的大概知识,详情请看变长参数的实现。变长参数涉及一个自定义的数据类型va_list,和三个宏定义va_start, va_arg, va_end。他们都定义在头文件stdarg.h中,我是直接通过gcc内置宏定义的,与链接给出的文章不同,因为那篇文章是为了讲解变长参数,真正实现时用gcc内置宏就可以了,相当于gcc内置宏为我们做好了定义,这样正确率更高,要知道调试OS Kernel可是相当烦。
stdarg.h
1 #ifndef __STDARG_H__
2 #define __STDARG_H__
3
4 #define va_list __builtin_va_list
5 #define va_start(ap, last) __builtin_va_start (ap, last)
6 #define va_arg(ap, type) __builtin_va_arg (ap, type)
7 #define va_end(ap) __builtin_va_end (ap)
8
9 #endif
10
C类型头文件 ctype.h
里面都是些常用宏,比如 islower(c)判断c是不是小写字母,isdigit(c)判断c是不是十进制数码,isxdigit(c)判断c是不是十六进制数码
isspace(c)判断c是不是空白字符
ctype.h
1 #ifndef __CTYPE_H__
2 #define __CTYPE_H__
3
4 #define islower(c) (((c) >= 'a') && ((c) <= 'z'))
5 #define isupper(c) (((c) >= 'A') && ((c) <= 'Z'))
6 #define isalpha(c) (islower (c) || isupper (c))
7 #define isdigit(c) (((c) >= '0') && ((c) <= '9'))
8 #define isalnum(c) (isalpha (c) || isdigit (c))
9 #define ispunct(c) \
10 ((((c) >= 0x21) && ((c) <= 0x2f)) || \
11 (((c) >= 0x3a) && ((c) <= 0x40)) || \
12 (((c) >= 0x5b) && ((c) <= 0x60)) || \
13 (((c) >= 0x7b) && ((c) <= 0x7e)))
14 #define isgraph(c) (((c) >= 0x21) && ((c) <= 0x7e))
15 #define isspace(c) ((((c) >= 0x09) && ((c) <= 0x0d)) || ((c) == ' '))
16 #define isprint(c) (((c) >= 0x20) && ((c) <= 0x7e))
17 #define iscntrl(c) (((c) <= 0x1f) || ((c) == 0x7f))
18 #define isxdigit(c) \
19 (isdigit (c) || (((c) >= 'a') && ((c) <= 'f')) || \
20 (((c) >= 'A') && ((c) <= 'F')))
21
22 #define tolower(c) (isupper (c) ? (c)+'a'-'A' : (c))
23 #define toupper(c) (islower (c) ? (c)+'A'-'a' : (c))
24
25 #endif
26
字符串处理 string.h string.c
关于 memcpy函数和mememove函数的区别请自行Google
string.h
1 #ifndef __STRING_H__
2 #define __STRING_H__
3
4 #include "types.h"
5
6 void *memcpy (void *dest, const void *src, size_t n);
7 void *memmove (void *dest, const void *src, size_t n);
8 char *strcpy (char *dest, const char *src);
9 char *strncpy (char *dest, const char *src, size_t n);
10 int strcmp (const char *s1, const char *s2);
11 int strncmp (const char *s1, const char *s2, size_t n);
12 int strlen (const char *s);
13
14 #endif
string.c
1 #include "types.h"
2 #include "string.h"
3
4 void *memcpy (void *dest, const void *src, size_t n) {
5 int i;
6 for (i = 0; i < (int)n; i++) *(char *)(dest + i) = *(char *)(src + i);
7 return dest;
8 }
9
10 void *memmove (void *dest, const void *src, size_t n) {
11 int i;
12 if (src > dest)
13 for (i = 0; i < (int)n; i++)
14 *(char *)(dest + i) = *(char *)(src + i);
15 if (src < dest)
16 for (i = (int)(n - 1); i >= 0; i--)
17 *(char *)(dest + i) = *(char *)(src + i);
18 return dest;
19 }
20
21 char *strcpy (char *dest, const char *src) {
22 int i = 0;
23 do { dest[i] = src[i]; } while (src[i++] != 0);
24 return dest;
25 }
26
27 char *strncpy (char *dest, const char *src, size_t n) {
28 int i = 0;
29 while ((i < (int)n) && (src[i] != 0)) { dest[i] = src[i]; i++; }
30 while (i < (int)n) dest[i++] = 0;
31 return dest;
32 }
33
34 int strcmp (const char *s1, const char *s2) {
35 int i = 0;
36 while ((s1[i] == s2[i]) && (s1[i] != 0)) i++;
37 return s1[i] - s2[i];
38 }
39
40 int strncmp (const char *s1, const char *s2, size_t n) {
41 int i = 0;
42 while ((i < (int)n) && (s1[i] == s2[i]) && (s1[i] != 0)) i++;
43 return (i == (int)n) ? 0 : s1[i] - s2[i];
44 }
45
46 int strlen (const char *s) {
47 int i = 0;
48 while (s[i] != 0) i++;
49 return i;
50 }
51
打印函数 vsprintf.h vsprintf.c
vsprintf.h
1 #ifndef __VSPRINTF_H__
2 #define __VSPRINTF_H__
3
4 #include "stdarg.h"
5
6 int sprintf(char *str, const char *format, ); // 将输出重定向到缓冲区 str
7 int vsprintf (char *str, const char *format, va_list ap); // 这是一个中转函数,真正完成格式化功能
8 int printk(const char *format, ); // 和 printf一样
9
10 #endif
vsprintf.c
1 #include "types.h"
2 #include "ctype.h"
3 #include "console.h"
4 #include "stdarg.h"
5 #include "string.h"
6 #include "vsprintf.h"
7
8 /* flags */
9 #define LEFT 0x01
10 #define PLUS 0x02
11 #define SPACE 0x04
12 #define SPECIAL 0x08
13 #define ZERO 0x10
14 #define SIGN 0x20 /* signed if set */
15 #define SMALL 0x40 /* 'abcdef' if set, 'ABCDEF' otherwise */
16
17 int32_t get_wide (const char **s);
18 void number_to_string (long num, int32_t base, int32_t flags, int32_t wide, int32_t precision, char **s);
19
20 int sprintf(char *str, const char *format,) {
21 va_list args;
22 int32_t res;
23 va_start (args, format);
24 res = vsprintf(str, format, args);
25 va_end (args);
26 return res;
27 }
28
29 int32_t vsprintf (char *str, const char *format, va_list ap) {
30 char c;
31 char *start = str;
32 int32_t flags;
33 int32_t wide;
34 int32_t precision;
35 int32_t qualifier;
36 char *s;
37 int32_t i, len, base;
38
39 while ((c = *format++) != 0) {
40 if (c != '%') { *str++ = c; continue; }
41 if (*format == '%') { *str++ = '%'; format++; continue; }
42
43 /* get flags */
44 flags = 0;
45 while (1) {
46 if (*format == '-') { flags |= LEFT; format++; continue; }
47 if (*format == '+') { flags |= PLUS; format++; continue; }
48 if (*format == ' ') { flags |= SPACE; format++; continue; }
49 if (*format == '#') { flags |= SPECIAL; format++; continue; }
50 if (*format == '0') { flags |= ZERO ; format++; continue; }
51 break;
52 }
53
54 /* get wide */
55 wide = -1;
56 if (isdigit (*format)) wide = get_wide ((const char **)(&format));
57 else if (*format == '*') { wide = va_arg (ap, int32_t); format++; }
58
59 /* get precision */
60 precision = -1;
61 if (*format == '.') {
62 format++;
63 if (isdigit (*format))
64 precision = get_wide ((const char **)(&format));
65 else if (*format == '*') {
66 precision = va_arg (ap, int32_t);
67 format++;
68 }
69 else precision = 0;
70 }
71
72 /* get qualifier */
73 qualifier = -1;
74 if ((*format == 'h') || (*format == 'l')) qualifier = *format++;
75
76 /* get format */
77 switch (*format++) {
78 case 'i':
79 case 'd':
80 flags |= SIGN;
81 if (precision != -1) flags &= ~ZERO;
82 switch (qualifier) {
83 case 'h':
84 number_to_string ((short) va_arg (ap, int32_t), 10, flags,
85 wide, precision, &str);
86 break;
87 case 'l':
88 number_to_string (va_arg (ap, long), 10, flags,
89 wide, precision, &str);
90 break;
91 default:
92 number_to_string (va_arg (ap, int32_t), 10, flags,
93 wide, precision, &str);
94 break;
95 }
96 break;
97
98 case 'u':
99 base = 10;
100 goto num_to_str_without_sign;
101
102 case 'o':
103 base = 8;
104 goto num_to_str_without_sign;
105
106 case 'x':
107 flags |= SMALL;
108 case 'X':
109 base = 16;
110
111 num_to_str_without_sign:
112 flags &= (~PLUS & ~SPACE);
113 if (precision != -1) flags &= ~ZERO;
114 switch (qualifier) {
115 case 'h':
116 number_to_string ((unsigned short) va_arg (ap, int32_t), \
117 base, flags, wide, precision, &str);
118 break;
119 case 'l':
120 number_to_string ((unsigned long) va_arg (ap, long), \
121 base, flags, wide, precision, &str);
122 break;
123 default:
124 number_to_string((uint32_t)va_arg (ap, int32_t), \
125 base, flags, wide, precision, &str);
126 break;
127 }
128 break;
129
130 case 's':
131 s = va_arg (ap, char *);
132 len = strlen (s);
133 if ((precision >= 0) && (len > precision)) len = precision;
134
135 /* rigth justified : pad with spaces */
136 if (!(flags & LEFT)) while (len < wide--) *str++ = ' ';
137 for (i = 0; i < len; i++) *str++ = *s++;
138 /* left justified : pad with spaces */
139 while (len < wide--) *str++ = ' ';
140 break;
141
142 case 'c':
143 /* rigth justified : pad with spaces */
144 if (!(flags & LEFT)) while (1 < wide--) *str++ = ' ';
145 *str++ = (unsigned char) va_arg (ap, int32_t);
146 /* left justified : pad with spaces */
147 while (1 < wide--) *str++ = ' ';
148 break;
149
150 default:
151 return -1;
152 }
153 }
154 *str = 0;
155
156 return (int32_t)(str-start);
157 }
158
159 int32_t printk(const char *format, )
160 {
161 char buff[1024];
162 char *str = buff;
163 va_list args;
164 int32_t res;
165 va_start (args, format);
166 res = vsprintf (str, format, args);
167 va_end (args);
168 cons_write(buff);
169 return res;
170 }
171
172 int32_t get_wide (const char **s) {
173 int32_t res = 0;
174 while (isdigit (**s)) res = 10*res + *((*s)++) - '0';
175 return res;
176 }
177
178 #define LONG_STRSIZE_BASE_2 32
179
180 void number_to_string (long num, int32_t base, int32_t flags, int32_t wide, int32_t precision, char **s) {
181 char sign; /* sign printed : '+', '-', ' ', or 0 (no sign) */
182 int32_t num_cpy = num;
183 unsigned long ul_num = (unsigned long) num; /* for unsigned format */
184
185 /* string representation of num (reversed) */
186 char tmp[LONG_STRSIZE_BASE_2];
187 int32_t i = 0; /* number of figures in tmp */
188
189 const char *digits = "0123456789ABCDEF";
190 if (flags & SMALL) digits = "0123456789abcdef";
191
192 if ((base < 2) || (base > 16)) return;
193
194 if ((flags & SIGN) && (num < 0)) { sign = '-'; num = -num; }
195 else sign = (flags & PLUS) ? '+' : ((flags & SPACE) ? ' ' : 0);
196 if (sign) wide--;
197
198 if (flags & SPECIAL) {
199 if ((base == 16) && (num != 0)) wide -= 2; /* '0x' or '0X' */
200 if (base ==

201 }
202
203 if (num == 0) tmp[i++] = '0';
204 /* signed format */
205 if (flags & SIGN) {
206 while (num != 0) {
207 tmp[i++] = digits[num % base];
208 num = num / base;
209 }
210 }
211 /* unsigned format */
212 else {
213 while (ul_num != 0) {
214 tmp[i++] = digits[ul_num % base];
215 ul_num = ul_num / base;
216 }
217 }
218
219 if (i > precision) precision = i;
220 wide -= precision;
221
222 /* wide = number of padding chars */
223 /* precision = number of figures after the sign and the special chars */
224
225 /* right justified and no zeropad : pad with spaces */
226 if (!(flags & (LEFT + ZERO))) while (wide-- > 0) *((*s)++) = ' ';
227
228 if (sign) *((*s)++) = sign;
229 if ((flags & SPECIAL) && (num_cpy != 0)) {
230 if (base ==

231 if (base == 16) {
232 *((*s)++) = '0';
233 if (flags & SMALL) *((*s)++) = 'x';
234 else *((*s)++) = 'X';
235 }
236 }
237
238 /* rigth justified and zeropad : pad with 0 */
239 if (!(flags & LEFT)) while (wide-- > 0) *((*s)++) = '0';
240
241 /* print num */
242 while (i < precision--) *((*s)++) = '0';
243 while (i-- > 0) *((*s)++) = tmp[i];
244
245 /* left justfied : pad with spaces */
246 while (wide-- > 0) *((*s)++) = ' ';
247 }
248
这一节的程序和上节的一样,起基础作用,并没有关系到进程,内存管理等OS核心理论。但是它们的正确与否至关重要,这也是OS研究的繁琐之处,想要一探它的奥秘还必须先做一些杂七杂八的玩意儿。
测试程序 test.c
让该程序做一些算术题目,并格式化输出结果
test.c
1 #include "console.h"
2 #include "vsprintf.h"
3
4 int test(void)
5 {
6 int a = 32;
7 int b = 68;
8 cons_clear();
9 printk("\n\n");
10 printk(" November 8, 2009\n");
11 printk("Hi,John\n\n");
12 printk("Now, I am capable of caculating math expressions,\n");
13 printk("and what's more, showing the results to our friends.\n");
14 printk("Look!\n\n");
15 printk(" %d + %d = %d \n",a, b, a+b);
16 printk(" 0x%x + 0x%x = 0x%x \n",a,b,a+b);
17 printk(" Your Tinux\n");
18 return 0;
19 }
运行结果如下:
PS: 此节的程序几乎全部来自CROCOS, 这是个开源OS项目, 它的新颖之处在于OS开发方式, 先像开发用户程序一样开发OS组件,最后再移到真实的硬件环境中。
若有兴趣,请访问 http://crocos.sourceforge.net/
发表评论
-
内存屏障
2010-02-26 11:03 1523处理器的乱序和并发执行 目前的高级处理器,为了提高内部逻辑元 ... -
函数调用堆栈分析
2010-02-26 10:53 1392理解调用栈最重要的两 ... -
mtrace检测内存泄露
2010-02-25 09:50 1108[url] http://math.acadiau.ca/AC ... -
c语言编程之字符串操作
2010-02-25 09:41 8781. //在s串中查找与s1相匹配的字符串,找到后用 ... -
linux C 链接库 so制作及调用[转]
2010-02-24 16:26 2598文章分类:C++编程 [文章作者:陈毓端 若转载请标注原文链 ... -
mtrace的使用
2010-02-24 16:02 1346对于内存溢出之类的麻烦可能大家在编写指针比较多的复杂的程序的时 ... -
单片机的C语言中位操作用法(转
2010-02-24 14:27 2226单片机的C语言中位操作用法 作者:郭天祥 在对单处机进 ... -
Linux下的itoa函数
2010-02-21 17:55 1789上篇文章说到linux需要it ... -
va_list、va_start、va_arg、va_end的原理与使用
2010-02-05 10:34 29261. 概述 由于在C语言中没有函数重载,解 ... -
快速排序(quickSort)
2010-02-04 10:50 8821. #include <stdio.h> ... -
C问题---itoa函数
2010-02-04 10:36 1075------------------------------ ... -
itoa函数及atoi函数
2010-02-04 10:35 1340C语言提供了几个标准库函数,可以将任意类型(整型、长整型、浮点 ... -
结构体零长度数组的作用
2010-02-04 10:21 1388在一些 C 语言编写的代码中,有时可以看到如下定义的结构: ... -
优化C代码常用的几招
2010-02-04 10:14 789性能优化方面永远注意8 ... -
我经常去的网站
2010-02-03 17:53 1645MFC相关网站 www.codeproject.com ht ... -
可重入函数与不可重入函数
2010-02-03 16:35 948原文地址:http://blog.chin ... -
linux线程池及其测试
2010-02-03 16:32 2375/*----------------------------- ... -
哈夫曼编码
2010-02-03 16:26 1326本文描述在网上能够找到的最简单,最快速的哈夫曼编码。本方法不使 ... -
优化变成了忧患:String.split引发的“内存泄露”
2010-02-01 17:39 1126一直赞叹Sun对待技术的 ... -
锁无关的(Lock-Free)数据结构——在避免死锁的同时确保线程
2010-01-26 14:47 917http://hi.baidu.com/%5F%E2%64%5 ...
相关推荐
MATLAB课程设计(非库函数实现高斯模糊,边缘检测,傅里叶等操作-基础) MATLAB课程设计(非库函数实现高斯模糊,边缘检测,傅里叶等操作-基础) MATLAB课程设计(非库函数实现高斯模糊,边缘检测,傅里叶等操作-基础) ...
STM32 自定义HID 设备, 通过快传输接收上位机发来的...上位机使用Libusb库函数实现,接口简单。程序中添加了上位机接收数据的接口,USB 设备端的IN 接口也做好了,用户只要将需要发送给HOST的数据添加进去就可以了.zip
调用库函数实现截图功能.zip源码Labview个人项目资料程序资源下载调用库函数实现截图功能.zip源码Labview个人项目资料程序资源下载调用库函数实现截图功能.zip源码Labview个人项目资料程序资源下载调用库函数实现...
lv调用库函数实现屏幕截图.zip源码Labview个人项目资料程序资源下载lv调用库函数实现屏幕截图.zip源码Labview个人项目资料程序资源下载lv调用库函数实现屏幕截图.zip源码Labview个人项目资料程序资源下载lv调用...
本压缩包“LabVIEWlv调用库函数实现屏幕截图.rar”显然提供了使用LabVIEW进行屏幕截图的功能。在LabVIEW中,实现这一功能通常涉及以下几个关键知识点: 1. **调用库函数**:LabVIEW允许用户通过Library Binding节点...
# 基于C语言的Arm优化库函数实现 ## 项目简介 本项目是一个由Arm提供的优化库函数实现,涵盖了数学、网络和字符串处理等多个子项目。这些库函数经过优化,旨在为Arm架构提供高效的性能支持。项目采用双许可证模式...
资料比较全地整理了string.h中常见的字符串处理函数,对每个函数完整地实现并有简要的注释。如果你喜欢深入研究C编译器技术,本资料值得你拥有。
在这个“LabVIEW调用库函数实现截图功能”的示例中,我们主要讨论如何利用LabVIEW的库函数来实现屏幕截图的功能。 首先,要实现截图功能,我们需要理解LabVIEW中的“库函数”或“函数库”。这些库通常包含了预定义...
课程设计 基于MATLAB非库函数实现高斯模糊边缘检测傅里叶等操作源码+GUI界面+详细文档+全部资料(高分项目)课程设计 基于MATLAB非库函数实现高斯模糊边缘检测傅里叶等操作源码+GUI界面+详细文档+全部资料(高分项目...
在“LabView图形化编程语言之调用库函数实现截图功能”这个主题中,我们将深入探讨如何利用LabView的库函数来实现屏幕截图的功能。 在LabView中,开发者通过连接各种不同的图标,即数据流图或称为G语言,来构建程序...
用c语言库函数实现文件复制功能,UNIX程序设计课程的作业
课程设计 基于MATLAB非库函数实现高斯模糊,边缘检测,傅里叶等操作-基础)源码+GUI界面+项目资料齐全+说明文档.zip课程设计 基于MATLAB非库函数实现高斯模糊,边缘检测,傅里叶等操作-基础)源码+GUI界面+项目资料齐全+...
通过LabVIEW,我们可以创建用户界面,直观地设计数据采集和控制流程,同时利用Modbus库函数实现与PLC的数据交换。描述中提到的"能用试过的"表明这些案例已经经过实际验证,具有很高的实用性。 LabVIEW中的Modbus...
在深入探讨如何不调用C库函数实现`memmove`和`memcpy`的功能之前,我们首先需要理解这两个函数的基本概念及其在计算机编程中的作用。`memcpy`和`memmove`都是用于内存操作的重要函数,它们负责将源内存区域的数据...
调用 DSP 库函数实现 FFT 的运算 本实验报告的目的是了解 FFT 的原理和在 DSP 中的设计及编程方法。实验任务是利用 CCS 库函数 CFFT 对 sin(40*PI*t) 进行 64 点的 FFT 运算,并回显结果图形并进行分析。 一、实验...
实现us级别延时, 65535最大us延时 ; 3. PB5; 蜂鸣器控制功能模块, 非PWM; 4. USART1初始化, 中断未开启; 5. USART2初始化, 开启中断; 6. Key按键控制亮灯 Key_UP/Key_DOWN 灯1亮、 Key_LEFT/Key_RIGHT 灯...