static int rd_factor (const char **p, int *valid, int level, int *check, int print_errors) { /* read a factor of an expression */ int result; if (verbose >= 6) fprintf (stderr, "%5d (0x%04x): Starting to read factor (string=%s).\n", stack[sp].line, addr, *p); result = rd_value (p, valid, level, check, print_errors); *p = delspc (*p); while (**p == '*' || **p == '/') { *check = 0; if (**p == '*') { (*p)++; result *= rd_value (p, valid, level, check, print_errors); } else if (**p == '/') { (*p)++; result /= rd_value (p, valid, level, check, print_errors); } *p = delspc (*p); } if (verbose >= 7) fprintf (stderr, "%5d (0x%04x): rd_factor returned %d (%04x).\n", stack[sp].line, addr, result, result); return result; }
Status BinCommon::rd_parms_vlst(CommandInitiator* thread, uint offset, va_list parms) { const Field* b = m_fields; uchar token = 0; uint tag = 0; uint prev_tag = 0; bool peek = true; uint unkown_tags_limit = 30; if (m_depth++ > DEPTH_LIMIT) return ERR_DECODE; const Field* f = &b[offset]; const Field* e = &b[f->get_end()]; // message descriptor ended while (f != e) { if (peek) { if (rd_uchar(thread, token) != OK) return ERR_DECODE; if (token != 'z') { if (token == 'N') { if (rd_uchar(thread, token) != OK && token != 'z') return ERR_DECODE; return ERR_CALL; } if (rd_value(thread, tag) != OK || tag < prev_tag) return ERR_DECODE; prev_tag = tag; } } if (token == 'z') { // we shall reset all remaining fields f->set_field_to_default(va_arg(parms, void*)); peek = false; // no more to read... } else if (tag == f->get_tag()) {
Status BinCommon::rd_value(CommandInitiator* thread, int& val) { uint uval; Status status = rd_value(thread, uval); if (status == OK) val = (uval >> 1) ^ -static_cast<int>(uval & 1); return status; }
Status BinCommon::rd_value(CommandInitiator* thread, Binary& value) { uint size; Status status = rd_value(thread, size); if (status == OK) { if (size > 0) { // protect from unrealistic size? value.reserve(size); status = rd_bytes(thread, size, (char*) value.data()); } } return status; }
Status BinCommon::rd_value(CommandInitiator* thread, String& value) { uint size; Status status = rd_value(thread, size); if (status == OK && size > 0) { value = String(size+1); if ((status = rd_bytes(thread, size, (char*)value.data())) != OK) return status; ((char*)value.data())[size]=0; } else { value = String(); } return status; }
Status BinCommon::rd_list(CommandInitiator* thread, void* dst_value, uint offset) { const Field* b = m_fields; const Field* f = b+offset; uint size = 0; // currently the protocol doesn't provide list size f->set_field_to_default(dst_value); //f->reserve(dst_value, size); char kind = (char)f->kind(); void* elem; uchar token; while (rd_uchar(thread, token) == OK) { if (token == ']') return OK; if (token == kind || (kind == 'b' && (token == 'T' || token == 'F'))) { f->append(dst_value, size++, elem); if (rd_value(token, thread, elem, offset) != OK) return ERR_DECODE; } else break; } return ERR_DECODE; }
Status BinCommon::rd_property(CommandInitiator* thread, uint& mid, uint& oid, uint& property, uchar& kind) { uchar token; // printf("m_begin_property %d\n", m_begin_property); if (!m_begin_property) { if (rd_value(thread, m_mod_property) != Protocol::OK) goto lost_connection; if (rd_value(thread, m_obj_property) != Protocol::OK) goto lost_connection; if (rd_uchar(thread, kind) != Protocol::OK) goto lost_connection; if (rd_value(thread, property) != Protocol::OK) goto lost_connection; } else { if (rd_uchar(thread, token) != Protocol::OK) goto lost_connection; if (token == ']') { if (rd_uchar(thread, token) != Protocol::OK) goto lost_connection; if (token == ',') { //continue if (rd_value(thread, m_obj_property) != Protocol::OK) goto lost_connection; if (rd_uchar(thread, kind) != Protocol::OK) goto lost_connection; if (rd_value(thread, property) != Protocol::OK) goto lost_connection; } else if (token == ']') { m_begin_property = 0; if (rd_uchar(thread, token) != Protocol::OK) goto lost_connection; if (token == ']') { rd_uchar(thread, token); //z if (m_buffering < 0) m_buffering = 0; m_transport->end_decoding(thread); return Protocol::COMPLETED; } else if (token == ',') { return rd_property(thread, mid, oid, property, kind); } } goto lost_connection; } else { kind = token; if (rd_value(thread, property) != Protocol::OK) goto lost_connection; } } m_begin_property++; mid = m_mod_property; oid = m_obj_property; return Protocol::OK; lost_connection: m_begin_property = 0; return Protocol::ERR_DECODE; }
Status BinCommon::rd_uint(CommandInitiator* thread, void* val, uint) { return rd_value(thread, *static_cast<uint*>(val)); }
Status BinCommon::rd_binary(CommandInitiator* thread, void* value, uint) { return rd_value(thread, *static_cast<Binary*>(value)); }
Status BinCommon::rd_string(CommandInitiator* thread, void* value, uint) { return rd_value(thread, *static_cast<String*>(value)); }
Status BinCommon::rd_filename(CommandInitiator* thread, void* value, uint) { return rd_value(thread, *static_cast<Filename*>(value)); }
Status BinCommon::rd_message(CommandInitiator* thread, void* message_received, uint offset) { uchar token = 0; uint tag = 0; uint prev_tag = 0; bool peek = true; uint unkown_tags_limit = 30; if (m_depth++ > DEPTH_LIMIT) return ERR_DECODE; const Field* b = m_fields; const Field* f = &b[offset]; const Field* e = &b[f->get_end()]; // message descriptor ended while (f != e) { if (peek) { if (rd_uchar(thread, token) != OK) return ERR_DECODE; if (token != 'z') { if (token == 'N') { if (rd_uchar(thread, token) != OK && token != 'z') return ERR_DECODE; return ERR_CALL; } if (rd_value(thread, tag) != OK || tag < prev_tag) return ERR_DECODE; prev_tag = tag; } } if (token == 'z') { // we shall reset all remaining fields f->set_to_default(message_received); peek = false; // no more to read... } else if (tag == f->get_tag()) { // check that type in message matches the field type flag // (except for boolean, as no type flag is given but value is immediately given) if (!(token == f->kind() || (f->kind() == 'b' && (token == 'F' || token == 'T')) || (f->is_list() && token == '[') ) ) return ERR_DECODE; if (rd_value(token, thread, f->offset(message_received), f-m_fields) != OK) return ERR_DECODE; peek = true; } else { // tag is unknown: skip the value peek = tag < f->get_tag(); if (peek) { if (unkown_tags_limit-- == 0 || sk_value(token, thread) != OK) return ERR_DECODE; continue; // keep current field } f->set_to_default(message_received); } // goto next field... f = f->next(); } while (token != 'z') { if (rd_uchar(thread, token) != OK) return ERR_DECODE; if (token != 'z') { if (token == 'N') { if (rd_uchar(thread, token) != OK && token != 'z') return ERR_DECODE; return ERR_CALL; } if (rd_value(thread, tag) != OK || tag < prev_tag) return ERR_DECODE; prev_tag = tag; if (unkown_tags_limit-- == 0 || sk_value(token, thread) != OK) return ERR_DECODE; } } m_depth--; return OK; }