next_token函数
init/tokenizer.cpp中next_token函数
6 int next_token(struct parse_state *state)
7 {
8 char *x = state->ptr;
9 char *s;
10
11 if (state->nexttoken) {
12 int t = state->nexttoken;
13 state->nexttoken = 0;
14 return t;
15 }
16
17 for (;;) {
18 switch (*x) {
19 case 0:
20 state->ptr = x;
21 return T_EOF;
22 case '\n':
23 x++;
24 state->ptr = x;
25 return T_NEWLINE;
26 case ' ':
27 case '\t':
28 case '\r':
29 x++;
30 continue;
31 case '#':
32 while (*x && (*x != '\n')) x++;
33 if (*x == '\n') {
34 state->ptr = x+1;
35 return T_NEWLINE;
36 } else {
37 state->ptr = x;
38 return T_EOF;
39 }
40 default:
41 goto text;
42 }
43 }
44
45 textdone:
46 state->ptr = x;
47 *s = 0;
48 return T_TEXT;
49 text:
50 state->text = s = x;
51 textresume:
52 for (;;) {
53 switch (*x) {
54 case 0:
55 goto textdone;
56 case ' ':
57 case '\t':
58 case '\r':
59 x++;
60 goto textdone;
61 case '\n':
62 state->nexttoken = T_NEWLINE;
63 x++;
64 goto textdone;
65 case '"':
66 x++;
67 for (;;) {
68 switch (*x) {
69 case 0:
70 /* unterminated quoted thing */
71 state->ptr = x;
72 return T_EOF;
73 case '"':
74 x++;
75 goto textresume;
76 default:
77 *s++ = *x++;
78 }
79 }
80 break;
81 case '\\':
82 x++;
83 switch (*x) {
84 case 0:
85 goto textdone;
86 case 'n':
87 *s++ = '\n';
88 break;
89 case 'r':
90 *s++ = '\r';
91 break;
92 case 't':
93 *s++ = '\t';
94 break;
95 case '\\':
96 *s++ = '\\';
97 break;
98 case '\r':
99 /* \ <cr> <lf> -> line continuation */
100 if (x[1] != '\n') {
101 x++;
102 continue;
103 }
104 case '\n':
105 /* \ <lf> -> line continuation */
106 state->line++;
107 x++;
108 /* eat any extra whitespace */
109 while((*x == ' ') || (*x == '\t')) x++;
110 continue;
111 default:
112 /* unknown escape -- just copy */
113 *s++ = *x++;
114 }
115 continue;
116 default:
117 *s++ = *x++;
118 }
119 }
120 return T_EOF;
121 }
next_token函数整体逻辑:把文件中所有内容保存到字符串str。
在17行到43行处理逻辑,在字符串找到有用字符,则会进入text中,分割字符串,保存内容;如果遇到字符串中非有用字符是"#",继续在字符串str中轮询,直接遇到换行符(’\n’),或者轮询到结束符(EOF),分别在35行返回T_NEWLINE,或者在38行中返回return T_EOF;如果遇到空行"\n",则返回T_NEWLINE;如到’ ‘,’\t’,'r’等特殊字符继续向前轮询字符。
有个数据结构struct parse_state。
struct parse_state
{
char *ptr; ------>指向下一个字符串的开始字符
char *text; ------>保存
int line; --->处理的行数
int nexttoken; ---->处理过的分割符
};
举个例子:处理如下配置文件。
配置文件内容如下,使用vim set list查看,$是转行符,^I是table,其他就是看见的空格。
# Copyright (C) 2012 The Android Open Source Project$
#$
# IMPORTANT: Do not create world writable files or directories.$
# This is a common source of Android security bugs.$
#$
$
import /init.environ.rc$
import /init.usb.rc$
$
on early-init$
# Set init and its forked children's oom_adj.$
write /proc/1/oom_score_adj -1000$
在第1个注释语句,从31行处理,直接轮询到行末换行符(’\n’),并且从35行出。
第6行是空行,则22行进,遇到换行符(’\n’),从25行出。
有用信息:
on early-init$
处理这行,第一个字符是’o’,运行到40行,goto text,state->text = s=x,
执行到 s++ = x++;则x=‘n’,再执行s++ = *x++,x=’ ';执行到58行,
x++后x=‘e’,然后goto textdone后,state->ptr=x,*s=0,则state->text=“on”,再返回T_TEXT。
附表
|转义字符| 意义 |ASCII码值(十进制)|
|–|--|
| \n |换行(LF),将当前位置移到下一行开头 |010|
| \r |回车(CR) ,将当前位置移到本行开头 |013|
| \t |水平制表(HT) ( 跳到下一个TAB位置)|009|
\r是回车(CR),将光标移动到行前.
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char* argv[])
{
printf("ab c\n"); // 输出:ab c
printf("\td\n"); // 输出: d
printf("abc\rf\n"); // 输出:fbc
char str1[20]="abc\rf";
printf("%x %x %x %x %x",str1[0],str1[1],str1[2],str1[3],str1[4]);//0x61 0x62 0x63 0xd 0x66
return 0;
}