// processes an incoming byte in the midi state machine void midi_msg_proc(uint8_t b) { bool is_status = ((b & 0x80) != 0); // handle status byte if (is_status) { if (is_realtime(b)) { // real-time, no data, process immediately msg_handle_fn(b, NULL, 0); } else { // non real-time idx = 0; len = get_len(b); status = b; if (len == 0) { // no data, process immediately msg_handle_fn(status, NULL, len); status = next_status(status); } } return; } // handle data byte if ((status > 0) && (len > 0)) { if (idx < len) { // store data byte data[idx++] = b; if (idx == len) { idx = 0; // process it msg_handle_fn(status, data, len); // prepare for next message status = next_status(status); } } else { // overrun, should never happen } } else { // unexpected data, ignore it } }
int tokenize(struct token_list* tk_list, char* file_buffer) { enum Status status; line_num; size_t token_begin, token_end; token_begin = 0, token_end = 0; status = STATUS_INVALID; str_toupper(file_buffer); /* * Careful: it seems an error to let "i <= len", * but we need one more execution to flush the last token into token list. */ size_t line_num = 1; for (size_t i = 0; ; ++i) { struct token_node* tok_node; switch (status) { case STATUS_LETTER: if (!IS_LETTER(file_buffer[i]) && !IS_DIGIT(file_buffer[i])) { token_end = i; tok_node = create_token(TOKEN_LABEL, file_buffer + token_begin, token_end - token_begin); tok_node->type = letter_type(tok_node->liter, tok_node->len); token_append(tk_list, tok_node); token_begin = i; status = next_status(status, file_buffer[i]); } break; case STATUS_PRAGMA: if (!IS_LETTER(file_buffer[i])) { int type; token_end = i; type = pragma_type(file_buffer + token_begin, token_end - token_begin); if (type < 0) { error("invalid pragma ad line %d\n", line_num); return -4; } tok_node = create_token(type, file_buffer + token_begin, token_end - token_begin); token_append(tk_list, tok_node); token_begin = i; status = next_status(status, file_buffer[i]); } break; case STATUS_PUNCTUATION: token_end = i; tok_node = create_token(file_buffer[token_begin], file_buffer + token_begin, token_end - token_begin); token_append(tk_list, tok_node); token_begin = i; status = next_status(status, file_buffer[i]); break; case STATUS_NUMBER: if (!IS_NUMBER(file_buffer[i])) { token_end = i; if (!check_number(file_buffer + token_begin, token_end - token_begin)) { error("invalid number format at line %d\n", line_num); return -2; } tok_node = create_token(TOKEN_NUMBER, file_buffer + token_begin, token_end - token_begin); tok_node->data = parse_number(tok_node->liter); token_append(tk_list, tok_node); token_begin = i; status = next_status(status, file_buffer[i]); } break; case STATUS_BLANK: if (!IS_BLANK(file_buffer[i])) { token_begin = i; status = next_status(status, file_buffer[i]); } break; case STATUS_COMMENTS: //once status is in comments, it will always be in comments if ('\n' == file_buffer[i]) { token_begin = i; status = next_status(status, file_buffer[i]); } break; case STATUS_INVALID: token_begin = i; status = next_status(status, file_buffer[i]); if (STATUS_INVALID == status && 0 != file_buffer[i]) { error("invalid format at line %d\n", line_num); return -3; } break; } if (0 == file_buffer[i]) break; else if ('\n' == file_buffer[i]) ++line_num; } return 0; }