+/**
+ * Sets the debug mask of module name to lvl
+ */
+static void set_dbg_level(const char *name, unsigned lvl)
+{
+ firm_dbg_module_t *module = dbg_register(name);
+
+ if (firm_dbg_get_mask(module) != lvl) {
+ firm_dbg_set_mask(module, lvl);
+
+ dbg_printf("Setting debug mask of module %s to %u\n", name, lvl);
+ }
+} /* set_dbg_level */
+
+/**
+ * Redirects the debug output of module name to fname
+ */
+static void set_dbg_outfile(const char *name, const char *fname)
+{
+ firm_dbg_module_t *module = dbg_register(name);
+ FILE *f = fopen(fname, "w");
+
+ if (! f) {
+ perror(fname);
+ return;
+ }
+
+ firm_dbg_set_file(module, f);
+ dbg_printf("Redirecting debug output of module %s to file %s\n", name, fname);
+} /* set_dbg_outfile */
+
+/**
+ * Show info about a firm thing.
+ */
+static void show_firm_object(void *firm_thing) {
+ FILE *f = stdout;
+
+ if (firm_thing == NULL) {
+ fprintf(f, "<NULL>\n");
+ return;
+ }
+ switch (get_kind(firm_thing)) {
+ case k_BAD:
+ fprintf(f, "BAD: (%p)\n", firm_thing);
+ break;
+ case k_entity:
+ dump_entity_to_file(f, firm_thing, dump_verbosity_max);
+ break;
+ case k_type:
+ dump_type_to_file(f, firm_thing, dump_verbosity_max);
+ break;
+ case k_ir_graph:
+ case k_ir_node:
+ case k_ir_mode:
+ case k_ir_op:
+ case k_tarval:
+ case k_ir_loop:
+ case k_ir_compound_graph_path:
+ case k_ir_extblk:
+ case k_ir_prog:
+ fprintf(f, "NIY\n");
+ break;
+ default:
+ fprintf(f, "Cannot identify thing at (%p).\n", firm_thing);
+ }
+} /* show_firm_object */
+
+/**
+ * Find a firm type by its number.
+ */
+static ir_type *find_type_nr(long nr) {
+ int i, n = get_irp_n_types();
+ ir_type *tp;
+
+ for (i = 0; i < n; ++i) {
+ tp = get_irp_type(i);
+ if (get_type_nr(tp) == nr)
+ return tp;
+ }
+ tp = get_glob_type();
+ if (get_type_nr(tp) == nr)
+ return tp;
+ return NULL;
+} /* find_type_nr */
+
+/**
+ * Find a firm type by its name.
+ */
+static ir_type *find_type_name(const char *name) {
+ int i, n = get_irp_n_types();
+ ir_type *tp;
+
+ for (i = 0; i < n; ++i) {
+ tp = get_irp_type(i);
+ if (strcmp(get_type_name(tp), name) == 0)
+ return tp;
+ }
+ tp = get_glob_type();
+ if (strcmp(get_type_name(tp), name) == 0)
+ return tp;
+ return NULL;
+} /* find_type_name */
+
+/** The environment for the entity search functions. */
+typedef struct find_env {
+ union {
+ long nr; /**< the number that is searched for */
+ const char *name; /**< the name that is searched for */
+ } u;
+ ir_entity *res; /**< the result */
+} find_env_t;
+
+/**
+ * Type-walker: Find an entity with given number.
+ */
+static void check_ent_nr(type_or_ent *tore, void *ctx) {
+ ir_entity *ent = (ir_entity *)tore;
+ find_env_t *env = ctx;
+
+ if (is_entity(ent))
+ if (get_entity_nr(ent) == env->u.nr) {
+ env->res = ent;
+ }
+} /* check_ent_nr */
+
+/**
+ * Type-walker: Find an entity with given name.
+ */
+static void check_ent_name(type_or_ent *tore, void *ctx) {
+ ir_entity *ent = (ir_entity *)tore;
+ find_env_t *env = ctx;
+
+ if (is_entity(ent))
+ if (strcmp(get_entity_name(ent), env->u.name) == 0) {
+ env->res = ent;
+ }
+} /* check_ent_name */
+
+/**
+ * Find a firm entity by its number.
+ */
+static ir_entity *find_entity_nr(long nr) {
+ find_env_t env;
+
+ env.u.nr = nr;
+ env.res = NULL;
+ type_walk(check_ent_nr, NULL, &env);
+ return env.res;
+} /* find_entity_nr */
+
+/**
+ * Find a firm entity by its name.
+ */
+static ir_entity *find_entity_name(const char *name) {
+ find_env_t env;
+
+ env.u.name = name;
+ env.res = NULL;
+ type_walk(check_ent_name, NULL, &env);
+ return env.res;
+} /* find_entity_name */
+
+/**
+ * Search methods for a name.
+ */
+static void show_by_name(type_or_ent *tore, void *env) {
+ ident *id = (ident *)env;
+
+ if (is_entity(tore)) {
+ ir_entity *ent = (ir_entity *)tore;
+
+ if (is_method_entity(ent)) {
+ if (get_entity_ident(ent) == id) {
+ ir_type *owner = get_entity_owner(ent);
+ ir_graph *irg = get_entity_irg(ent);
+
+ if (owner != get_glob_type()) {
+ printf("%s::%s", get_type_name(owner), get_id_str(id));
+ } else {
+ printf("%s", get_id_str(id));
+ }
+ if (irg)
+ printf("[%ld] (%p)\n", get_irg_graph_nr(irg), irg);
+ else
+ printf(" NULL\n");
+ }
+ }
+ }
+} /* show_by_name */
+
+/**
+ * Search methods for a ldname.
+ */
+static void show_by_ldname(type_or_ent *tore, void *env) {
+ ident *id = (ident *)env;
+
+ if (is_entity(tore)) {
+ ir_entity *ent = (ir_entity *)tore;
+
+ if (is_method_entity(ent)) {
+ if (get_entity_ld_ident(ent) == id) {
+ ir_type *owner = get_entity_owner(ent);
+ ir_graph *irg = get_entity_irg(ent);
+
+ if (owner != get_glob_type()) {
+ printf("%s::%s", get_type_name(owner), get_id_str(id));
+ } else {
+ printf("%s", get_id_str(id));
+ }
+ if (irg)
+ printf("[%ld] (%p)\n", get_irg_graph_nr(irg), irg);
+ else
+ printf(" NULL\n");
+ }
+ }
+ }
+} /* show_by_ldname */
+
+/**
+ * prints the address and graph number of all irgs with given name
+ */
+static void irg_name(const char *name) {
+ ident *id = new_id_from_str(name);
+
+ type_walk(show_by_name, NULL, (void *)id);
+} /* irg_name */
+
+/**
+ * prints the address and graph number of all irgs with given ld_name
+ */
+static void irg_ld_name(const char *name) {
+ ident *id = new_id_from_str(name);
+
+ type_walk(show_by_ldname, NULL, (void *)id);
+} /* irg_ld_name */
+
+enum tokens {
+ tok_create = 256,
+ tok_replace,
+ tok_lower,
+ tok_remirg,
+ tok_newent,
+ tok_newtype,
+ tok_showtype,
+ tok_showent,
+ tok_init,
+ tok_bp,
+ tok_enable,
+ tok_disable,
+ tok_setmask,
+ tok_setlvl,
+ tok_setoutfile,
+ tok_irgname,
+ tok_irgldname,
+ tok_help,
+ tok_identifier,
+ tok_number,
+ tok_eof,
+ tok_error
+};
+
+static const char *reserved[] = {
+ "create",
+ "replace",
+ "lower",
+ "remirg",
+ "newent",
+ "newtype",
+ "showtype",
+ "showent",
+ "init",
+ "bp",
+ "enable",
+ "disable",
+ "setmask",
+ "setlvl",
+ "setoutfile",
+ "irgname",
+ "irgldname",
+ "help"
+};
+
+/**
+ * The Lexer data.
+ */
+static struct lexer {
+ int has_token; /**< set if a token is cached. */
+ unsigned cur_token; /**< current token. */
+ unsigned number; /**< current token attribute. */
+ const char *s; /**< current token attribute. */
+ unsigned len; /**< current token attribute. */
+
+ const char *curr_pos;
+ const char *end_pos;
+ const char *tok_start;
+} lexer;
+
+/**
+ * Initialize the lexer.
+ */
+static void init_lexer(const char *input) {
+ lexer.has_token = 0;
+ lexer.curr_pos = input;
+ lexer.end_pos = input + strlen(input);
+} /* init_lexer */
+
+
+/**
+ * Get the next char from the input.
+ */
+static char next_char(void) {
+ if (lexer.curr_pos >= lexer.end_pos)
+ return '\0';
+ return *lexer.curr_pos++;
+} /* next_char */
+
+#define unput() if (lexer.curr_pos < lexer.end_pos) --lexer.curr_pos
+
+#undef MIN
+#define MIN(a, b) (a) < (b) ? (a) : (b)
+
+/**
+ * The lexer.
+ */
+static unsigned get_token(void) {
+ char c;
+ int i;
+
+ /* skip white space */
+ do {
+ c = next_char();
+ } while (c != '\0' && isspace(c));
+
+ lexer.tok_start = lexer.curr_pos - 1;
+ if (c == '.') {
+ /* command begins here */
+ int len = 0;
+
+ do {
+ c = next_char();
+ ++len;
+ } while (isalpha(c));
+ unput();
+
+ --len;
+ for (i = sizeof(reserved)/sizeof(reserved[0]) - 1; i >= 0; --i) {
+ if (strncasecmp(lexer.tok_start + 1, reserved[i], len) == 0 && reserved[i][len] == '\0')
+ break;
+ }
+ if (i >= 0)
+ return 256 + i;
+ return tok_error;
+ } else if (isalpha(c)) {
+ /* identifier */
+ lexer.s = lexer.curr_pos - 1;
+
+ do {
+ c = next_char();
+ } while (isgraph(c));
+ unput();
+ lexer.len = lexer.curr_pos - lexer.s;
+ return tok_identifier;
+ } else if (isdigit(c) || c == '-') {
+ unsigned number = 0;
+ unsigned sign = 0;
+
+ /* we support negative numbers as well, so one can easily set all bits with -1 */
+ if (c == '-') {
+ sign = 1;
+ c = next_char();
+ }
+
+ if (c == '0') {
+ c = next_char();
+
+ if (c == 'x' || c == 'X') {
+ for (;;) {
+ c = next_char();
+
+ if (! isxdigit(c))
+ break;
+ if (isdigit(c))
+ number = (number << 4) | (c - '0');
+ else
+ number = (number << 4) | (toupper(c) - 'A' + 10);
+ }
+ unput();
+ lexer.number = number;
+ return tok_number;
+ }
+ }
+ for (;;) {
+ if (! isdigit(c))
+ break;
+ number = number * 10 + (c - '0');
+ c = next_char();
+ }
+ unput();
+ lexer.number = sign ? 0 - number : number;
+ return tok_number;
+ }
+ else if (c == '\0')
+ return tok_eof;
+ return c;
+} /* get_token */