Print? // \ System \ core \ init \ init_parser.c
Int lookup_keyword (const char * s)
{
Switch (* s ++ ){
Case 'C ':
If (! Strcmp (s, "opy") return K_copy;
If (! Strcmp (s, "apability") return K_capability;
If (! Strcmp (s, "hdir") return K_chdir;
If (! Strcmp (s, "hroot") return K_chroot;
If (! Strcmp (s, "lass") return K_class;
If (! Strcmp (s, "lass_start") return K_class_start;
If (! Strcmp (s, "lass_stop") return K_class_stop;
If (! Strcmp (s, "lass_reset") return K_class_reset;
//......
}
Return K_UNKNOWN;
}
// \ System \ core \ init \ init_parser.c
Int lookup_keyword (const char * s)
{
Switch (* s ++ ){
Case 'C ':
If (! Strcmp (s, "opy") return K_copy;
If (! Strcmp (s, "apability") return K_capability;
If (! Strcmp (s, "hdir") return K_chdir;
If (! Strcmp (s, "hroot") return K_chroot;
If (! Strcmp (s, "lass") return K_class;
If (! Strcmp (s, "lass_start") return K_class_start;
If (! Strcmp (s, "lass_stop") return K_class_stop;
If (! Strcmp (s, "lass_reset") return K_class_reset;
//......
}
Return K_UNKNOWN;
}
From this code segment, we can find that this function classifies the first character of the string based on the saved string, and then compares the character to return the corresponding K_xxx. then pass the keyword into kw_is for judgment. Google's judgment design here kw_is will use macro instead of using general functions for implementation. First, this judgment action is only for comparison, another point is to reduce the performance of the functioncall stack once to speed up execution.
[Cpp]
// System \ core \ init \ init_parser.c
# Define kw_is (kw, type) (keyword_info [kw]. flags & (type ))
// System \ core \ init \ init_parser.c
# Define kw_is (kw, type) (keyword_info [kw]. flags & (type ))
We can see that the flags and types carried by elements in the keyword_info array are used for & comparison.
[Cpp]
// System \ core \ init \ init_parser.c
# Define KEYWORD (symbol, flags, nargs, func )\
[K _ # symbol] ={# symbol, func, nargs + 1, flags ,},
Struct {
Const char * name;
Int (* func) (int nargs, char ** args );
Unsigned char nargs;
Unsigned char flags;
} Keyword_info [KEYWORD_COUNT] = {
[K_UNKNOWN] = {"unknown", 0, 0, 0 },
# Include "keywords. h"
};
// System \ core \ init \ keywords. h
//...
KEYWORD (capability, OPTION, 0, 0)
KEYWORD (chdir, COMMAND, 1, do_chdir)
KEYWORD (chroot, COMMAND, 1, do_chroot)
KEYWORD (class, OPTION, 0, 0)
KEYWORD (class_start, COMMAND, 1, do_class_start)
KEYWORD (class_stop, COMMAND, 1, do_class_stop)
KEYWORD (class_reset, COMMAND, 1, do_class_reset)
KEYWORD (console, OPTION, 0, 0)
//....
// System \ core \ init \ init_parser.c
# Define KEYWORD (symbol, flags, nargs, func )\
[K _ # symbol] ={# symbol, func, nargs + 1, flags ,},
Struct {
Const char * name;
Int (* func) (int nargs, char ** args );
Unsigned char nargs;
Unsigned char flags;
} Keyword_info [KEYWORD_COUNT] = {
[K_UNKNOWN] = {"unknown", 0, 0, 0 },
# Include "keywords. h"
};
// System \ core \ init \ keywords. h
//...
KEYWORD (capability, OPTION, 0, 0)
KEYWORD (chdir, COMMAND, 1, do_chdir)
KEYWORD (chroot, COMMAND, 1, do_chroot)
KEYWORD (class, OPTION, 0, 0)
KEYWORD (class_start, COMMAND, 1, do_class_start)
KEYWORD (class_stop, COMMAND, 1, do_class_stop)
KEYWORD (class_reset, COMMAND, 1, do_class_reset)
KEYWORD (console, OPTION, 0, 0)
//....
From the above we can know that keyword_info is a Mappingtable. The keyword K_xxx returned by each lookup_keyword function corresponds to a function do_xxx.
Therefore, the call lookup_keyword in the parse_config function can be further analyzed.
[Cpp]
// System \ core \ init \ init_parser.c
Int kw = lookup_keyword (args [0]);
If (kw_is (kw, SECTION )){
State. parse_line (& state, 0, 0 );
Parse_new_section (& state, kw, nargs, args );
} Else {
State. parse_line (& state, nargs, args );
}
// System \ core \ init \ init_parser.c
Int kw = lookup_keyword (args [0]);
If (kw_is (kw, SECTION )){
State. parse_line (& state, 0, 0 );
Parse_new_section (& state, kw, nargs, args );
} Else {
State. parse_line (& state, nargs, args );
}
We can see from the previous analysis on lookup_keyword and kw_is. Here we will learn from init. find the keyword in rc and use the kw_is judgment for different parser methods. it can be seen from the above program code that a new list is available only when SECTION flag exists in the keyword_infomapping table. in the current version of (android4.2. h. You can know all the keywords. Only the import, on, and service characters corresponding to the SECTIONflag are available. besides the import character, the on and service are used to create the previously mentioned actionlist and service list. next, we will analyze the parse_new_section function.
[Cpp]
// System \ core \ init \ init_parser.c
Void parse_new_section (struct parse_state * state, int kw,
Int nargs, char ** args)
{
Printf ("[% s] \ n", args [0],
Nargs> 1? Args [1]: "");
Switch (kw ){
Case K_service:
State-> context = parse_service (state, nargs, args );
If (state-> context ){
State-> parse_line = parse_line_service;
Return;
}
Break;
Case K_on:
State-> context = parse_action (state, nargs, args );
If (state-> context ){
State-> parse_line = parse_line_action;
Return;
}
Break;
Case K_import:
Parse_import (state, nargs, args );
Break;
}
State-> parse_line = parse_line_no_op;
}
// System \ core \ init \ init_parser.c
Void parse_new_section (struct parse_state * state, int kw,
Int nargs, char ** args)
{
Printf ("[% s] \ n", args [0],
Nargs> 1? Args [1]: "");
Switch (kw ){
Case K_service:
State-> context = parse_service (state, nargs, args );
If (state-> context ){
State-> parse_line = parse_line_service;
Return;
}
Break;
Case K_on:
State-> context = parse_action (state, nargs, args );
If (state-> context ){
State-> parse_line = parse_line_action;
Return;
}
Break;
Case K_import:
Parse_import (state, nargs, args );
Break;
}
State-> parse_line = parse_line_no_op;
}
In the execution process analysis, the execute_one_command function is only used to execute the command above the action list, so it is analyzed from the parse_action function.
[Cpp]
// System \ core \ init \ init_parser.c
Static void * parse_action (struct parse_state * state, int nargs, char ** args)
{
Struct action * act;
If (nargs <2 ){
Parse_error (state, "actions must have a trigger \ n ");
Return 0;
}
If (nargs> 2 ){
Parse_error (state, "actions may not have extra parameters \ n ");
Return 0;
}
Act = calloc (1, sizeof (* act ));
Act-> name = args [1];
List_init (& act-> commands );
List_add_tail (& action_list, & act-> alist );
/* XXX add to hash */
Return act;
}
// System \ core \ init \ init_parser.c
Static void * parse_action (struct parse_state * state, int nargs, char ** args)
{
Struct action * act;
If (nargs <2 ){
Parse_error (state, "actions must have a trigger \ n ");
Return 0;
}
If (nargs> 2 ){
Parse_error (state, "actions may not have extra parameters \ n ");
Return 0;
}
Act = calloc (1, sizeof (* act ));
Act-> name = args [1];
List_init (& act-> commands );
List_add_tail (& action_list, & act-> alist );
/* XXX add to hash */
Return act;
}
It can be seen from the code above that the action list is the sort list created by a string of act elements. Once the action list has a new act element, the parse_line_action function is executed.
[Cpp]
// System \ core \ init \ init_parser.c
Static void parse_line_action (struct parse_state * state, int nargs, char ** args)
{
Struct command * cmd;
Struct action * act = state-> context;
Int (* func) (int nargs, char ** args );
Int kw, n;
If (nargs = 0 ){
Return;
}
Kw = lookup_keyword (args [0]);
If (! Kw_is (kw, COMMAND )){
Parse_error (state, "invalid command '% s' \ n", args [0]);
Return;
}
N = kw_nargs (kw );
If (nargs <n ){
Parse_error (state, "% s requires % d % s \ n", args [0], n-1,
N> 2? "Arguments": "argument ");
Return;
}
Cmd = malloc (sizeof (* cmd) + sizeof (char *) * nargs );
Cmd-> func = kw_func (kw );
Cmd-> nargs = nargs;
Memcpy (cmd-> args, args, sizeof (char *) * nargs );
List_add_tail (& act-> commands, & cmd-> clist );
}
// System \ core \ init \ init_parser.c
Static void parse_line_action (struct parse_state * state, int nargs, char ** args)
{
Struct command * cmd;
Struct action * act = state-> context;
Int (* func) (int nargs, char ** args );
Int kw, n;
If (nargs = 0 ){
Return;
}
Kw = lookup_keyword (args [0]);
If (! Kw_is (kw, COMMAND )){
Parse_error (state, "invalid command '% s' \ n", args [0]);
Return;
}
N = kw_nargs (kw );
If (nargs <n ){
Parse_error (state, "% s requires % d % s \ n", args [0], n-1,
N> 2? "Arguments": "argument ");
Return;
}
Cmd = malloc (sizeof (* cmd) + sizeof (char *) * nargs );
Cmd-> func = kw_func (kw );
Cmd-> nargs = nargs;
Memcpy (cmd-> args, args, sizeof (char *) * nargs );
List_add_tail (& act-> commands, & cmd-> clist );
}