1
0
Fork 0
forked from len0rd/rockbox

sbtools: factor code in command parser

Change-Id: I790c373b8a0319cdb00650d3c59919bd4b0b96f6
This commit is contained in:
Amaury Pouly 2013-08-22 01:15:00 +02:00
parent 81f97f67e2
commit a122b52d66

View file

@ -582,15 +582,7 @@ struct cmd_file_t *db_parse_file(const char *file)
/* add initial constants */ /* add initial constants */
for(int i = 0; i < NR_INITIAL_CONSTANTS; i++) for(int i = 0; i < NR_INITIAL_CONSTANTS; i++)
{ db_add_int_opt(&cmd_file->constant_list, init_const_name[i], init_const_value[i]);
struct cmd_option_t *opt = xmalloc(sizeof(struct cmd_option_t));
memset(opt, 0, sizeof(struct cmd_option_t));
opt->name = strdup(init_const_name[i]);
opt->is_string = false;
opt->val = init_const_value[i];
opt->next = cmd_file->constant_list;
cmd_file->constant_list = opt;
}
struct lex_ctx_t lctx; struct lex_ctx_t lctx;
lctx.ctx.file = file; lctx.ctx.file = file;
@ -611,22 +603,17 @@ struct cmd_file_t *db_parse_file(const char *file)
while(true) while(true)
{ {
struct cmd_option_t *opt = xmalloc(sizeof(struct cmd_option_t));
memset(opt, 0, sizeof(struct cmd_option_t));
next(true); next(true);
if(lexem.type == LEX_RBRACE) if(lexem.type == LEX_RBRACE)
break; break;
if(lexem.type != LEX_IDENTIFIER) if(lexem.type != LEX_IDENTIFIER)
parse_error(lexem, "Identifier expected in constants\n"); parse_error(lexem, "Identifier expected in constants\n");
opt->name = lexem.str; const char *name = lexem.str;
next(false); /* lexem string is kept as option name */ next(false); /* lexem string is kept as option name */
if(lexem.type != LEX_EQUAL) if(lexem.type != LEX_EQUAL)
parse_error(lexem, "'=' expected after identifier\n"); parse_error(lexem, "'=' expected after identifier\n");
next(true); next(true);
opt->is_string = false; db_add_int_opt(&cmd_file->constant_list, name, parse_intexpr(&lctx, cmd_file->constant_list));
opt->val = parse_intexpr(&lctx, cmd_file->constant_list);
opt->next = cmd_file->constant_list;
cmd_file->constant_list = opt;
if(lexem.type != LEX_SEMICOLON) if(lexem.type != LEX_SEMICOLON)
parse_error(lexem, "';' expected after string\n"); parse_error(lexem, "';' expected after string\n");
} }
@ -644,28 +631,20 @@ struct cmd_file_t *db_parse_file(const char *file)
next(true); next(true);
if(lexem.type == LEX_RBRACE) if(lexem.type == LEX_RBRACE)
break; break;
struct cmd_option_t *opt = xmalloc(sizeof(struct cmd_option_t));
memset(opt, 0, sizeof(struct cmd_option_t));
if(lexem.type != LEX_IDENTIFIER) if(lexem.type != LEX_IDENTIFIER)
parse_error(lexem, "Identifier expected in options\n"); parse_error(lexem, "Identifier expected in options\n");
opt->name = lexem.str; const char *name = lexem.str;
next(false); /* lexem string is kept as option name */ next(false); /* lexem string is kept as option name */
if(lexem.type != LEX_EQUAL) if(lexem.type != LEX_EQUAL)
parse_error(lexem, "'=' expected after identifier\n"); parse_error(lexem, "'=' expected after identifier\n");
next(true); next(true);
if(lexem.type == LEX_STRING) if(lexem.type == LEX_STRING)
{ {
opt->is_string = true; db_add_str_opt(&cmd_file->opt_list, name, lexem.str);
opt->str = lexem.str; next(true);
next(false); /* lexem string is kept as option name */
} }
else else
{ db_add_int_opt(&cmd_file->opt_list, name, parse_intexpr(&lctx, cmd_file->constant_list));
opt->is_string = false;
opt->val = parse_intexpr(&lctx, cmd_file->constant_list);
}
opt->next = cmd_file->opt_list;
cmd_file->opt_list = opt;
if(lexem.type != LEX_SEMICOLON) if(lexem.type != LEX_SEMICOLON)
parse_error(lexem, "';' expected after string\n"); parse_error(lexem, "';' expected after string\n");
} }
@ -683,30 +662,27 @@ struct cmd_file_t *db_parse_file(const char *file)
next(true); next(true);
if(lexem.type == LEX_RBRACE) if(lexem.type == LEX_RBRACE)
break; break;
struct cmd_source_t *src = xmalloc(sizeof(struct cmd_source_t));
memset(src, 0, sizeof(struct cmd_source_t));
if(lexem.type != LEX_IDENTIFIER) if(lexem.type != LEX_IDENTIFIER)
parse_error(lexem, "identifier expected in sources\n"); parse_error(lexem, "identifier expected in sources\n");
src->identifier = lexem.str; const char *srcid = lexem.str;
if(db_find_source_by_id(cmd_file, srcid) != NULL)
parse_error(lexem, "Duplicate source identifier\n");
next(false); /* lexem string is kept as source name */ next(false); /* lexem string is kept as source name */
if(lexem.type != LEX_EQUAL) if(lexem.type != LEX_EQUAL)
parse_error(lexem, "'=' expected after identifier\n"); parse_error(lexem, "'=' expected after identifier\n");
next(true); next(true);
if(lexem.type == LEX_STRING) if(lexem.type == LEX_STRING)
{ {
src->is_extern = false; db_add_source(cmd_file, srcid, lexem.str);
src->filename = lexem.str; next(true);
next(false); /* lexem string is kept as file name */
} }
else if(lexem.type == LEX_IDENTIFIER && !strcmp(lexem.str, "extern")) else if(lexem.type == LEX_IDENTIFIER && !strcmp(lexem.str, "extern"))
{ {
src->is_extern = true;
src->filename = strdup("<extern>"); /* duplicate because it will be free'd */
next(true); next(true);
if(lexem.type != LEX_LPAREN) if(lexem.type != LEX_LPAREN)
parse_error(lexem, "'(' expected after 'extern'\n"); parse_error(lexem, "'(' expected after 'extern'\n");
next(true); next(true);
src->extern_nr = parse_intexpr(&lctx, cmd_file->constant_list); db_add_extern_source(cmd_file, srcid, parse_intexpr(&lctx, cmd_file->constant_list));
if(lexem.type != LEX_RPAREN) if(lexem.type != LEX_RPAREN)
parse_error(lexem, "')' expected\n"); parse_error(lexem, "')' expected\n");
next(true); next(true);
@ -715,24 +691,14 @@ struct cmd_file_t *db_parse_file(const char *file)
parse_error(lexem, "String or 'extern' expected after '='\n"); parse_error(lexem, "String or 'extern' expected after '='\n");
if(lexem.type != LEX_SEMICOLON) if(lexem.type != LEX_SEMICOLON)
parse_error(lexem, "';' expected\n"); parse_error(lexem, "';' expected\n");
if(db_find_source_by_id(cmd_file, src->identifier) != NULL)
parse_error(lexem, "Duplicate source identifier\n");
/* type filled later */
src->type = CMD_SRC_UNK;
src->next = cmd_file->source_list;
cmd_file->source_list = src;
} }
/* sections */ /* sections */
struct cmd_section_t *end_sec = NULL;
while(true) while(true)
{ {
next(true); next(true);
if(lexem.type == LEX_EOF) if(lexem.type == LEX_EOF)
break; break;
struct cmd_section_t *sec = xmalloc(sizeof(struct cmd_section_t));
struct cmd_inst_t *end_list = NULL;
memset(sec, 0, sizeof(struct cmd_section_t));
if(lexem.type != LEX_IDENTIFIER || strcmp(lexem.str, "section") != 0) if(lexem.type != LEX_IDENTIFIER || strcmp(lexem.str, "section") != 0)
parse_error(lexem, "'section' expected\n"); parse_error(lexem, "'section' expected\n");
next(true); next(true);
@ -740,35 +706,27 @@ struct cmd_file_t *db_parse_file(const char *file)
parse_error(lexem, "'(' expected after 'section'\n"); parse_error(lexem, "'(' expected after 'section'\n");
next(true); next(true);
/* can be any number */ /* can be any number */
sec->identifier = parse_intexpr(&lctx, cmd_file->constant_list); struct cmd_section_t *sec = db_add_section(cmd_file, parse_intexpr(&lctx, cmd_file->constant_list), false);
/* options ? */ /* options ? */
if(lexem.type == LEX_SEMICOLON) if(lexem.type == LEX_SEMICOLON)
{ {
do do
{ {
next(true); next(true);
struct cmd_option_t *opt = xmalloc(sizeof(struct cmd_option_t));
memset(opt, 0, sizeof(struct cmd_option_t));
if(lexem.type != LEX_IDENTIFIER) if(lexem.type != LEX_IDENTIFIER)
parse_error(lexem, "Identifier expected for section option\n"); parse_error(lexem, "Identifier expected for section option\n");
opt->name = lexem.str; const char *name = lexem.str;
next(false); /* lexem string is kept as option name */ next(false); /* lexem string is kept as option name */
if(lexem.type != LEX_EQUAL) if(lexem.type != LEX_EQUAL)
parse_error(lexem, "'=' expected after option identifier\n"); parse_error(lexem, "'=' expected after option identifier\n");
next(true); next(true);
if(lexem.type == LEX_STRING) if(lexem.type == LEX_STRING)
{ {
opt->is_string = true; db_add_str_opt(&sec->opt_list, name, lexem.str);
opt->str = lexem.str; next(true);
next(false); /* lexem string is kept as option string */
} }
else else
{ db_add_int_opt(&sec->opt_list, name, parse_intexpr(&lctx, cmd_file->constant_list));
opt->is_string = false;
opt->val = parse_intexpr(&lctx, cmd_file->constant_list);
}
opt->next = sec->opt_list;
sec->opt_list = opt;
}while(lexem.type == LEX_COLON); }while(lexem.type == LEX_COLON);
} }
if(lexem.type != LEX_RPAREN) if(lexem.type != LEX_RPAREN)
@ -783,8 +741,7 @@ struct cmd_file_t *db_parse_file(const char *file)
next(true); next(true);
if(lexem.type == LEX_RBRACE) if(lexem.type == LEX_RBRACE)
break; break;
struct cmd_inst_t *inst = xmalloc(sizeof(struct cmd_inst_t)); struct cmd_inst_t *inst = db_add_inst(&sec->inst_list, CMD_LOAD, 0);
memset(inst, 0, sizeof(struct cmd_inst_t));
if(lexem.type != LEX_IDENTIFIER) if(lexem.type != LEX_IDENTIFIER)
parse_error(lexem, "Instruction expected in section\n"); parse_error(lexem, "Instruction expected in section\n");
if(strcmp(lexem.str, "load") == 0) if(strcmp(lexem.str, "load") == 0)
@ -851,16 +808,6 @@ struct cmd_file_t *db_parse_file(const char *file)
} }
else else
parse_error(lexem, "Internal error"); parse_error(lexem, "Internal error");
if(end_list == NULL)
{
sec->inst_list = inst;
end_list = inst;
}
else
{
end_list->next = inst;
end_list = inst;
}
} }
} }
else if(lexem.type == LEX_LE) else if(lexem.type == LEX_LE)
@ -876,17 +823,6 @@ struct cmd_file_t *db_parse_file(const char *file)
} }
else else
parse_error(lexem, "'{' or '<=' expected after section directive\n"); parse_error(lexem, "'{' or '<=' expected after section directive\n");
if(end_sec == NULL)
{
cmd_file->section_list = sec;
end_sec = sec;
}
else
{
end_sec->next = sec;
end_sec = sec;
}
} }
#undef lexem #undef lexem
#undef next #undef next