diff options
| author | Amaury Pouly <amaury.pouly@gmail.com> | 2012-05-23 11:03:35 +0200 |
|---|---|---|
| committer | Amaury Pouly <amaury.pouly@gmail.com> | 2012-05-31 13:57:25 +0200 |
| commit | a87a9ef37372b4380808ec2efa7c762e137668f1 (patch) | |
| tree | 9c759088f0f9cf6717d96789b6805812f6b187ea /utils/imxtools/dbparser.c | |
| parent | ba8e4367fb4d116ffc01c12cc619bfc714e582c9 (diff) | |
| download | rockbox-a87a9ef37372b4380808ec2efa7c762e137668f1.zip rockbox-a87a9ef37372b4380808ec2efa7c762e137668f1.tar.gz rockbox-a87a9ef37372b4380808ec2efa7c762e137668f1.tar.bz2 rockbox-a87a9ef37372b4380808ec2efa7c762e137668f1.tar.xz | |
imxtools: move tools to a new sbtools/ subdirectory
Change-Id: I0d8d6831b35037725486f61fc363de87bc8ba92e
Diffstat (limited to 'utils/imxtools/dbparser.c')
| -rw-r--r-- | utils/imxtools/dbparser.c | 857 |
1 files changed, 0 insertions, 857 deletions
diff --git a/utils/imxtools/dbparser.c b/utils/imxtools/dbparser.c deleted file mode 100644 index 89a63b3..0000000 --- a/utils/imxtools/dbparser.c +++ /dev/null @@ -1,857 +0,0 @@ -/*************************************************************************** - * __________ __ ___. - * Open \______ \ ____ ____ | | _\_ |__ _______ ___ - * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / - * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2011 Amaury Pouly - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#define _POSIX_C_SOURCE 200809L /* for strdup */ -#include <stdio.h> -#include <ctype.h> -#include <stdint.h> -#include <string.h> -#include "dbparser.h" -#include "misc.h" - -enum lexem_type_t -{ - LEX_IDENTIFIER, - LEX_LPAREN, - LEX_RPAREN, - LEX_NUMBER, - LEX_STRING, /* double-quoted string */ - LEX_EQUAL, - LEX_SEMICOLON, - LEX_LBRACE, - LEX_RBRACE, - LEX_RANGLE, - LEX_OR, - LEX_LSHIFT, - LEX_COLON, - LEX_LE, - LEX_EOF -}; - -struct lexem_t -{ - enum lexem_type_t type; - /* if str is not NULL, it must be a malloc'd pointer */ - char *str; - uint32_t num; - int line; - const char *file; -}; - -struct context_t -{ - const char *file; - char *begin; - char *end; - char *ptr; - int line; -}; - -#define parse_error(ctx, ...) \ - do { fprintf(stderr, "%s:%d: ", ctx->file, ctx->line); \ - fprintf(stderr, __VA_ARGS__); exit(2); } while(0) - -static void advance(struct context_t *ctx, int nr_chars) -{ - while(nr_chars--) - { - if(*(ctx->ptr++) == '\n') - ctx->line++; - } -} - -static inline bool eof(struct context_t *ctx) -{ - return ctx->ptr == ctx->end; -} - -static inline bool next_valid(struct context_t *ctx, int nr) -{ - return ctx->ptr + nr < ctx->end; -} - -static inline char cur_char(struct context_t *ctx) -{ - return *ctx->ptr; -} - -static inline char next_char(struct context_t *ctx, int nr) -{ - return ctx->ptr[nr]; -} - -static inline void locate_lexem(struct lexem_t *lex, struct context_t *ctx) -{ - lex->file = ctx->file; - lex->line = ctx->line; -} - -static void __parse_string(struct context_t *ctx, void *user, void (*emit_fn)(void *user, char c)) -{ - while(!eof(ctx)) - { - if(cur_char(ctx) == '"') - break; - else if(cur_char(ctx) == '\\') - { - advance(ctx, 1); - if(eof(ctx)) - parse_error(ctx, "Unfinished string\n"); - if(cur_char(ctx) == '\\') emit_fn(user, '\\'); - else if(cur_char(ctx) == '\'') emit_fn(user, '\''); - else if(cur_char(ctx) == '\"') emit_fn(user, '\"'); - else parse_error(ctx, "Unknown escape sequence \\%c\n", cur_char(ctx)); - advance(ctx, 1); - } - else - { - emit_fn(user, cur_char(ctx)); - advance(ctx, 1); - } - } - if(eof(ctx) || cur_char(ctx) != '"') - parse_error(ctx, "Unfinished string\n"); - advance(ctx, 1); -} - -static void __parse_string_emit(void *user, char c) -{ - char **pstr = (char **)user; - *(*pstr)++ = c; -} - -static void __parse_string_count(void *user, char c) -{ - (void) c; - (*(int *)user)++; -} - -static void parse_string(struct context_t *ctx, struct lexem_t *lexem) -{ - locate_lexem(lexem, ctx); - /* skip " */ - advance(ctx, 1); - /* compute length */ - struct context_t cpy_ctx = *ctx; - int length = 0; - __parse_string(&cpy_ctx, (void *)&length, __parse_string_count); - /* parse again */ - lexem->type = LEX_STRING; - lexem->str = xmalloc(length + 1); - lexem->str[length] = 0; - char *pstr = lexem->str; - __parse_string(ctx, (void *)&pstr, __parse_string_emit); -} - -static void parse_ascii_number(struct context_t *ctx, struct lexem_t *lexem) -{ - locate_lexem(lexem, ctx); - /* skip ' */ - advance(ctx, 1); - /* we expect n<=4 character and then ' */ - int len = 0; - uint32_t value = 0; - while(!eof(ctx)) - { - if(cur_char(ctx) != '\'') - { - value = value << 8 | cur_char(ctx); - len++; - advance(ctx, 1); - } - else - break; - } - if(eof(ctx) || cur_char(ctx) != '\'') - parse_error(ctx, "Unterminated ascii number literal\n"); - if(len == 0 || len > 4) - parse_error(ctx, "Invalid ascii number literal length: only 1 to 4 characters allowed\n"); - /* skip ' */ - advance(ctx, 1); - lexem->type = LEX_NUMBER; - lexem->num = value; -} - -static void parse_number(struct context_t *ctx, struct lexem_t *lexem) -{ - locate_lexem(lexem, ctx); - /* check base */ - int base = 10; - if(cur_char(ctx) == '0' && next_valid(ctx, 1) && next_char(ctx, 1) == 'x') - { - advance(ctx, 2); - base = 16; - } - - lexem->type = LEX_NUMBER; - lexem->num = 0; - while(!eof(ctx) && isxdigit(cur_char(ctx))) - { - if(base == 10 && !isdigit(cur_char(ctx))) - break; - byte v; - if(convxdigit(cur_char(ctx), &v)) - break; - lexem->num = base * lexem->num + v; - advance(ctx, 1); - } -} - -static void parse_identifier(struct context_t *ctx, struct lexem_t *lexem) -{ - locate_lexem(lexem, ctx); - /* remember position */ - char *old = ctx->ptr; - while(!eof(ctx) && (isalnum(cur_char(ctx)) || cur_char(ctx) == '_')) - advance(ctx, 1); - lexem->type = LEX_IDENTIFIER; - int len = ctx->ptr - old; - lexem->str = xmalloc(len + 1); - lexem->str[len] = 0; - memcpy(lexem->str, old, len); -} - -static void next_lexem(struct context_t *ctx, struct lexem_t *lexem) -{ - #define ret_simple(t, adv) \ - do {locate_lexem(lexem, ctx); \ - lexem->type = t; \ - advance(ctx, adv); \ - return;} while(0) - while(!eof(ctx)) - { - char c = cur_char(ctx); - /* skip whitespace */ - if(c == ' ' || c == '\t' || c == '\n' || c == '\r') - { - advance(ctx, 1); - continue; - } - /* skip C++ style comments */ - if(c == '/' && next_valid(ctx, 1) && next_char(ctx, 1) == '/') - { - while(!eof(ctx) && cur_char(ctx) != '\n') - advance(ctx, 1); - continue; - } - /* skip C-style comments */ - if(c == '/' && next_valid(ctx, 1) && next_char(ctx, 1) == '*') - { - advance(ctx, 2); - while(true) - { - if(!next_valid(ctx, 1)) - parse_error(ctx, "Unterminated comment"); - if(cur_char(ctx) == '*' && next_char(ctx, 1) == '/') - { - advance(ctx, 2); - break; - } - advance(ctx, 1); - } - continue; - } - break; - } - if(eof(ctx)) ret_simple(LEX_EOF, 0); - char c = cur_char(ctx); - bool nv = next_valid(ctx, 1); - char nc = nv ? next_char(ctx, 1) : 0; - if(c == '(') ret_simple(LEX_LPAREN, 1); - if(c == ')') ret_simple(LEX_RPAREN, 1); - if(c == '{') ret_simple(LEX_LBRACE, 1); - if(c == '}') ret_simple(LEX_RBRACE, 1); - if(c == '>') ret_simple(LEX_RANGLE, 1); - if(c == '=') ret_simple(LEX_EQUAL, 1); - if(c == ';') ret_simple(LEX_SEMICOLON, 1); - if(c == ',') ret_simple(LEX_COLON, 1); - if(c == '|') ret_simple(LEX_OR, 1); - if(c == '<' && nv && nc == '<') ret_simple(LEX_LSHIFT, 2); - if(c == '<' && nv && nc == '=') ret_simple(LEX_LE, 2); - if(c == '"') return parse_string(ctx, lexem); - if(c == '\'') return parse_ascii_number(ctx, lexem); - if(isdigit(c)) return parse_number(ctx, lexem); - if(isalpha(c) || c == '_') return parse_identifier(ctx, lexem); - parse_error(ctx, "Unexpected character '%c'\n", c); - #undef ret_simple -} - -#if 0 -static void log_lexem(struct lexem_t *lexem) -{ - switch(lexem->type) - { - case LEX_EOF: printf("<eof>"); break; - case LEX_EQUAL: printf("="); break; - case LEX_IDENTIFIER: printf("id(%s)", lexem->str); break; - case LEX_LPAREN: printf("("); break; - case LEX_RPAREN: printf(")"); break; - case LEX_LBRACE: printf("{"); break; - case LEX_RBRACE: printf("}"); break; - case LEX_SEMICOLON: printf(";"); break; - case LEX_NUMBER: printf("num(%d)", lexem->num); break; - case LEX_STRING: printf("str(%s)", lexem->str); break; - case LEX_OR: printf("|"); break; - case LEX_LSHIFT: printf("<<"); break; - default: printf("<unk>"); - } -} -#endif - -struct cmd_source_t *db_find_source_by_id(struct cmd_file_t *cmd_file, const char *id) -{ - struct cmd_source_t *src = cmd_file->source_list; - while(src) - { - if(strcmp(src->identifier, id) == 0) - return src; - src = src->next; - } - return NULL; -} - -struct cmd_option_t *db_find_option_by_id(struct cmd_option_t *opt, const char *name) -{ - while(opt) - { - if(strcmp(opt->name, name) == 0) - return opt; - opt = opt->next; - } - return NULL; -} - -#define INVALID_SB_SUBVERSION 0xffff - -static uint16_t parse_sb_subversion(char *str) -{ - int len = strlen(str); - uint16_t n = 0; - if(len == 0 || len > 4) - return INVALID_SB_SUBVERSION; - for(int i = 0; i < len; i++) - { - if(!isdigit(str[i])) - return INVALID_SB_SUBVERSION; - n = n << 4 | (str[i] - '0'); - } - return n; -} - -bool db_parse_sb_version(struct sb_version_t *ver, char *str) -{ - int len = strlen(str); - int cnt = 0; - int pos[2]; - - for(int i = 0; i < len; i++) - { - if(str[i] != '.') - continue; - if(cnt == 2) - return false; - pos[cnt++] = i + 1; - str[i] = 0; - } - if(cnt != 2) - return false; - ver->major = parse_sb_subversion(str); - ver->minor = parse_sb_subversion(str + pos[0]); - ver->revision = parse_sb_subversion(str + pos[1]); - return ver->major != INVALID_SB_SUBVERSION && - ver->minor != INVALID_SB_SUBVERSION && - ver->revision != INVALID_SB_SUBVERSION; -} - -#undef parse_error -#define parse_error(lexem, ...) \ - do { fprintf(stderr, "%s:%d: ", lexem.file, lexem.line); \ - fprintf(stderr, __VA_ARGS__); exit(2); } while(0) - -struct lex_ctx_t -{ - struct context_t ctx; - struct lexem_t lexem; -}; - -/* When lexems hold strings (like identifier), it might be useful to steal - * the pointer and don't clean the lexem but in other case, one don't want - * to keep the pointer to the string and just want to release the memory. - * Thus clean_lexem should be true except when one keeps a pointer */ -static inline void next(struct lex_ctx_t *ctx, bool clean_lexem) -{ - if(clean_lexem) - free(ctx->lexem.str); - memset(&ctx->lexem, 0, sizeof(struct lexem_t)); - next_lexem(&ctx->ctx, &ctx->lexem); -} - -static uint32_t parse_term_expr(struct lex_ctx_t *ctx, struct cmd_option_t *const_list) -{ - uint32_t ret = 0; - if(ctx->lexem.type == LEX_NUMBER) - ret = ctx->lexem.num; - else if(ctx->lexem.type == LEX_IDENTIFIER) - { - struct cmd_option_t *c = db_find_option_by_id(const_list, ctx->lexem.str); - if(c == NULL) - parse_error(ctx->lexem, "Undefined reference to constant '%s'\n", ctx->lexem.str); - if(c->is_string) - parse_error(ctx->lexem, "Internal error: constant '%s' is not an integer\n", ctx->lexem.str); - ret = c->val; - } - else - parse_error(ctx->lexem, "Number or constant identifier expected\n"); - next(ctx, true); - return ret; -} - -static uint32_t parse_shift_expr(struct lex_ctx_t *ctx, struct cmd_option_t *const_list) -{ - uint32_t v = parse_term_expr(ctx, const_list); - while(ctx->lexem.type == LEX_LSHIFT) - { - next(ctx, true); - v <<= parse_term_expr(ctx, const_list); - } - return v; -} - -static uint32_t parse_or_expr(struct lex_ctx_t *ctx, struct cmd_option_t *const_list) -{ - uint32_t v = parse_shift_expr(ctx, const_list); - while(ctx->lexem.type == LEX_OR) - { - next(ctx, true); - v |= parse_shift_expr(ctx, const_list); - } - return v; -} - -static uint32_t parse_intexpr(struct lex_ctx_t *ctx, struct cmd_option_t *const_list) -{ - return parse_or_expr(ctx, const_list); -} - -#define NR_INITIAL_CONSTANTS 4 -static char *init_const_name[NR_INITIAL_CONSTANTS] = {"true", "false", "yes", "no"}; -static uint32_t init_const_value[NR_INITIAL_CONSTANTS] = {1, 0, 1, 0}; - -struct cmd_file_t *db_parse_file(const char *file) -{ - size_t size; - FILE *f = fopen(file, "r"); - if(f == NULL) - { - if(g_debug) - perror("Cannot open db file"); - return NULL; - } - fseek(f, 0, SEEK_END); - size = ftell(f); - fseek(f, 0, SEEK_SET); - char *buf = xmalloc(size); - if(fread(buf, size, 1, f) != 1) - { - if(g_debug) - perror("Cannot read db file"); - return NULL; - } - fclose(f); - - if(g_debug) - printf("Parsing db file '%s'\n", file); - struct cmd_file_t *cmd_file = xmalloc(sizeof(struct cmd_file_t)); - memset(cmd_file, 0, sizeof(struct cmd_file_t)); - - /* add initial constants */ - for(int i = 0; i < NR_INITIAL_CONSTANTS; 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; - lctx.ctx.file = file; - lctx.ctx.line = 1; - lctx.ctx.begin = buf; - lctx.ctx.ptr = buf; - lctx.ctx.end = buf + size; - #define next(clean_lexem) next(&lctx, clean_lexem) - #define lexem lctx.lexem - /* init lexer */ - next(false); /* don't clean init lexem because it doesn't exist */ - /* constants ? */ - if(lexem.type == LEX_IDENTIFIER && !strcmp(lexem.str, "constants")) - { - next(true); - if(lexem.type != LEX_LBRACE) - parse_error(lexem, "'{' expected after 'constants'\n"); - - while(true) - { - struct cmd_option_t *opt = xmalloc(sizeof(struct cmd_option_t)); - memset(opt, 0, sizeof(struct cmd_option_t)); - next(true); - if(lexem.type == LEX_RBRACE) - break; - if(lexem.type != LEX_IDENTIFIER) - parse_error(lexem, "Identifier expected in constants\n"); - opt->name = lexem.str; - next(false); /* lexem string is kept as option name */ - if(lexem.type != LEX_EQUAL) - parse_error(lexem, "'=' expected after identifier\n"); - next(true); - opt->is_string = false; - 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) - parse_error(lexem, "';' expected after string\n"); - } - next(true); - } - /* options ? */ - if(lexem.type == LEX_IDENTIFIER && !strcmp(lexem.str, "options")) - { - next(true); - if(lexem.type != LEX_LBRACE) - parse_error(lexem, "'{' expected after 'options'\n"); - - while(true) - { - next(true); - if(lexem.type == LEX_RBRACE) - 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) - parse_error(lexem, "Identifier expected in options\n"); - opt->name = lexem.str; - next(false); /* lexem string is kept as option name */ - if(lexem.type != LEX_EQUAL) - parse_error(lexem, "'=' expected after identifier\n"); - next(true); - if(lexem.type == LEX_STRING) - { - opt->is_string = true; - opt->str = lexem.str; - next(false); /* lexem string is kept as option name */ - } - else - { - 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) - parse_error(lexem, "';' expected after string\n"); - } - next(true); - } - /* sources */ - if(lexem.type != LEX_IDENTIFIER || strcmp(lexem.str, "sources")) - parse_error(lexem, "'sources' expected\n"); - next(true); - if(lexem.type != LEX_LBRACE) - parse_error(lexem, "'{' expected after 'sources'\n"); - - while(true) - { - next(true); - if(lexem.type == LEX_RBRACE) - 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) - parse_error(lexem, "identifier expected in sources\n"); - src->identifier = lexem.str; - next(false); /* lexem string is kept as source name */ - if(lexem.type != LEX_EQUAL) - parse_error(lexem, "'=' expected after identifier\n"); - next(true); - if(lexem.type == LEX_STRING) - { - src->is_extern = false; - src->filename = lexem.str; - next(false); /* lexem string is kept as file name */ - } - 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); - if(lexem.type != LEX_LPAREN) - parse_error(lexem, "'(' expected after 'extern'\n"); - next(true); - src->extern_nr = parse_intexpr(&lctx, cmd_file->constant_list); - if(lexem.type != LEX_RPAREN) - parse_error(lexem, "')' expected\n"); - next(true); - } - else - parse_error(lexem, "String or 'extern' expected after '='\n"); - if(lexem.type != LEX_SEMICOLON) - 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 */ - struct cmd_section_t *end_sec = NULL; - while(true) - { - next(true); - if(lexem.type == LEX_EOF) - 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) - parse_error(lexem, "'section' expected\n"); - next(true); - if(lexem.type != LEX_LPAREN) - parse_error(lexem, "'(' expected after 'section'\n"); - next(true); - /* can be any number */ - sec->identifier = parse_intexpr(&lctx, cmd_file->constant_list); - /* options ? */ - if(lexem.type == LEX_SEMICOLON) - { - do - { - 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) - parse_error(lexem, "Identifier expected for section option\n"); - opt->name = lexem.str; - next(false); /* lexem string is kept as option name */ - if(lexem.type != LEX_EQUAL) - parse_error(lexem, "'=' expected after option identifier\n"); - next(true); - if(lexem.type == LEX_STRING) - { - opt->is_string = true; - opt->str = lexem.str; - next(false); /* lexem string is kept as option string */ - } - else - { - 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); - } - if(lexem.type != LEX_RPAREN) - parse_error(lexem, "')' expected after section identifier\n"); - next(true); - if(lexem.type == LEX_LBRACE) - { - sec->is_data = false; - /* commands */ - while(true) - { - next(true); - if(lexem.type == LEX_RBRACE) - break; - struct cmd_inst_t *inst = xmalloc(sizeof(struct cmd_inst_t)); - memset(inst, 0, sizeof(struct cmd_inst_t)); - if(lexem.type != LEX_IDENTIFIER) - parse_error(lexem, "Instruction expected in section\n"); - if(strcmp(lexem.str, "load") == 0) - inst->type = CMD_LOAD; - else if(strcmp(lexem.str, "call") == 0) - inst->type = CMD_CALL; - else if(strcmp(lexem.str, "jump") == 0) - inst->type = CMD_JUMP; - else if(strcmp(lexem.str, "mode") == 0) - inst->type = CMD_MODE; - else - parse_error(lexem, "Instruction expected in section\n"); - next(true); - - if(inst->type == CMD_LOAD) - { - if(lexem.type != LEX_IDENTIFIER) - parse_error(lexem, "Identifier expected after instruction\n"); - inst->identifier = lexem.str; - if(db_find_source_by_id(cmd_file, inst->identifier) == NULL) - parse_error(lexem, "Undefined reference to source '%s'\n", inst->identifier); - next(false); /* lexem string kept as identifier */ - if(lexem.type == LEX_RANGLE) - { - // load at - inst->type = CMD_LOAD_AT; - next(true); - inst->addr = parse_intexpr(&lctx, cmd_file->constant_list); - } - if(lexem.type != LEX_SEMICOLON) - parse_error(lexem, "';' expected after command\n"); - } - else if(inst->type == CMD_CALL || inst->type == CMD_JUMP) - { - if(lexem.type == LEX_IDENTIFIER) - { - inst->identifier = lexem.str; - if(db_find_source_by_id(cmd_file, inst->identifier) == NULL) - parse_error(lexem, "Undefined reference to source '%s'\n", inst->identifier); - next(false); /* lexem string kept as identifier */ - } - else - { - inst->type = (inst->type == CMD_CALL) ? CMD_CALL_AT : CMD_JUMP_AT; - inst->addr = parse_intexpr(&lctx, cmd_file->constant_list); - } - - if(lexem.type == LEX_LPAREN) - { - next(true); - inst->argument = parse_intexpr(&lctx, cmd_file->constant_list); - if(lexem.type != LEX_RPAREN) - parse_error(lexem, "Expected closing brace\n"); - next(true); - } - if(lexem.type != LEX_SEMICOLON) - parse_error(lexem, "';' expected after command\n"); - } - else if(inst->type == CMD_MODE) - { - inst->argument = parse_intexpr(&lctx, cmd_file->constant_list); - if(lexem.type != LEX_SEMICOLON) - parse_error(lexem, "Expected ';' after command\n"); - } - else - 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) - { - sec->is_data = true; - next(true); - if(lexem.type != LEX_IDENTIFIER) - parse_error(lexem, "Identifier expected after '<='\n"); - sec->source_id = lexem.str; - next(false); /* lexem string is kept as source id */ - if(lexem.type != LEX_SEMICOLON) - parse_error(lexem, "';' expected after identifier\n"); - } - else - 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 next - - free(buf); - return cmd_file; -} - -void db_generate_default_sb_version(struct sb_version_t *ver) -{ - ver->major = ver->minor = ver->revision = 0x999; -} - -void db_free_option_list(struct cmd_option_t *opt_list) -{ - while(opt_list) - { - struct cmd_option_t *next = opt_list->next; - fflush(stdout); - free(opt_list->name); - free(opt_list->str); - free(opt_list); - opt_list = next; - } -} - -void db_free(struct cmd_file_t *file) -{ - db_free_option_list(file->opt_list); - db_free_option_list(file->constant_list); - struct cmd_source_t *src = file->source_list; - while(src) - { - struct cmd_source_t *next = src->next; - free(src->identifier); - fflush(stdout); - free(src->filename); - if(src->loaded) - { - if(src->type == CMD_SRC_BIN) - free(src->bin.data); - if(src->type == CMD_SRC_ELF) - elf_release(&src->elf); - } - free(src); - src = next; - } - struct cmd_section_t *sec = file->section_list; - while(sec) - { - struct cmd_section_t *next = sec->next; - db_free_option_list(sec->opt_list); - free(sec->source_id); - struct cmd_inst_t *inst = sec->inst_list; - while(inst) - { - struct cmd_inst_t *next = inst->next; - free(inst->identifier); - free(inst); - inst = next; - } - free(sec); - sec = next; - } - free(file); -} |