static struct AstNode *parse_special( struct DomNode *dom, struct ParserState *state) { struct AstNode *result; if ((!err_state() && (result = parse_do_block(dom, state))) || (!err_state() && (result = parse_match(dom, state))) || (!err_state() && (result = parse_if(dom, state))) || (!err_state() && (result = parse_while(dom, state))) || (!err_state() && (result = parse_func_def(dom, state))) || (!err_state() && (result = parse_min_nary(dom, 1, DOM_RES_AND, ast_make_spec_bool_and, state))) || (!err_state() && (result = parse_min_nary(dom, 1, DOM_RES_OR, ast_make_spec_bool_or, state))) || (!err_state() && (result = parse_min_nary(dom, 1, DOM_RES_SET_OF, ast_make_spec_set_of, state))) || (!err_state() && (result = parse_binary(dom, DOM_RES_RANGE_OF, ast_make_spec_range_of, state))) || (!err_state() && (result = parse_unary(dom, DOM_RES_ARRAY_OF, ast_make_spec_array_of, state))) || (!err_state() && (result = parse_min_nary(dom, 1, DOM_RES_TUPLE_OF, ast_make_spec_tuple_of, state))) || (!err_state() && (result = parse_unary(dom, DOM_RES_POINTER_TO, ast_make_spec_pointer_to, state))) || (!err_state() && (result = parse_min_nary(dom, 1, DOM_RES_FUNCTION, ast_make_spec_function_type, state))) || (!err_state() && (result = parse_unary(dom, DOM_RES_TYPE_PRODUCT, ast_make_spec_type_product, state))) || (!err_state() && (result = parse_unary(dom, DOM_RES_TYPE_UNION, ast_make_spec_type_union, state))) || (!err_state() && (result = parse_bind(dom, state))) || (!err_state() && (result = parse_unary(dom, DOM_RES_PTR, ast_make_spec_ptr, state))) || (!err_state() && (result = parse_unary(dom, DOM_RES_PEEK, ast_make_spec_peek, state))) || (!err_state() && (result = parse_binary(dom, DOM_RES_POKE, ast_make_spec_poke, state))) || (!err_state() && (result = parse_unary(dom, DOM_RES_BEGIN, ast_make_spec_begin, state))) || (!err_state() && (result = parse_unary(dom, DOM_RES_END, ast_make_spec_end, state))) || (!err_state() && (result = parse_unary(dom, DOM_RES_INC, ast_make_spec_inc, state))) || (!err_state() && (result = parse_unary(dom, DOM_RES_SUCC, ast_make_spec_succ, state)))) { return result; } else { return NULL; } }
int test_to_uns(testspec_t *t, FILE *ofp) { mp_int in[1]; int test_len, out_len; mp_result res; if(!parse_int_values(t, in, NULL, NULL)) return imath_errno = MP_BADARG, 0; trim_line(t->output[0]); if((out_len = parse_binary(t->output[0], g_bin1, sizeof(g_bin1))) < 0) return imath_errno = MP_BADARG, 0; if((test_len = mp_int_unsigned_len(in[0])) != out_len) { sprintf(g_output, "Output lengths do not match (want %d, got %d)", test_len, out_len); return imath_errno = OTHER_ERROR, 0; } if((res = mp_int_to_unsigned(in[0], g_bin2, sizeof(g_bin2))) != MP_OK) return imath_errno = res, 0; if(memcmp(g_bin1, g_bin2, test_len) != 0) { int pos = 0, i; for(i = 0; i < test_len - 1; ++i) pos += sprintf(g_output + pos, "%d.", g_bin2[i]); sprintf(g_output + pos, "%d", g_bin2[i]); return imath_errno = OTHER_ERROR, 0; } return 1; }
void change_c::parse_value() { switch (m_property.m_type) { case property_element_c::EBMLT_STRING: parse_ascii_string(); break; case property_element_c::EBMLT_USTRING: parse_unicode_string(); break; case property_element_c::EBMLT_UINT: parse_unsigned_integer(); break; case property_element_c::EBMLT_INT: parse_signed_integer(); break; case property_element_c::EBMLT_BOOL: parse_boolean(); break; case property_element_c::EBMLT_BINARY: parse_binary(); break; case property_element_c::EBMLT_FLOAT: parse_floating_point_number(); break; default: assert(false); } }
int test_read_uns(testspec_t *t, FILE *ofp) { mp_int out[1], in = g_zreg + 1; int in_len; mp_result res, expect; if(!parse_int_values(t, NULL, out, &expect)) return imath_errno = MP_BADARG, 0; trim_line(t->input[0]); if((in_len = parse_binary(t->input[0], g_bin1, sizeof(g_bin1))) < 0) return imath_errno = MP_BADARG, 0; if((res = mp_int_read_unsigned(in, g_bin1, in_len)) != expect) return imath_errno = res, 0; if(expect == MP_OK && mp_int_compare(in, out[0]) != 0) { mp_int_to_string(in, 10, g_output, OUTPUT_LIMIT); return imath_errno = OTHER_ERROR, 0; } return 1; }
static BtorNode * parse_sdiv (BtorBTORParser * parser, int len) { return parse_binary (parser, len, btor_sdiv_exp); }
static BtorNode * parse_nand (BtorBTORParser * parser, int len) { return parse_binary (parser, len, btor_nand_exp); }
static BtorNode * parse_urem (BtorBTORParser * parser, int len) { return parse_binary (parser, len, btor_urem_exp); }
static inline #endif PsycParseUpdateRC psyc_parse_update (PsycParseUpdateState *state, char *oper, PsycString *value) { PsycParseIndexRC ret; if (state->cursor >= state->buffer.length) return PSYC_PARSE_UPDATE_END; state->startc = state->cursor; switch (state->part) { case PSYC_UPDATE_PART_START: value->length = 0; value->data = NULL; // fall thru case PSYC_INDEX_PART_TYPE: case PSYC_INDEX_PART_LIST: case PSYC_INDEX_PART_STRUCT: case PSYC_INDEX_PART_DICT_LENGTH: case PSYC_INDEX_PART_DICT: ret = psyc_parse_index((PsycParseIndexState*)state, value); switch (ret) { case PSYC_PARSE_INDEX_INSUFFICIENT: case PSYC_PARSE_INDEX_LIST_LAST: case PSYC_PARSE_INDEX_STRUCT_LAST: case PSYC_PARSE_INDEX_END: return PSYC_PARSE_UPDATE_INSUFFICIENT; case PSYC_PARSE_INDEX_ERROR_TYPE: if (state->buffer.data[state->cursor] != ' ') return ret; state->part = PSYC_PARSE_UPDATE_TYPE; value->length = 0; value->data = NULL; ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_UPDATE_INSUFFICIENT); break; default: return ret; } case PSYC_UPDATE_PART_TYPE: if (!psyc_is_oper(state->buffer.data[state->cursor])) return PSYC_PARSE_UPDATE_ERROR_OPER; *oper = state->buffer.data[state->cursor]; ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_UPDATE_END); switch (parse_keyword((ParseState*)state, value)) { case PARSE_SUCCESS: // end of keyword case PARSE_ERROR: // no keyword switch (state->buffer.data[state->cursor]) { case ':': state->part = PSYC_UPDATE_PART_LENGTH; break; case ' ': state->part = PSYC_UPDATE_PART_VALUE; break; default: return PSYC_PARSE_UPDATE_ERROR_TYPE; } state->cursor++; return PSYC_PARSE_UPDATE_TYPE; break; case PARSE_INSUFFICIENT: // end of buffer return PSYC_PARSE_UPDATE_TYPE_END; default: // should not be reached return PSYC_PARSE_UPDATE_ERROR; } break; case PSYC_UPDATE_PART_LENGTH: switch (parse_length((ParseState*)state, &state->elemlen)) { case PARSE_SUCCESS: // length is complete state->elemlen_found = 1; state->elem_parsed = 0; value->length = state->elemlen; value->data = NULL; if (state->buffer.data[state->cursor] != ' ') return PSYC_PARSE_UPDATE_ERROR_LENGTH; state->part = PSYC_UPDATE_PART_VALUE; if (value->length == 0) return PSYC_PARSE_UPDATE_END; ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_UPDATE_INSUFFICIENT); break; case PARSE_INSUFFICIENT: // length is incomplete if (value->length == 0) return PSYC_PARSE_UPDATE_END; return PSYC_PARSE_UPDATE_INSUFFICIENT; case PARSE_ERROR: // no length after : return PSYC_PARSE_UPDATE_ERROR_LENGTH; default: // should not be reached return PSYC_PARSE_UPDATE_ERROR; } // fall thru case PSYC_UPDATE_PART_VALUE: if (state->elemlen_found) { switch (parse_binary((ParseState*)state, state->elemlen, value, &state->elem_parsed)) { case PARSE_SUCCESS: if (value->length == state->elem_parsed) ret = PSYC_PARSE_UPDATE_VALUE; else ret = PSYC_PARSE_UPDATE_VALUE_END; break; case PARSE_INCOMPLETE: if (value->length == state->elem_parsed) ret = PSYC_PARSE_UPDATE_VALUE_START; else ret = PSYC_PARSE_UPDATE_VALUE_CONT; break; default: // should not be reached return PSYC_PARSE_UPDATE_ERROR_VALUE; } } else { value->data = state->buffer.data + state->cursor; value->length = state->buffer.length - state->cursor; ret = PSYC_PARSE_UPDATE_VALUE; } state->part = PSYC_INDEX_PART_TYPE; state->cursor++; return ret; } return PSYC_PARSE_INDEX_ERROR; // should not be reached }
static inline #endif PsycParseIndexRC psyc_parse_index (PsycParseIndexState *state, PsycString *idx) { ParseRC ret; if (state->cursor >= state->buffer.length) return PSYC_PARSE_INDEX_END; state->startc = state->cursor; switch (state->part) { case PSYC_INDEX_PART_START: case PSYC_INDEX_PART_TYPE: idx->length = 0; idx->data = NULL; switch (state->buffer.data[state->cursor]) { case '#': state->part = PSYC_INDEX_PART_LIST; ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_INSUFFICIENT); goto PSYC_INDEX_PART_LIST; case '.': state->part = PSYC_INDEX_PART_DICT; ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_INSUFFICIENT); goto PSYC_INDEX_PART_STRUCT; case '{': state->part = PSYC_INDEX_PART_DICT; ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_INSUFFICIENT); goto PSYC_INDEX_PART_DICT_LENGTH; default: return PSYC_PARSE_INDEX_ERROR_TYPE; } case PSYC_INDEX_PART_LIST: PSYC_INDEX_PART_LIST: switch (parse_length((ParseState*)state, &idx->length)) { case PARSE_SUCCESS: // list index is complete state->part = PSYC_INDEX_PART_TYPE; return PSYC_PARSE_INDEX_LIST; case PARSE_INSUFFICIENT: // list index at the end of buffer return PSYC_PARSE_INDEX_LIST_LAST; case PARSE_ERROR: // no index return PSYC_PARSE_INDEX_ERROR_LIST; default: // should not be reached return PSYC_PARSE_INDEX_ERROR; } case PSYC_INDEX_PART_STRUCT: PSYC_INDEX_PART_STRUCT: switch (parse_keyword((ParseState*)state, idx)) { case PARSE_SUCCESS: // end of keyword state->part = PSYC_INDEX_PART_TYPE; return PSYC_PARSE_INDEX_STRUCT; case PARSE_INSUFFICIENT: // end of buffer return PSYC_PARSE_INDEX_STRUCT_LAST; case PARSE_ERROR: // no keyword return PSYC_PARSE_INDEX_ERROR_STRUCT; default: // should not be reached return PSYC_PARSE_INDEX_ERROR; } case PSYC_INDEX_PART_DICT_LENGTH: PSYC_INDEX_PART_DICT_LENGTH: switch (parse_length((ParseState*)state, &state->elemlen)) { case PARSE_SUCCESS: // length is complete state->elemlen_found = 1; state->elem_parsed = 0; idx->length = state->elemlen; idx->data = NULL; if (state->buffer.data[state->cursor] != ' ') return PSYC_PARSE_INDEX_ERROR_DICT_LENGTH; state->part = PSYC_INDEX_PART_DICT; ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_INSUFFICIENT); break; case PARSE_INSUFFICIENT: // length is incomplete return PSYC_PARSE_DICT_INSUFFICIENT; case PARSE_ERROR: // no length state->part = PSYC_INDEX_PART_DICT; break; default: // should not be reached return PSYC_PARSE_INDEX_ERROR; } // fall thru case PSYC_INDEX_PART_DICT: if (state->elemlen_found) { switch (parse_binary((ParseState*)state, state->elemlen, idx, &state->elem_parsed)) { case PARSE_SUCCESS: if (idx->length == state->elem_parsed) ret = PSYC_PARSE_INDEX_DICT; else ret = PSYC_PARSE_INDEX_DICT_END; break; case PARSE_INCOMPLETE: if (idx->length == state->elem_parsed) ret = PSYC_PARSE_INDEX_DICT_START; else ret = PSYC_PARSE_INDEX_DICT_CONT; break; default: // should not be reached return PSYC_PARSE_INDEX_ERROR_DICT; } } else { switch (parse_until((ParseState*)state, '}', idx)) { case PARSE_SUCCESS: ret = PSYC_PARSE_INDEX_DICT; break; case PARSE_INSUFFICIENT: return PSYC_PARSE_INDEX_INSUFFICIENT; default: // should not be reached return PSYC_PARSE_INDEX_ERROR_DICT; } } state->part = PSYC_INDEX_PART_TYPE; state->cursor++; return ret; } return PSYC_PARSE_INDEX_ERROR; // should not be reached }
/** * Parse dictionary. * * dict = [ type ] *dict-item * dict-item = "{" ( dict-key / length SP OCTET) "}" * ( type [ SP dict-value ] / [ length ] [ ":" type ] [ SP *OCTET ] ) * dict-key = %x00-7C / %x7E-FF ; any byte except "{" * dict-value = %x00-7A / %x7C-FF ; any byte except "}" */ PsycParseDictRC psyc_parse_dict (PsycParseDictState *state, PsycString *type, PsycString *elem) { ParseRC ret; if (state->cursor >= state->buffer.length) return PSYC_PARSE_DICT_END; state->startc = state->cursor; switch (state->part) { case PSYC_DICT_PART_START: type->length = elem->length = 0; type->data = elem->data = NULL; state->part = PSYC_DICT_PART_TYPE; // fall thru case PSYC_DICT_PART_TYPE: switch (parse_keyword((ParseState*)state, type)) { case PARSE_SUCCESS: // end of keyword state->part = PSYC_DICT_PART_KEY_START; return PSYC_PARSE_DICT_TYPE; case PARSE_INSUFFICIENT: // end of buffer return PSYC_PARSE_DICT_END; case PARSE_ERROR: // no keyword state->part = PSYC_DICT_PART_KEY_START; break; default: // should not be reached return PSYC_PARSE_DICT_ERROR; } // fall thru case PSYC_DICT_PART_KEY_START: if (state->buffer.data[state->cursor] != '{') return PSYC_PARSE_DICT_ERROR_KEY_START; type->length = elem->length = 0; type->data = elem->data = NULL; state->elem_parsed = 0; state->elemlen_found = 0; state->part = PSYC_DICT_PART_KEY_LENGTH; ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_DICT_INSUFFICIENT); // fall thru case PSYC_DICT_PART_KEY_LENGTH: switch (parse_length((ParseState*)state, &state->elemlen)) { case PARSE_SUCCESS: // length is complete state->elemlen_found = 1; state->elem_parsed = 0; elem->length = state->elemlen; elem->data = NULL; if (state->buffer.data[state->cursor] != ' ') return PSYC_PARSE_DICT_ERROR_KEY_LENGTH; state->part = PSYC_DICT_PART_KEY; ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_INSUFFICIENT); break; case PARSE_INSUFFICIENT: // length is incomplete return PSYC_PARSE_DICT_INSUFFICIENT; case PARSE_ERROR: // no length state->part = PSYC_DICT_PART_KEY; break; default: // should not be reached return PSYC_PARSE_DICT_ERROR; } // fall thru case PSYC_DICT_PART_KEY: if (state->elemlen_found) { switch (parse_binary((ParseState*)state, state->elemlen, elem, &state->elem_parsed)) { case PARSE_SUCCESS: if (elem->length == state->elem_parsed) ret = PSYC_PARSE_DICT_KEY; else ret = PSYC_PARSE_DICT_KEY_END; break; case PARSE_INCOMPLETE: if (elem->length == state->elem_parsed) ret = PSYC_PARSE_DICT_KEY_START; else ret = PSYC_PARSE_DICT_KEY_CONT; break; default: // should not be reached return PSYC_PARSE_DICT_ERROR; } } else { switch (parse_until((ParseState*)state, '}', elem)) { case PARSE_SUCCESS: ret = PSYC_PARSE_DICT_KEY; break; case PARSE_INSUFFICIENT: return PSYC_PARSE_DICT_INSUFFICIENT; default: // should not be reached return PSYC_PARSE_DICT_ERROR; } } state->part = PSYC_DICT_PART_VALUE_START; state->startc = state->cursor; return ret; case PSYC_DICT_PART_VALUE_START: switch (state->buffer.data[state->cursor] != '}') return PSYC_PARSE_DICT_ERROR_VALUE_START; type->length = elem->length = 0; type->data = elem->data = NULL; state->elem_parsed = 0; state->elemlen_found = 0; state->part = PSYC_DICT_PART_VALUE_TYPE; ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_DICT_VALUE_LAST); // fall thru case PSYC_DICT_PART_VALUE_TYPE: if (state->buffer.data[state->cursor] == '=') { ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); switch (parse_keyword((ParseState*)state, type)) { case PARSE_SUCCESS: switch (state->buffer.data[state->cursor]) { case ':': state->part = PSYC_DICT_PART_VALUE_LENGTH; ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_DICT_VALUE_LAST); break; case ' ': state->part = PSYC_DICT_PART_VALUE; ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_DICT_VALUE_LAST); goto PSYC_DICT_PART_VALUE; case '{': state->part = PSYC_DICT_PART_KEY_START; return PSYC_PARSE_DICT_VALUE; break; default: return PSYC_PARSE_DICT_ERROR_VALUE_TYPE; } break; case PARSE_INSUFFICIENT: // end of buffer return PSYC_PARSE_DICT_VALUE_LAST; case PARSE_ERROR: return PSYC_PARSE_DICT_ERROR_VALUE_TYPE; default: // should not be reached return PSYC_PARSE_DICT_ERROR; } } // fall thru case PSYC_DICT_PART_VALUE_LENGTH: switch (parse_length((ParseState*)state, &state->elemlen)) { case PARSE_SUCCESS: // length is complete state->elemlen_found = 1; state->elem_parsed = 0; elem->length = state->elemlen; elem->data = NULL; break; case PARSE_INSUFFICIENT: // length is incomplete return PSYC_PARSE_DICT_INSUFFICIENT; case PARSE_ERROR: // no length break; default: // should not be reached return PSYC_PARSE_DICT_ERROR; } switch (state->buffer.data[state->cursor]) { case ' ': state->part = PSYC_DICT_PART_VALUE; ADVANCE_STARTC_OR_RETURN(PSYC_PARSE_DICT_VALUE_LAST); break; case '{': state->part = PSYC_DICT_PART_KEY_START; return PSYC_PARSE_DICT_VALUE; default: return PSYC_PARSE_DICT_ERROR_VALUE_LENGTH; } // fall thru case PSYC_DICT_PART_VALUE: PSYC_DICT_PART_VALUE: if (state->elemlen_found) { switch (parse_binary((ParseState*)state, state->elemlen, elem, &state->elem_parsed)) { case PARSE_SUCCESS: if (elem->length == state->elem_parsed) ret = PSYC_PARSE_DICT_VALUE; else ret = PSYC_PARSE_DICT_VALUE_END; break; case PARSE_INCOMPLETE: if (elem->length == state->elem_parsed) ret = PSYC_PARSE_DICT_VALUE_START; else ret = PSYC_PARSE_DICT_VALUE_CONT; break; default: // should not be reached return PSYC_PARSE_DICT_ERROR; } } else { switch (parse_until((ParseState*)state, '{', elem)) { case PARSE_SUCCESS: ret = PSYC_PARSE_DICT_VALUE; break; case PARSE_INSUFFICIENT: return PSYC_PARSE_DICT_VALUE_LAST; default: // should not be reached return PSYC_PARSE_DICT_ERROR; } } state->part = PSYC_DICT_PART_KEY_START; return ret; } return PSYC_PARSE_DICT_ERROR; // should not be reached }
static inline #endif PsycParseRC psyc_parse (PsycParseState *state, char *oper, PsycString *name, PsycString *value) { #ifdef DEBUG if (state->flags & PSYC_PARSE_ROUTING_ONLY && state->flags & PSYC_PARSE_START_AT_CONTENT) PP(("Invalid flag combination")); #endif ParseRC ret; // a return value size_t pos = state->cursor; // a cursor position // Start position of the current line in the buffer // in case we return insufficent, we rewind to this position. state->startc = state->cursor; if (state->flags & PSYC_PARSE_START_AT_CONTENT && (state->buffer.length == 0 || state->cursor >= state->buffer.length - 1)) return PSYC_PARSE_COMPLETE; // First we test if we can access the first char. if (state->cursor >= state->buffer.length) // Cursor is not inside the length. return PSYC_PARSE_INSUFFICIENT; switch (state->part) { case PSYC_PART_RESET: // New packet starts here, reset state. state->value_parsed = 0; state->valuelen = 0; state->valuelen_found = 0; state->routinglen = 0; state->content_parsed = 0; state->contentlen = 0; state->contentlen_found = 0; state->part = PSYC_PART_ROUTING; // fall thru case PSYC_PART_ROUTING: if (state->routinglen > 0) { if (state->buffer.data[state->cursor] != '\n') return PSYC_PARSE_ERROR_MOD_NL; ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); } // Each line of the header starts with a glyph, // i.e. :_name, -_name +_name etc, // so just test if the first char is a glyph. if (psyc_is_oper(state->buffer.data[state->cursor])) { // it is a glyph, so a variable starts here ret = psyc_parse_modifier(state, oper, name, value); state->routinglen += state->cursor - pos; return ret == PARSE_SUCCESS ? PSYC_PARSE_ROUTING : ret; } else { // not a glyph state->part = PSYC_PART_LENGTH; state->startc = state->cursor; // fall thru } case PSYC_PART_LENGTH: // End of header, content starts with an optional length then a NL if (psyc_is_numeric(state->buffer.data[state->cursor])) { state->contentlen_found = 1; state->contentlen = 0; do { state->contentlen = 10 * state->contentlen + state->buffer.data[state->cursor] - '0'; ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); } while (psyc_is_numeric(state->buffer.data[state->cursor])); } if (state->buffer.data[state->cursor] == '\n') { // start of content // If we need to parse the header only and we know the content length, // then skip content parsing. if (state->flags & PSYC_PARSE_ROUTING_ONLY) { state->part = PSYC_PART_DATA; if (++(state->cursor) >= state->buffer.length) return PSYC_PARSE_INSUFFICIENT; goto PSYC_PART_DATA; } else state->part = PSYC_PART_CONTENT; } else { // Not start of content, this must be the end. // If we have a length then it should've been followed by a \n if (state->contentlen_found) return PSYC_PARSE_ERROR_LENGTH; state->part = PSYC_PART_END; goto PSYC_PART_END; } state->startc = state->cursor + 1; ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); // fall thru case PSYC_PART_CONTENT: // In case of an incomplete binary variable resume parsing it. if (state->value_parsed < state->valuelen) { ret = parse_binary((ParseState*)state, state->valuelen, value, &state->value_parsed); state->content_parsed += value->length; if (ret == PARSE_INCOMPLETE) return PSYC_PARSE_ENTITY_CONT; return PSYC_PARSE_ENTITY_END; } pos = state->cursor; if (state->content_parsed > 0) { if (state->buffer.data[state->cursor] != '\n') return PSYC_PARSE_ERROR_MOD_NL; ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); } // Each line of the header starts with a glyph, // i.e. :_name, -_name +_name etc. // So just test if the first char is a glyph. // In the body, the same applies, only that the // method does not start with a glyph. if (psyc_is_oper(state->buffer.data[state->cursor])) { if (state->content_parsed == 0) { ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); if (state->buffer.data[state->cursor] == '\n') { *oper = *(state->buffer.data + state->cursor - 1); switch (*oper) { case PSYC_STATE_RESYNC: state->content_parsed++; return PSYC_PARSE_STATE_RESYNC; case PSYC_STATE_RESET: state->content_parsed++; return PSYC_PARSE_STATE_RESET; default: return PSYC_PARSE_ERROR_MOD_NAME; } } state->cursor--; } ret = psyc_parse_modifier(state, oper, name, value); state->content_parsed += state->cursor - pos; if (ret == PARSE_INCOMPLETE) return PSYC_PARSE_ENTITY_START; else if (ret == PARSE_SUCCESS) return PSYC_PARSE_ENTITY; return ret; } else { state->content_parsed += state->cursor - pos; state->startc = state->cursor; state->part = PSYC_PART_METHOD; // fall thru } case PSYC_PART_METHOD: pos = state->cursor; ret = parse_keyword((ParseState*)state, name); if (ret == PARSE_INSUFFICIENT) return ret; else if (ret == PARSE_SUCCESS) { // The method ends with a \n then the data follows. if (state->buffer.data[state->cursor] != '\n') return PSYC_PARSE_ERROR_METHOD; state->valuelen_found = 0; state->value_parsed = 0; state->valuelen = 0; if (state->contentlen_found) { // len found, set start position to the beginning of data. state->cursor++; state->startc = state->cursor; state->content_parsed += state->cursor - pos; state->part = PSYC_PART_DATA; } else { // Otherwise keep it at the beginning of method. ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); } } else { // No method, which means the packet should end now. state->part = PSYC_PART_END; state->startc = state->cursor; goto PSYC_PART_END; } // fall thru case PSYC_PART_DATA: PSYC_PART_DATA: value->data = state->buffer.data + state->cursor; value->length = 0; if (state->contentlen_found) { // We know the length of the packet. if (!state->valuelen_found) { // start of data state->valuelen_found = 1; state->valuelen = state->contentlen - state->content_parsed; if (state->valuelen && !(state->flags & PSYC_PARSE_ROUTING_ONLY)) state->valuelen--; // \n at the end is not part of data } if (state->value_parsed < state->valuelen) { ret = parse_binary((ParseState*)state, state->valuelen, value, &state->value_parsed); state->content_parsed += value->length; if (ret == PARSE_INCOMPLETE) return state->value_parsed == value->length ? PSYC_PARSE_BODY_START : PSYC_PARSE_BODY_CONT; } state->part = PSYC_PART_END; return state->valuelen == value->length ? PSYC_PARSE_BODY : PSYC_PARSE_BODY_END; } else { // Search for the terminator. size_t datac = state->cursor; // start of data if (state->flags & PSYC_PARSE_ROUTING_ONLY) // in routing-only mode restart state->startc = datac; // from the start of data while (1) { uint8_t nl = state->buffer.data[state->cursor] == '\n'; // check for |\n if we're at the start of data or we have found a \n if (state->cursor == datac || nl) { // incremented cursor inside length? if (state->cursor + 1 + nl >= state->buffer.length) { state->cursor = state->startc; return PSYC_PARSE_INSUFFICIENT; } if (state->buffer.data[state->cursor + nl] == '|' && state->buffer.data[state->cursor + 1 + nl] == '\n') { // packet ends here if (state->flags & PSYC_PARSE_ROUTING_ONLY) value->length++; state->content_parsed += state->cursor - pos; state->cursor += nl; state->part = PSYC_PART_END; return PSYC_PARSE_BODY; } } value->length++; ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); } } case PSYC_PART_END: PSYC_PART_END: // if data was not empty next is the \n at the end of data if (state->contentlen_found && state->valuelen_found && state->valuelen && !(state->flags & PSYC_PARSE_ROUTING_ONLY)) { state->valuelen = 0; state->valuelen_found = 0; if (state->buffer.data[state->cursor] != '\n') return PSYC_PARSE_ERROR_END; state->content_parsed++; state->cursor++; } // End of packet, at this point we have already passed a \n // and the cursor should point to | if (state->cursor + 1 >= state->buffer.length) return PSYC_PARSE_INSUFFICIENT; if (state->buffer.data[state->cursor] == '|' && state->buffer.data[state->cursor + 1] == '\n') { // Packet ends here. state->cursor += 2; state->part = PSYC_PART_RESET; return PSYC_PARSE_COMPLETE; } else { // Packet should've ended here, return error. state->part = PSYC_PART_RESET; return PSYC_PARSE_ERROR_END; } } return PSYC_PARSE_ERROR; // should not be reached }
/** * Parse simple or binary variable. * @return PARSE_ERROR or PARSE_SUCCESS */ static inline ParseRC psyc_parse_modifier (PsycParseState *state, char *oper, PsycString *name, PsycString *value) { *oper = *(state->buffer.data + state->cursor); ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); ParseRC ret = parse_keyword((ParseState*)state, name); if (ret == PARSE_ERROR) return PSYC_PARSE_ERROR_MOD_NAME; else if (ret != PARSE_SUCCESS) return ret; size_t length = 0; value->length = 0; state->valuelen = 0; state->valuelen_found = 0; state->value_parsed = 0; // Parse the value. // If we're in the content part check if it's a binary var. if (state->part == PSYC_PART_CONTENT && state->buffer.data[state->cursor] == ' ') { // binary arg // After SP the length follows. ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); if (psyc_is_numeric(state->buffer.data[state->cursor])) { state->valuelen_found = 1; do { length = 10 * length + state->buffer.data[state->cursor] - '0'; ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); } while (psyc_is_numeric(state->buffer.data[state->cursor])); state->valuelen = length; } else return PSYC_PARSE_ERROR_MOD_LEN; // After the length a TAB follows. if (state->buffer.data[state->cursor] != '\t') return PSYC_PARSE_ERROR_MOD_TAB; if (++(state->cursor) >= state->buffer.length) return length ? PARSE_INCOMPLETE : PARSE_SUCCESS; // if length=0 we're done ret = parse_binary((ParseState*)state, state->valuelen, value, &state->value_parsed); if (ret == PARSE_INCOMPLETE) return ret; return PARSE_SUCCESS; } else if (state->buffer.data[state->cursor] == '\t') { // simple arg ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); value->data = state->buffer.data + state->cursor; while (state->buffer.data[state->cursor] != '\n') { value->length++; ADVANCE_CURSOR_OR_RETURN(PSYC_PARSE_INSUFFICIENT); } return PARSE_SUCCESS; } else return PSYC_PARSE_ERROR_MOD_TAB; }