Ejemplo n.º 1
0
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;
    }
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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);
  }
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
static BtorNode *
parse_sdiv (BtorBTORParser * parser, int len)
{
  return parse_binary (parser, len, btor_sdiv_exp);
}
Ejemplo n.º 6
0
static BtorNode *
parse_nand (BtorBTORParser * parser, int len)
{
  return parse_binary (parser, len, btor_nand_exp);
}
Ejemplo n.º 7
0
static BtorNode *
parse_urem (BtorBTORParser * parser, int len)
{
  return parse_binary (parser, len, btor_urem_exp);
}
Ejemplo n.º 8
0
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
}
Ejemplo n.º 9
0
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
}
Ejemplo n.º 10
0
/**
 * 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
}
Ejemplo n.º 11
0
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
}
Ejemplo n.º 12
0
/**
 * 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;
}