@weixin
2015-05-24T14:38:06.000000Z
字数 16633
阅读 1583
compile
I debugged the crowbar program, just have a rough idea how the crowbar works.
print("hoge\tpiyo\n\\n");
save it as a file, test.crb.
lldb --source test/br_aliases crowbar test/test.crb
br_aliases
command alias bfl breakpoint set -f %1 -l %2bfl main.c 21bfl create.c 121bfl create.c 152bfl create.c 207bfl execute.c 298bfl eval.c 746bfl eval.c 683bfl eval.c 656bfl eval.c 587
why in this print case, crb_create_funciton_call_expression got triggered.
go back to crowbar.y, you would see this :
primary_expression: IDENTIFIER LP argument_list RP{$$ = crb_create_function_call_expression($1, $3);}| IDENTIFIER LP RP{$$ = crb_create_function_call_expression($1, NULL);}
print("hello"); exactly match the pattern.
here is the call graph from doxygen 
here is the interpret process from doxygen

print("3 + 5.." + (3 + 5) + "\n"); #this is a comment
test2.crb
I used pvtrace and graphviz dynamically analyze the code, here is the pic :

create identifier
* thread #1: tid = 0x23a0a2, 0x000000010000960c crowbar`crb_create_identifier(str=0x0000000101002200) + 12 at string.c:58, queue = 'com.apple.main-thread', stop reason = breakpoint 4.1frame #0: 0x000000010000960c crowbar`crb_create_identifier(str=0x0000000101002200) + 12 at string.c:5855 {56 char *new_str;57-> 58 new_str = crb_malloc(strlen(str) + 1);5960 strcpy(new_str, str);61
the above code shows the str is print, why?
(lldb) p str(char *) $1 = 0x0000000101002200 "print"
see crowbar.l,
<INITIAL>[A-Za-z_][A-Za-z_0-9]* {yylval.identifier = crb_create_identifier(yytext);return IDENTIFIER;}
lexer woudl ignore the LP and RP, just go ahead and see ", then decide to open_string_literal
* thread #1: tid = 0x23a0a2, 0x00000001000094c4 crowbar`crb_open_string_literal + 4 at string.c:15, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1frame #0: 0x00000001000094c4 crowbar`crb_open_string_literal + 4 at string.c:1512 void13 crb_open_string_literal(void)14 {-> 15 st_string_literal_buffer_size = 0;16 }1718 void
then lexer see another ", decide to close string
* thread #1: tid = 0x23a0a2, 0x00000001000095ec crowbar`crb_close_string_literal + 76 at string.c:50, queue = 'com.apple.main-thread', stop reason = step overframe #0: 0x00000001000095ec crowbar`crb_close_string_literal + 76 at string.c:5047 memcpy(new_str, st_string_literal_buffer, st_string_literal_buffer_size);48 new_str[st_string_literal_buffer_size] = '\0';49-> 50 return new_str;51 }5253 char *(lldb) p new_str(char *) $4 = 0x0000000101000158 "3 + 5.."
the pattern is like this :
* thread #1: tid = 0x1e945a, 0x00000001000043b2 crowbar`yyparse + 2818 at crowbar.y:148, queue = 'com.apple.main-thread', stop reason = step overframe #0: 0x00000001000043b2 crowbar`yyparse + 2818 at crowbar.y:148145 : multiplicative_expression146 | additive_expression ADD multiplicative_expression147 {-> 148 $$ = crb_create_binary_expression(ADD_EXPRESSION, $1, $3);149 }150 | additive_expression SUB multiplicative_expression151 {
then it would start create a binary expression
ESSION, left=0x0000000100803360, right=0x0000000100803378) + 22 at create.c:152, queue = 'com.apple.main-thread', stop reason = breakpoint 3.1frame #0: 0x0000000100005a66 crowbar`crb_create_binary_expression(operator=ADD_EXPRESSION, left=0x0000000100803360, right=0x0000000100803378) + 22 at create.c:152149 crb_create_binary_expression(ExpressionType operator,150 Expression *left, Expression *right)151 {-> 152 if ((left->type == INT_EXPRESSION153 || left->type == DOUBLE_EXPRESSION)154 && (right->type == INT_EXPRESSION155 || right->type == DOUBLE_EXPRESSION)) {(lldb) bt* thread #1: tid = 0x1e945a, 0x0000000100005a66 crowbar`crb_create_binary_expression(operator=ADD_EXPRESSION, left=0x0000000100803360, right=0x0000000100803378) + 22 at create.c:152, queue = 'com.apple.main-thread', stop reason = breakpoint 3.1* frame #0: 0x0000000100005a66 crowbar`crb_create_binary_expression(operator=ADD_EXPRESSION, left=0x0000000100803360, right=0x0000000100803378) + 22 at create.c:152frame #1: 0x00000001000043b2 crowbar`yyparse + 2818 at crowbar.y:148frame #2: 0x000000010000550c crowbar`CRB_compile(interpreter=0x0000000100803240, fp=0x00007fff7d8cf070) + 44 at interface.c:47frame #3: 0x0000000100005358 crowbar`main(argc=2, argv=0x00007fff5fbff798) + 184 at main.c:22frame #4: 0x00007fff9b5655c9 libdyld.dylib`start + 1frame #5: 0x00007fff9b5655c9 libdyld.dylib`start + 1
it would first evalue (3+5), the tree looks like this :
(lldb) p left->type(ExpressionType) $1 = INT_EXPRESSION(lldb) p right->type(ExpressionType) $2 = INT_EXPRESSION
then it would
frame #0: 0x0000000100005a66 crowbar`crb_create_binary_expression(operator=ADD_EXPRESSION, left=0x0000000101000140, right=0x0000000101000160) + 22 at create.c:152149 crb_create_binary_expression(ExpressionType operator,150 Expression *left, Expression *right)151 {-> 152 if ((left->type == INT_EXPRESSION153 || left->type == DOUBLE_EXPRESSION)154 && (right->type == INT_EXPRESSION155 || right->type == DOUBLE_EXPRESSION)) {(lldb) p left->type(ExpressionType) $9 = STRING_EXPRESSION(lldb) p right->u.int_value(int) $10 = 8(lldb) p left->u.string_value(char *) $11 = 0x0000000101000158 "3 + 5.."
if (true) {print("true\n");}
dynamic code analysis 
crb_create_boolean_expression, firstly see 'true', then at crowbar.y it create boolean expression
197 | TRUE_T198 {-> 199 $$ = crb_create_boolean_expression(CRB_TRUE);200 }201 | FALSE_T
crb_create_identifier, then see 'print', create identifier at crowbar.l
55 <INITIAL>[A-Za-z_][A-Za-z_0-9]* {-> 56 yylval.identifier = crb_create_identifier(yytext);57 return IDENTIFIER;58 }
crb_open_string_literal, then see ", at crowbar.l
<INITIAL>\" {72 crb_open_string_literal();-> 73 BEGIN STRING_LITERAL_STATE;74 }
crb_close_string_literal, same as above
<STRING_LITERAL_STATE>\" {98 Expression *expression = crb_alloc_expression(STRING_EXPRESSION);-> 99 expression->u.string_value = crb_close_string_literal();100 yylval.expression = expression;101 BEGIN INITIAL;102 return STRING_LITERAL;
crb_create_argument_list, then see "true\n" as argument, at crowbar.y
argument_list74 : expression75 {-> 76 $$ = crb_create_argument_list($1);77 }78 | argument_list COMMA expression
crb_create_function_call_expression, after get argument_list, then see 'funciton call' at crowbar.y
177 primary_expression178 : IDENTIFIER LP argument_list RP179 {-> 180 $$ = crb_create_function_call_expression($1, $3);181 }182 | IDENTIFIER LP RP
crb_create_statement_list, then print("true\n"); as a statement, because the statement pattern is expression SEMICOLON
83 statement_list84 : statement85 {-> 86 $$ = crb_create_statement_list($1);87 }
crb_create_block
308 block309 : LC statement_list RC310 {-> 311 $$ = crb_create_block($2);312 }313 | LC RC
crb_create_if_statement
239 if_statement240 : IF LP expression RP block241 {-> 242 $$ = crb_create_if_statement($3, $5, NULL, NULL);243 }244 | IF LP expression RP block ELSE block
crb_chain_statement_list
frame #0: 0x00000001000040f5 crowbar`yyparse + 2117 at crowbar.y:5047 CRB_Interpreter *inter = crb_get_current_interpreter();4849 inter->statement_list-> 50 = crb_chain_statement_list(inter->statement_list, $1);
dynamic code analysis ![call graph 2]
if (false) {print("bad\n");} else {print("good\n");}
crb_create_boolean_expression
frame #0: 0x000000010000451b crowbar`yyparse + 3179 at crowbar.y:203200 }201 | FALSE_T202 {-> 203 $$ = crb_create_boolean_expression(CRB_FALSE);204 }205 | NULL_T206 {
crb_create_identifier, print
frame #0: 0x00000001000019db crowbar`yylex + 1435 at crowbar.l:5653 <INITIAL>"/" return DIV;54 <INITIAL>"%" return MOD;55 <INITIAL>[A-Za-z_][A-Za-z_0-9]* {-> 56 yylval.identifier = crb_create_identifier(yytext);57 return IDENTIFIER;58 }59 <INITIAL>([1-9][0-9]*)|"0" {
crb_close_string_literal
* thread #1: tid = 0x43fb0, 0x00000001000095ec crowbar`crb_close_string_literal + 76 at string.c:50, queue = 'com.apple.main-thread', stop reason = step overframe #0: 0x00000001000095ec crowbar`crb_close_string_literal + 76 at string.c:5047 memcpy(new_str, st_string_literal_buffer, st_string_literal_buffer_size);48 new_str[st_string_literal_buffer_size] = '\0';49-> 50 return new_str;51 }5253 char *(lldb) p new_str(char *) $5 = 0x0000000101000170 "bad\n"
frame #0: 0x0000000100001bb1 crowbar`yylex + 1905 at crowbar.l:9996 <COMMENT>. ;97 <STRING_LITERAL_STATE>\" {98 Expression *expression = crb_alloc_expression(STRING_EXPRESSION);-> 99 expression->u.string_value = crb_close_string_literal();100 yylval.expression = expression;101 BEGIN INITIAL;102 return STRING_LITERAL;
crb_create_argument_list
frame #0: 0x00000001000041a2 crowbar`yyparse + 2290 at crowbar.y:7673 argument_list74 : expression75 {-> 76 $$ = crb_create_argument_list($1);77 }78 | argument_list COMMA expression79 {
crb_create_function_call
frame #0: 0x00000001000044a0 crowbar`yyparse + 3056 at crowbar.y:180177 primary_expression178 : IDENTIFIER LP argument_list RP179 {-> 180 $$ = crb_create_function_call_expression($1, $3);181 }182 | IDENTIFIER LP RP183 {
*crb_create_statement_list
crb_create_block
frame #0: 0x0000000100004790 crowbar`yyparse + 3808 at crowbar.y:311308 block309 : LC statement_list RC310 {-> 311 $$ = crb_create_block($2);312 }313 | LC RC
crb_create_identifier, print again
crb_create_statement_list
(lldb) p statement->u.expression_s->u.function_call_expression(FunctionCallExpression) $27 = {identifier = 0x00000001010001e0 "print"argument = 0x0000000101000208}
crb_create_block
(lldb) p then_block->statement_list->statement->u.expression_s->type(ExpressionType) $35 = FUNCTION_CALL_EXPRESSION
crb_create_if_statement
(lldb) p then_block->statement_list->statement->u.expression_s->u.function_call_expression.argument->expression->u.string_value(char *) $46 = 0x0000000101000170 "bad\n"
crb_chain_statement_list
frame #0: 0x000000010000594e crowbar`crb_chain_statement_list(list=0x0000000000000000, statement=0x0000000101000270) + 30 at create.c:9592 StatementList *pos;9394 if (list == NULL)-> 95 return crb_create_statement_list(statement);9697 for (pos = list; pos->next; pos = pos->next)98 ;(lldb) p statement(Statement *) $47 = 0x0000000101000270(lldb) p statement->type(StatementType) $48 = IF_STATEMENT
test code :
i = 0;for (;;) {print(" i.." + i);if (i > 5) {break;}i = i + 1;}print("\n");
dynamic code analysis : 
create identifier
frame #0: 0x000000010000960c crowbar`crb_create_identifier(str=0x0000000101800000) + 12 at string.c:5855 {56 char *new_str;57-> 58 new_str = crb_malloc(strlen(str) + 1);5960 strcpy(new_str, str);61(lldb) p str(char *) $1 = 0x0000000101800000 "i"
create assign expression
frame #0: 0x0000000100005a15 crowbar`crb_create_assign_expression(variable=0x0000000101000138, operand=0x0000000101000140) + 21 at create.c:121118 {119 Expression *exp;120-> 121 exp = crb_alloc_expression(ASSIGN_EXPRESSION);122 exp->u.assign_expression.variable = variable;123 exp->u.assign_expression.operand = operand;124(lldb) p operand(Expression *) $3 = 0x0000000101000140(lldb) p operand->type(ExpressionType) $4 = INT_EXPRESSION(lldb) p operand->u.int_value(int) $5 = 0
crb_chain_statement_list
frame #0: 0x0000000100005940 crowbar`crb_chain_statement_list(list=0x0000000000000000, statement=0x0000000101000170) + 16 at create.c:9491 {92 StatementList *pos;93-> 94 if (list == NULL)95 return crb_create_statement_list(statement);9697 for (pos = list; pos->next; pos = pos->next)
(lldb) p statement->u.expression_s->type(ExpressionType) $10 = ASSIGN_EXPRESSION
crb_create_identifier
frame #0: 0x000000010000960c crowbar`crb_create_identifier(str=0x0000000101800016) + 12 at string.c:5855 {56 char *new_str;57-> 58 new_str = crb_malloc(strlen(str) + 1);5960 strcpy(new_str, str);61(lldb) p str(char *) $17 = 0x0000000101800016 "print"
crb_open_string_literal
crb_create_binary_expression, create binary expr for "i.." + i
frame #0: 0x0000000100005a66 crowbar`crb_create_binary_expression(operator=ADD_EXPRESSION, left=0x00000001010001b0, right=0x00000001010001d8) + 22 at create.c:152149 crb_create_binary_expression(ExpressionType operator,150 Expression *left, Expression *right)151 {-> 152 if ((left->type == INT_EXPRESSION153 || left->type == DOUBLE_EXPRESSION)154 && (right->type == INT_EXPRESSION155 || right->type == DOUBLE_EXPRESSION)) {(lldb) p left->type(ExpressionType) $19 = STRING_EXPRESSION(lldb) p left->u.string_value(char *) $20 = 0x00000001010001c8 " i.."(lldb) p right->u.string_value(char *) $21 = 0x00000001010001d0 "i"
crb_create_argument_list
frame #0: 0x0000000100005863 crowbar`crb_create_argument_list(expression=0x00000001010001f0) + 19 at create.c:5855 {56 ArgumentList *al;57-> 58 al = crb_malloc(sizeof(ArgumentList));59 al->expression = expression;60 al->next = NULL;61(lldb) p expression->type(ExpressionType) $23 = ADD_EXPRESSION
crb_create_function_call_expression
crb_create_statement_list
frame #0: 0x0000000100005903 crowbar`crb_create_statement_list(statement=0x0000000101000230) + 19 at create.c:8279 {80 StatementList *sl;81-> 82 sl = crb_malloc(sizeof(StatementList));83 sl->statement = statement;84 sl->next = NULL;85(lldb) p statement->type(StatementType) $26 = EXPRESSION_STATEMENT(lldb) p statement->u.expression_s->type(ExpressionType) $27 = FUNCTION_CALL_EXPRESSION(lldb) p statement->u.expression_s->u.string_value(char *) $28 = 0x00000001010001a8 "print"
crb_create_identifier, "i"
frame #0: 0x000000010000960c crowbar`crb_create_identifier(str=0x0000000101800031) + 12 at string.c:5855 {56 char *new_str;57-> 58 new_str = crb_malloc(strlen(str) + 1);5960 strcpy(new_str, str);61(lldb) p str(char *) $30 = 0x0000000101800031 "i"
crb_create_binary_expression
frame #0: 0x0000000100005a66 crowbar`crb_create_binary_expression(operator=GT_EXPRESSION, left=0x0000000101000270, right=0x0000000101000288) + 22 at create.c:152149 crb_create_binary_expression(ExpressionType operator,150 Expression *left, Expression *right)151 {-> 152 if ((left->type == INT_EXPRESSION153 || left->type == DOUBLE_EXPRESSION)154 && (right->type == INT_EXPRESSION155 || right->type == DOUBLE_EXPRESSION)) {(lldb) p left->type(ExpressionType) $32 = IDENTIFIER_EXPRESSION(lldb) p right->type(ExpressionType) $33 = INT_EXPRESSION(lldb) p left->u.string_value(char *) $34 = 0x0000000101000268 "i"(lldb) p left->u.int_value(int) $35 = 16777832(lldb) p right->u.int_value(int) $36 = 5
crb_create_break_statement
frame #0: 0x0000000100004763 crowbar`yyparse + 3763 at crowbar.y:299296 break_statement297 : BREAK SEMICOLON298 {-> 299 $$ = crb_create_break_statement();300 }301 ;302 continue_statement
crb_create_statement_list
frame #0: 0x00000001000041e3 crowbar`yyparse + 2355 at crowbar.y:8683 statement_list84 : statement85 {-> 86 $$ = crb_create_statement_list($1);87 }88 | statement_list statement
crb_create_block
frame #0: 0x0000000100006113 crowbar`crb_create_block(statement_list=0x00000001010002e0) + 19 at create.c:355352 {353 Block *block;354-> 355 block = crb_malloc(sizeof(Block));356 block->statement_list = statement_list;357358 return block;
crb_create_identifier
frame #0: 0x000000010000962e crowbar`crb_create_identifier(str=0x000000010180004c) + 46 at string.c:605758 new_str = crb_malloc(strlen(str) + 1);59-> 60 strcpy(new_str, str);6162 return new_str;63 }(lldb) p str(char *) $52 = 0x000000010180004c "i"
crb_create_if_statement
frame #0: 0x0000000100005f4d crowbar`crb_create_if_statement(condition=0x00000001010002a0, then_block=0x00000001010002f0, elsif_list=0x0000000000000000, else_block=0x0000000000000000) + 29 at create.c:289286 {287 Statement *st;288-> 289 st = alloc_statement(IF_STATEMENT);290 st->u.if_s.condition = condition;291 st->u.if_s.then_block = then_block;292 st->u.if_s.elsif_list = elsif_list;
frame #0: 0x00000001000045d2 crowbar`yyparse + 3362 at crowbar.y:242239 if_statement240 : IF LP expression RP block241 {-> 242 $$ = crb_create_if_statement($3, $5, NULL, NULL);243 }244 | IF LP expression RP block ELSE block
create_chain_statement_list,
frame #0: 0x0000000100005940 crowbar`crb_chain_statement_list(list=0x0000000101000258, statement=0x0000000101000300) + 16 at create.c:9491 {92 StatementList *pos;93-> 94 if (list == NULL)95 return crb_create_statement_list(statement);9697 for (pos = list; pos->next; pos = pos->next)(lldb) p statement->type
(lldb) p statement->u.expression_s->type(ExpressionType) $61 = GT_EXPRESSION
crb_chain_statement_list
frame #0: 0x0000000100005940 crowbar`crb_chain_statement_list(list=0x0000000101000258, statement=0x00000001010003a0) + 16 at create.c:9491 {92 StatementList *pos;93-> 94 if (list == NULL)95 return crb_create_statement_list(statement);9697 for (pos = list; pos->next; pos = pos->next)(lldb) p statement->type(StatementType) $79 = EXPRESSION_STATEMENT(lldb) p statement->u.expression_s(Expression *) $80 = 0x0000000101000388(lldb) p statement->u.expression_s->type(ExpressionType) $81 = ASSIGN_EXPRESSION(lldb) p statement->u.expression_s->u.string_value(char *) $82 = 0x00000001010002f8 "i"
crb_create_block
frame #0: 0x0000000100006113 crowbar`crb_create_block(statement_list=0x0000000101000258) + 19 at create.c:355352 {353 Block *block;354-> 355 block = crb_malloc(sizeof(Block));356 block->statement_list = statement_list;357358 return block;
crb_create_block
frame #0: 0x000000010000612a crowbar`crb_create_block(statement_list=0x0000000101000258) + 42 at create.c:358355 block = crb_malloc(sizeof(Block));356 block->statement_list = statement_list;357-> 358 return block;359 }360361 Statement *(lldb) p statement_list->statement->u.expression_s->type(ExpressionType) $94 = FUNCTION_CALL_EXPRESSION(lldb) p statement_list->statement->u.expression_s->u.string_value(char *) $95 = 0x00000001010001a8 "print"
crb_create_for_statement
frame #0: 0x00000001000060ad crowbar`crb_create_for_statement(init=0x0000000000000000, cond=0x0000000000000000, post=0x0000000000000000, block=0x00000001010003d8) + 29 at create.c:341338 {339 Statement *st;340-> 341 st = alloc_statement(FOR_STATEMENT);342 st->u.for_s.init = init;343 st->u.for_s.condition = cond;344 st->u.for_s.post = post;
crb_chain_statement_list
