-void firm_debug(const char *cmd) {
- long nr;
- unsigned bp;
- char name[1024], fname[1024];
- unsigned lvl;
-
- while (isspace(*cmd)) ++cmd;
-
- if (sscanf(cmd, ".create %ld\n", &nr) == 1) {
- break_on_nr(nr, BP_ON_NEW_NODE);
- }
- else if (sscanf(cmd, ".replace %ld\n", &nr) == 1) {
- break_on_nr(nr, BP_ON_REPLACE);
- }
- else if (sscanf(cmd, ".lower %ld\n", &nr) == 1) {
- break_on_nr(nr, BP_ON_LOWER);
- }
- else if (sscanf(cmd, ".remirg %ld\n", &nr) == 1) {
- break_on_nr(nr, BP_ON_REMIRG);
- }
- else if (sscanf(cmd, ".remirg %s\n", name) == 1) {
- break_on_ident(name, BP_ON_REMIRG);
- }
- else if (sscanf(cmd, ".newent %ld\n", &nr) == 1) {
- break_on_nr(nr, BP_ON_NEW_ENT);
- }
- else if (sscanf(cmd, ".newent %s\n", name) == 1) {
- break_on_ident(name, BP_ON_NEW_ENT);
- }
- else if (sscanf(cmd, ".newtype %ld\n", &nr) == 1) {
- break_on_nr(nr, BP_ON_NEW_TYPE);
- }
- else if (sscanf(cmd, ".newtype %s\n", name) == 1) {
- break_on_ident(name, BP_ON_NEW_TYPE);
- }
- else if (sscanf(cmd, ".showtype %ld\n", &nr) == 1) {
- show_firm_object(find_type_nr(nr));
- }
- else if (sscanf(cmd, ".showtype %s\n", name) == 1) {
- show_firm_object(find_type_name(name));
- }
- else if (sscanf(cmd, ".showent %ld\n", &nr) == 1) {
- show_firm_object(find_entity_nr(nr));
- }
- else if (sscanf(cmd, ".showent %s\n", name) == 1) {
- show_firm_object(find_entity_name(name));
- }
- else if (strcmp(cmd, ".init") == 0)
- break_on_init = 1;
- else if (strcmp(cmd, ".bp") == 0)
- show_bp();
- else if (sscanf(cmd, ".enable %u", &bp) == 1)
- bp_activate(bp, 1);
- else if (sscanf(cmd, ".disable %u", &bp) == 1)
- bp_activate(bp, 0);
- else if (sscanf(cmd, ".setmask %s %u\n", name, &lvl) == 2)
- set_dbg_level(name, lvl);
- else if (sscanf(cmd, ".setlvl %s %u\n", name, &lvl) == 2)
- set_dbg_level(name, (1 << lvl) - 1);
- else if (sscanf(cmd, ".setoutfile %s %s\n", name, fname) == 2)
- set_dbg_outfile(name, fname);
- else if (sscanf(cmd, ".irgname %s\n", name) == 1)
- irg_name(name);
- else if (sscanf(cmd, ".irgldname %s\n", name) == 1)
- irg_ld_name(name);
- else {
- show_commands();
- }
+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 == '.' || isalpha(c)) {
+ /* command begins here */
+ int len = 0;
+ const char* tok_start;
+
+ do {
+ c = next_char();
+ ++len;
+ } while (isgraph(c));
+ unput();
+
+ tok_start = lexer.tok_start;
+ if (*tok_start == '.') {
+ ++tok_start;
+ --len;
+ }
+ for (i = sizeof(reserved)/sizeof(reserved[0]) - 1; i >= 0; --i) {
+ if (strncasecmp(tok_start, reserved[i], len) == 0 && reserved[i][len] == '\0')
+ return 256 + i;
+ }
+
+ /* identifier */
+ lexer.s = lexer.tok_start;
+ 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 */
+
+void firm_debug(const char *cmd)
+{
+ char name[1024], fname[1024];
+ size_t len;
+
+ init_lexer(cmd);
+
+ for (;;) {
+ unsigned token;
+
+ token = get_token();
+
+ switch (token) {
+ case tok_eof:
+ goto leave;
+
+ case tok_create:
+ token = get_token();
+ if (token != tok_number)
+ goto error;
+ break_on_nr(lexer.number, BP_ON_NEW_NODE);
+ break;
+
+ case tok_replace:
+ token = get_token();
+ if (token != tok_number)
+ goto error;
+ break_on_nr(lexer.number, BP_ON_REPLACE);
+ break;
+
+ case tok_lower:
+ token = get_token();
+ if (token != tok_number)
+ goto error;
+ break_on_nr(lexer.number, BP_ON_LOWER);
+ break;
+
+ case tok_remirg:
+ token = get_token();
+
+ if (token == tok_number)
+ break_on_nr(lexer.number, BP_ON_REMIRG);
+ else if (token == tok_identifier) {
+ len = MIN(lexer.len, 1023);
+ strncpy(name, lexer.s, len);
+ name[len] = '\0';
+ break_on_ident(name, BP_ON_REMIRG);
+ } else
+ goto error;
+ break;
+
+ case tok_newent:
+ token = get_token();
+
+ if (token == tok_number)
+ break_on_nr(lexer.number, BP_ON_NEW_ENT);
+ else if (token == tok_identifier) {
+ len = MIN(lexer.len, 1023);
+ strncpy(name, lexer.s, len);
+ name[len] = '\0';
+ break_on_ident(name, BP_ON_NEW_ENT);
+ } else
+ goto error;
+ break;
+
+ case tok_newtype:
+ token = get_token();
+
+ if (token == tok_number)
+ break_on_nr(lexer.number, BP_ON_NEW_TYPE);
+ else if (token == tok_identifier) {
+ len = MIN(lexer.len, 1023);
+ strncpy(name, lexer.s, len);
+ name[len] = '\0';
+ break_on_ident(name, BP_ON_NEW_TYPE);
+ } else
+ goto error;
+ break;
+
+ case tok_showtype:
+ token = get_token();
+
+ if (token == tok_number)
+ show_firm_object(find_type_nr(lexer.number));
+ else if (token == tok_identifier) {
+ len = MIN(lexer.len, 1023);
+ strncpy(name, lexer.s, len);
+ name[len] = '\0';
+ show_firm_object(find_type_name(name));
+ } else
+ goto error;
+ break;
+
+ case tok_showent:
+ token = get_token();
+
+ if (token == tok_number)
+ show_firm_object(find_entity_nr(lexer.number));
+ else if (token == tok_identifier) {
+ len = MIN(lexer.len, 1023);
+ strncpy(name, lexer.s, len);
+ name[len] = '\0';
+ show_firm_object(find_entity_name(name));
+ } else
+ goto error;
+ break;
+
+ case tok_init:
+ break_on_init = 1;
+ break;
+
+ case tok_bp:
+ show_bp();
+ break;
+
+ case tok_enable:
+ token = get_token();
+ if (token != tok_number)
+ goto error;
+ bp_activate(lexer.number, 1);
+ break;
+
+ case tok_disable:
+ token = get_token();
+ if (token != tok_number)
+ goto error;
+ bp_activate(lexer.number, 0);
+ break;
+
+ case tok_setmask:
+ token = get_token();
+ if (token != tok_identifier)
+ goto error;
+ len = MIN(lexer.len, 1023);
+ strncpy(name, lexer.s, len);
+ name[len] = '\0';
+
+ token = get_token();
+ if (token != tok_number)
+ goto error;
+ set_dbg_level(name, lexer.number);
+ break;
+
+ case tok_setlvl:
+ token = get_token();
+ if (token != tok_identifier)
+ goto error;
+ len = MIN(lexer.len, 1023);
+ strncpy(name, lexer.s, len);
+ name[len] = '\0';
+
+ token = get_token();
+ if (token != tok_number)
+ goto error;
+ set_dbg_level(name, (1 << lexer.number) - 1);
+ break;
+
+ case tok_setoutfile:
+ token = get_token();
+ if (token != tok_identifier)
+ goto error;
+ len = MIN(lexer.len, 1023);
+ strncpy(name, lexer.s, len);
+ name[len] = '\0';
+
+ token = get_token();
+ if (token != tok_identifier)
+ goto error;
+ len = MIN(lexer.len, 1023);
+ strncpy(fname, lexer.s, len);
+ fname[len] = '\0';
+ set_dbg_outfile(name, fname);
+
+ case tok_irgname:
+ token = get_token();
+ if (token != tok_identifier)
+ goto error;
+ len = MIN(lexer.len, 1023);
+ strncpy(name, lexer.s, len);
+ name[len] = '\0';
+ irg_name(name);
+
+ case tok_irgldname:
+ token = get_token();
+ if (token != tok_identifier)
+ goto error;
+ len = MIN(lexer.len, 1023);
+ strncpy(name, lexer.s, len);
+ name[len] = '\0';
+ irg_ld_name(name);
+ break;
+
+ case tok_help:
+ show_commands();
+ break;
+
+ case tok_error:
+ default:
+error:
+ printf("Error: before %s\n", lexer.tok_start);
+ show_commands();
+ goto leave;
+ }
+
+ token = get_token();
+ if (token == tok_eof)
+ break;
+ if (token != ';')
+ goto error;
+ }
+leave:
+ ;