warning elimination reported by clang
[deliverable/titan.core.git] / core2 / Basetype2.cc
index 7a2114789412f9091b868161e65dc71cd52147b4..1ddac029f5783313b5f287a4906a5fc9638c986f 100644 (file)
@@ -1,10 +1,23 @@
-///////////////////////////////////////////////////////////////////////////////
-// Copyright (c) 2000-2014 Ericsson Telecom AB
-// All rights reserved. This program and the accompanying materials
-// are made available under the terms of the Eclipse Public License v1.0
-// which accompanies this distribution, and is available at
-// http://www.eclipse.org/legal/epl-v10.html
-///////////////////////////////////////////////////////////////////////////////
+/******************************************************************************
+ * Copyright (c) 2000-2016 Ericsson Telecom AB
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *   Baji, Laszlo
+ *   Balasko, Jeno
+ *   Baranyi, Botond
+ *   Beres, Szabolcs
+ *   Delic, Adam
+ *   Kovacs, Ferenc
+ *   Raduly, Csaba
+ *   Szabados, Kristof
+ *   Szabo, Bence Janos
+ *   Pandi, Krisztian
+ *
+ ******************************************************************************/
 #include "Basetype.hh"
 #include "TEXT.hh"
 #include "BER.hh"
@@ -21,6 +34,7 @@
 #include "Charstring.hh"
 #include "Universal_charstring.hh"
 #include "Addfunc.hh"
+#include "PreGenRecordOf.hh"
 
 ////////////////////////////////////////////////////////////////////////////////
 
@@ -175,10 +189,17 @@ int Base_Type::RAW_encode_negtest_raw(RAW_enc_tree&) const
   return 0;
 }
 
+int Base_Type::JSON_encode_negtest_raw(JSON_Tokenizer&) const
+{
+  TTCN_error("A value of type %s cannot be used as erroneous raw value for JSON encoding.",
+             get_descriptor()->name);
+  return 0;
+}
+
 int Base_Type::XER_encode_negtest(const Erroneous_descriptor_t* /*p_err_descr*/,
-  const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, unsigned int flavor, int indent) const
+  const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const
 {
-  return XER_encode(p_td, p_buf, flavor, indent); // ignore erroneous
+  return XER_encode(p_td, p_buf, flavor, indent, 0); // ignore erroneous
 }
 
 int Base_Type::RAW_encode_negtest(const Erroneous_descriptor_t *,
@@ -188,6 +209,13 @@ int Base_Type::RAW_encode_negtest(const Erroneous_descriptor_t *,
   return 0;
 }
 
+int Base_Type::JSON_encode_negtest(const Erroneous_descriptor_t* /*p_err_descr*/,
+  const TTCN_Typedescriptor_t& /*p_td*/, JSON_Tokenizer& /*p_tok*/) const
+{
+  TTCN_error("Internal error: calling Base_Type::JSON_encode_negtest().");
+  return 0;
+}
+
 #else
 #error this is for RT2 only
 #endif
@@ -225,7 +253,7 @@ void Record_Of_Type::clean_up()
       val_ptr = NULL;
     }
     else if (val_ptr->ref_count == 1) {
-      if (refd_indices.empty()) {
+      if (NULL == refd_ind_ptr) {
         for (int elem_count = 0; elem_count < val_ptr->n_elements; elem_count++) {
           if (val_ptr->value_elements[elem_count] != NULL) {
             delete val_ptr->value_elements[elem_count];
@@ -247,7 +275,7 @@ void Record_Of_Type::clean_up()
 }
 
 Record_Of_Type::Record_Of_Type(null_type /*other_value*/)
-: Base_Type(), val_ptr(new recordof_setof_struct), err_descr(NULL), max_refd_index(-1)
+: Base_Type(), val_ptr(new recordof_setof_struct), err_descr(NULL), refd_ind_ptr(NULL)
 {
   val_ptr->ref_count = 1;
   val_ptr->n_elements = 0;
@@ -255,13 +283,14 @@ Record_Of_Type::Record_Of_Type(null_type /*other_value*/)
 }
 
 Record_Of_Type::Record_Of_Type(const Record_Of_Type& other_value)
-: Base_Type(other_value), val_ptr(NULL), err_descr(other_value.err_descr), max_refd_index(-1)
+: Base_Type(other_value), RefdIndexInterface(other_value)
+, val_ptr(NULL), err_descr(other_value.err_descr), refd_ind_ptr(NULL)
 {
   if (!other_value.is_bound())
     TTCN_error("Copying an unbound record of/set of value.");
   // Increment ref_count only if val_ptr is not NULL
   if (other_value.val_ptr != NULL) {
-    if (other_value.refd_indices.empty()) {
+    if (NULL == other_value.refd_ind_ptr) {
       val_ptr = other_value.val_ptr;
       val_ptr->ref_count++;
     }
@@ -281,7 +310,7 @@ Record_Of_Type::Record_Of_Type(const Record_Of_Type& other_value)
 int Record_Of_Type::get_nof_elements() const
 {
   int nof_elements = (val_ptr != NULL) ? val_ptr->n_elements : 0;
-  if (!refd_indices.empty()) {
+  if (NULL != refd_ind_ptr) {
     while (nof_elements > 0) {
       if (is_elem_bound(nof_elements - 1)) {
         break;
@@ -300,23 +329,26 @@ bool Record_Of_Type::is_elem_bound(int index) const
 
 int Record_Of_Type::get_max_refd_index()
 {
-  if (refd_indices.empty()) {
+  if (NULL == refd_ind_ptr) {
     return -1;
   } 
-  if (-1 == max_refd_index) {
-    for (size_t i = 0; i < refd_indices.size(); ++i) {
-      if (refd_indices[i] > max_refd_index) {
-        max_refd_index = refd_indices[i];
+  if (-1 == refd_ind_ptr->max_refd_index) {
+    for (size_t i = 0; i < refd_ind_ptr->refd_indices.size(); ++i) {
+      if (refd_ind_ptr->refd_indices[i] > refd_ind_ptr->max_refd_index) {
+        refd_ind_ptr->max_refd_index = refd_ind_ptr->refd_indices[i];
       }
     }
   } 
-  return max_refd_index;
+  return refd_ind_ptr->max_refd_index;
 }
 
 bool Record_Of_Type::is_index_refd(int index)
 {
-  for (size_t i = 0; i < refd_indices.size(); ++i) {
-    if (index == refd_indices[i]) {
+  if (NULL == refd_ind_ptr) {
+    return false;
+  }
+  for (size_t i = 0; i < refd_ind_ptr->refd_indices.size(); ++i) {
+    if (index == refd_ind_ptr->refd_indices[i]) {
       return true;
     }
   }
@@ -362,7 +394,7 @@ void Record_Of_Type::set_value(const Base_Type* other_value)
     TTCN_error("Assigning an unbound value of type %s.",
                other_value->get_descriptor()->name);
   if (this != other_recof) {
-    if (refd_indices.empty() && other_recof->refd_indices.empty()) {
+    if (NULL == refd_ind_ptr && NULL == other_recof->refd_ind_ptr) {
       clean_up();
       val_ptr = other_recof->val_ptr;
       val_ptr->ref_count++;
@@ -733,7 +765,7 @@ void Record_Of_Type::set_size(int new_size)
 
 boolean Record_Of_Type::is_bound() const
 {
-  if (refd_indices.empty()) {
+  if (NULL == refd_ind_ptr) {
     return (val_ptr != NULL);
   }
   return (get_nof_elements() != 0);
@@ -853,7 +885,7 @@ int Record_Of_Type::TEXT_encode(const TTCN_Typedescriptor_t& p_td,
     }
     return encoded_length;
   }
-  const TTCN_Typedescriptor_t* elem_descr = get_elem_descr();
+  const TTCN_Typedescriptor_t* elem_descr = p_td.oftype_descr;
   for(int a=0;a<get_nof_elements();a++) {
     if(a!=0 && p_td.text->separator_encode) {
       buff.put_cs(*p_td.text->separator_encode);
@@ -939,9 +971,9 @@ int Record_Of_Type::TEXT_encode_negtest(const Erroneous_descriptor_t* p_err_desc
       }
       if (emb_descr) {
         encoded_length += get_at(a)->TEXT_encode_negtest(
-          emb_descr,*get_elem_descr(),buff);
+          emb_descr,*p_td.oftype_descr,buff);
       } else {
-        encoded_length += get_at(a)->TEXT_encode(*get_elem_descr(),buff);
+        encoded_length += get_at(a)->TEXT_encode(*p_td.oftype_descr,buff);
       }
       need_separator=true;
     }
@@ -1009,7 +1041,7 @@ int Record_Of_Type::TEXT_decode(const TTCN_Typedescriptor_t& p_td,
   while(TRUE){
     Base_Type* val = create_elem();
     pos=buff.get_pos();
-    int len = val->TEXT_decode(*get_elem_descr(),buff,limit,TRUE);
+    int len = val->TEXT_decode(*p_td.oftype_descr,buff,limit,TRUE);
     if(len==-1 || (len==0 && !limit.has_token())){
       buff.set_pos(pos);
       delete val;
@@ -1020,7 +1052,7 @@ int Record_Of_Type::TEXT_decode(const TTCN_Typedescriptor_t& p_td,
       break;
     }
     sep_found=FALSE;
-    if (refd_indices.empty()) {
+    if (NULL == refd_ind_ptr) {
       val_ptr->value_elements = (Base_Type**)reallocate_pointers(
         (void**)val_ptr->value_elements, val_ptr->n_elements, val_ptr->n_elements + 1);
       val_ptr->value_elements[val_ptr->n_elements]=val;
@@ -1100,7 +1132,7 @@ ASN_BER_TLV_t* Record_Of_Type::BER_encode_TLV(const TTCN_Typedescriptor_t& p_td,
     TTCN_EncDec_ErrorContext ec;
     for(int elem_i=0; elem_i<get_nof_elements(); elem_i++) {
       ec.set_msg("Component #%d: ", elem_i);
-      new_tlv->add_TLV(get_at(elem_i)->BER_encode_TLV(*get_elem_descr(), p_coding));
+      new_tlv->add_TLV(get_at(elem_i)->BER_encode_TLV(*p_td.oftype_descr, p_coding));
     }
     if (is_set()) new_tlv->sort_tlvs();
   }
@@ -1153,10 +1185,10 @@ ASN_BER_TLV_t* Record_Of_Type::BER_encode_TLV_negtest(const Erroneous_descriptor
         ec.set_msg("Component #%d: ", elem_i);
         if (emb_descr) {
           new_tlv->add_TLV(get_at(elem_i)->BER_encode_TLV_negtest(
-            emb_descr, *get_elem_descr(), p_coding));
+            emb_descr, *p_td.oftype_descr, p_coding));
         } else {
           new_tlv->add_TLV(get_at(elem_i)->BER_encode_TLV(
-            *get_elem_descr(), p_coding));
+            *p_td.oftype_descr, p_coding));
         }
       }
 
@@ -1196,7 +1228,7 @@ boolean Record_Of_Type::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td,
   TTCN_EncDec_ErrorContext ec_1("Component #");
   TTCN_EncDec_ErrorContext ec_2("0: ");
   while(BER_decode_constdTLV_next(stripped_tlv, V_pos, L_form, tmp_tlv)) {
-    get_at(get_nof_elements())->BER_decode_TLV(*get_elem_descr(), tmp_tlv, L_form);
+    get_at(get_nof_elements())->BER_decode_TLV(*p_td.oftype_descr, tmp_tlv, L_form);
     ec_2.set_msg("%d: ", val_ptr->n_elements);
   }
   return TRUE;
@@ -1229,7 +1261,7 @@ int Record_Of_Type::RAW_decode(const TTCN_Typedescriptor_t& p_td,
     set_size(0);
   }
   int start_field = get_nof_elements(); // append at the end
-  TTCN_Typedescriptor_t const& elem_descr = *get_elem_descr();
+  TTCN_Typedescriptor_t const& elem_descr = *p_td.oftype_descr;
   if (p_td.raw->fieldlength || sel_field != -1) {
     if (sel_field == -1) sel_field = p_td.raw->fieldlength;
     for (int a = 0; a < sel_field; a++) {
@@ -1247,7 +1279,6 @@ int Record_Of_Type::RAW_decode(const TTCN_Typedescriptor_t& p_td,
       if (!first_call) return -1;
       goto finished;
     }
-    int ext_bit = rawdec_ebv();
     while (limit > 0) {
       start_of_field = buff.get_pos_bit();
       Base_Type* field_bt = get_at(a); // non-const, extend the record-of
@@ -1264,12 +1295,11 @@ int Record_Of_Type::RAW_decode(const TTCN_Typedescriptor_t& p_td,
       decoded_length += decoded_field_length;
       limit -= decoded_field_length;
       a++;
-      if (ext_bit != 1/*XDEFNO*/&& ext_bit != -1/*XDEFDEFAULT*/) {
-        // ext_bit here may be 2 (XDEFYES) or 3 (XDEFREVERSE).
-        // (ext_bit != 2) is   0           or 1
+      if (EXT_BIT_NO != p_td.raw->extension_bit) {
+        // (EXT_BIT_YES != p_td.raw->extension_bit) is 0 or 1
         // This is the opposite value of what the bit needs to be to signal
         // the end of decoding, because x-or is the equivalent of !=
-        if ((ext_bit != 2/*XDEFYES*/) ^ buff.get_last_bit()) {
+        if ((EXT_BIT_YES != p_td.raw->extension_bit) ^ buff.get_last_bit()) {
           goto finished;
         }
       }
@@ -1291,7 +1321,7 @@ int Record_Of_Type::RAW_encode(const TTCN_Typedescriptor_t& p_td, RAW_enc_tree&
   myleaf.rec_of = TRUE;
   myleaf.body.node.num_of_nodes = encoded_num_of_records;
   myleaf.body.node.nodes = init_nodes_of_enc_tree(encoded_num_of_records);
-  TTCN_Typedescriptor_t const& elem_descr = *get_elem_descr();
+  TTCN_Typedescriptor_t const& elem_descr = *p_td.oftype_descr;
   for (int a = 0; a < encoded_num_of_records; a++) {
     const Base_Type *field_bt = get_at(a);
     myleaf.body.node.nodes[a] = new RAW_enc_tree(TRUE, &myleaf, &(myleaf.curr_pos), a, elem_descr.raw);
@@ -1342,7 +1372,7 @@ int Record_Of_Type::RAW_encode_negtest(const Erroneous_descriptor_t *p_err_descr
       continue;
     const Erroneous_values_t *err_vals = p_err_descr->next_field_err_values(i, values_idx);
     const Erroneous_descriptor_t *emb_descr = p_err_descr->next_field_emb_descr(i, edescr_idx);
-    TTCN_Typedescriptor_t const& elem_descr = *get_elem_descr();
+    TTCN_Typedescriptor_t const& elem_descr = *p_td.oftype_descr;
     if (err_vals && err_vals->before) {
       if (err_vals->before->errval == NULL)
         TTCN_error("internal error: erroneous before value missing");
@@ -1385,11 +1415,11 @@ int Record_Of_Type::RAW_encode_negtest(const Erroneous_descriptor_t *p_err_descr
         myleaf.body.node.nodes[node_pos] = new RAW_enc_tree(TRUE, &myleaf,
           &(myleaf.curr_pos), node_pos, elem_descr.raw);
         encoded_length += get_at(i)->RAW_encode_negtest(emb_descr, 
-          *get_elem_descr(), *myleaf.body.node.nodes[node_pos++]);
+          *p_td.oftype_descr, *myleaf.body.node.nodes[node_pos++]);
       } else {
         myleaf.body.node.nodes[node_pos] = new RAW_enc_tree(TRUE, &myleaf,
           &(myleaf.curr_pos), node_pos, elem_descr.raw);
-        encoded_length += get_at(i)->RAW_encode(*get_elem_descr()
+        encoded_length += get_at(i)->RAW_encode(*p_td.oftype_descr
           *myleaf.body.node.nodes[node_pos++]);
       }
     }
@@ -1418,8 +1448,12 @@ int Record_Of_Type::RAW_encode_negtest(const Erroneous_descriptor_t *p_err_descr
   return myleaf.length = encoded_length;
 }
 
-int Record_Of_Type::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const
+int Record_Of_Type::JSON_encode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok) const
 {
+  if (err_descr) {
+         return JSON_encode_negtest(err_descr, p_td, p_tok);
+  }
+  
   if (!is_bound()) {
     TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
       "Encoding an unbound %s of value.", is_set() ? "set" : "record");
@@ -1428,10 +1462,109 @@ int Record_Of_Type::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_
   
   int enc_len = p_tok.put_next_token(JSON_TOKEN_ARRAY_START, NULL);
   
-  for(int i = 0; i < get_nof_elements(); ++i) {
-    int ret_val = get_at(i)->JSON_encode(*get_elem_descr(), p_tok);
-    if (0 > ret_val) break;
-    enc_len += ret_val;
+  for (int i = 0; i < get_nof_elements(); ++i) {
+    if (NULL != p_td.json && p_td.json->metainfo_unbound && !get_at(i)->is_bound()) {
+      // unbound elements are encoded as { "metainfo []" : "unbound" }
+      enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);
+      enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, "metainfo []");
+      enc_len += p_tok.put_next_token(JSON_TOKEN_STRING, "\"unbound\"");
+      enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);
+    }
+    else {
+      int ret_val = get_at(i)->JSON_encode(*p_td.oftype_descr, p_tok);
+      if (0 > ret_val) break;
+      enc_len += ret_val;
+    }
+  }
+  
+  enc_len += p_tok.put_next_token(JSON_TOKEN_ARRAY_END, NULL);
+  return enc_len;
+}
+
+int Record_Of_Type::JSON_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
+                                        const TTCN_Typedescriptor_t& p_td,
+                                        JSON_Tokenizer& p_tok) const 
+{
+  if (!is_bound()) {
+    TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
+      "Encoding an unbound %s of value.", is_set() ? "set" : "record");
+    return -1;
+  }
+  
+  int enc_len = p_tok.put_next_token(JSON_TOKEN_ARRAY_START, NULL);
+  
+  int values_idx = 0;
+  int edescr_idx = 0;
+  
+  for (int i = 0; i < get_nof_elements(); ++i) {
+    if (-1 != p_err_descr->omit_before && p_err_descr->omit_before > i) {
+      continue;
+    }
+    
+    const Erroneous_values_t* err_vals = p_err_descr->next_field_err_values(i, values_idx);
+    const Erroneous_descriptor_t* emb_descr = p_err_descr->next_field_emb_descr(i, edescr_idx);
+    
+    if (NULL != err_vals && NULL != err_vals->before) {
+      if (NULL == err_vals->before->errval) {
+        TTCN_error("internal error: erroneous before value missing");
+      }
+      if (err_vals->before->raw) {
+        enc_len += err_vals->before->errval->JSON_encode_negtest_raw(p_tok);
+      } else {
+        if (NULL == err_vals->before->type_descr) {
+          TTCN_error("internal error: erroneous before typedescriptor missing");
+        }
+        enc_len += err_vals->before->errval->JSON_encode(*(err_vals->before->type_descr), p_tok);
+      }
+    }
+    
+    if (NULL != err_vals && NULL != err_vals->value) {
+      if (NULL != err_vals->value->errval) {
+        if (err_vals->value->raw) {
+          enc_len += err_vals->value->errval->JSON_encode_negtest_raw(p_tok);
+        } else {
+          if (NULL == err_vals->value->type_descr) {
+            TTCN_error("internal error: erroneous before typedescriptor missing");
+          }
+          enc_len += err_vals->value->errval->JSON_encode(*(err_vals->value->type_descr), p_tok);
+        }
+      }
+    }
+    else if (NULL != p_td.json && p_td.json->metainfo_unbound && !get_at(i)->is_bound()) {
+      // unbound elements are encoded as { "metainfo []" : "unbound" }
+      enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);
+      enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, "metainfo []");
+      enc_len += p_tok.put_next_token(JSON_TOKEN_STRING, "\"unbound\"");
+      enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);
+    }
+    else {
+      int ret_val;
+      if (NULL != emb_descr) {
+        ret_val = get_at(i)->JSON_encode_negtest(emb_descr, *p_td.oftype_descr, p_tok);
+      } else {
+        ret_val = get_at(i)->JSON_encode(*p_td.oftype_descr, p_tok);
+      }
+      if (0 > ret_val) break;
+      enc_len += ret_val;
+    }
+    
+    if (NULL != err_vals && NULL != err_vals->after) {
+      if (NULL == err_vals->after->errval) {
+        TTCN_error("internal error: erroneous after value missing");
+      }
+      if (err_vals->after->raw) {
+        enc_len += err_vals->after->errval->JSON_encode_negtest_raw(p_tok);
+      } else {
+        if (NULL == err_vals->after->type_descr) {
+          TTCN_error("internal error: erroneous before typedescriptor missing");
+        }
+        enc_len += err_vals->after->errval->JSON_encode(*(err_vals->after->type_descr), p_tok);
+      }
+    }
+    
+    if (-1 != p_err_descr->omit_after && p_err_descr->omit_after <= i) {
+      break;
+    }
   }
   
   enc_len += p_tok.put_next_token(JSON_TOKEN_ARRAY_END, NULL);
@@ -1451,11 +1584,35 @@ int Record_Of_Type::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenize
   } 
   
   set_size(0);
-  while (true) {
+  for (int nof_elements = 0; true; ++nof_elements) {
     // Read value tokens until we reach some other token
     size_t buf_pos = p_tok.get_buf_pos();
+    int ret_val;
+    if (NULL != p_td.json && p_td.json->metainfo_unbound) {
+      // check for metainfo object
+      ret_val = p_tok.get_next_token(&token, NULL, NULL);
+      if (JSON_TOKEN_OBJECT_START == token) {
+        char* value = NULL;
+        size_t value_len = 0;
+        ret_val += p_tok.get_next_token(&token, &value, &value_len);
+        if (JSON_TOKEN_NAME == token && 11 == value_len &&
+            0 == strncmp(value, "metainfo []", 11)) {
+          ret_val += p_tok.get_next_token(&token, &value, &value_len);
+          if (JSON_TOKEN_STRING == token && 9 == value_len &&
+              0 == strncmp(value, "\"unbound\"", 9)) {
+            ret_val = p_tok.get_next_token(&token, NULL, NULL);
+            if (JSON_TOKEN_OBJECT_END == token) {
+              dec_len += ret_val;
+              continue;
+            }
+          }
+        }
+      }
+      // metainfo object not found, jump back and let the element type decode it
+      p_tok.set_buf_pos(buf_pos);
+    }
     Base_Type* val = create_elem();
-    int ret_val = val->JSON_decode(*get_elem_descr(), p_tok, p_silent);
+    ret_val = val->JSON_decode(*p_td.oftype_descr, p_tok, p_silent);
     if (JSON_ERROR_INVALID_TOKEN == ret_val) {
       // undo the last action on the buffer
       p_tok.set_buf_pos(buf_pos);
@@ -1469,14 +1626,14 @@ int Record_Of_Type::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenize
       }
       return JSON_ERROR_FATAL;
     }
-    if (refd_indices.empty()) {
+    if (NULL == refd_ind_ptr) {
       val_ptr->value_elements = (Base_Type**)reallocate_pointers(
-        (void**)val_ptr->value_elements, val_ptr->n_elements, val_ptr->n_elements + 1);
-      val_ptr->value_elements[val_ptr->n_elements] = val;
-      val_ptr->n_elements++;
+        (void**)val_ptr->value_elements, val_ptr->n_elements, nof_elements + 1);
+      val_ptr->value_elements[nof_elements] = val;
+      val_ptr->n_elements = nof_elements + 1;
     }
     else {
-      get_at(get_nof_elements())->set_value(val);
+      get_at(nof_elements)->set_value(val);
       delete val;
     }
     dec_len += ret_val;
@@ -1528,7 +1685,7 @@ void Record_Of_Type::encode(const TTCN_Typedescriptor_t& p_td,
   case TTCN_EncDec::CT_XER: {
     TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name);
     unsigned XER_coding=va_arg(pvar, unsigned);
-    XER_encode(*(p_td.xer),p_buf, XER_coding, 0);
+    XER_encode(*(p_td.xer),p_buf, XER_coding, 0, 0);
     p_buf.put_c('\n');
     break;}
   case TTCN_EncDec::CT_JSON: {
@@ -1598,7 +1755,7 @@ void Record_Of_Type::decode(const TTCN_Typedescriptor_t& p_td,
     for (int success=reader.Read(); success==1; success=reader.Read()) {
       if (reader.NodeType() == XML_READER_TYPE_ELEMENT) break;
     }
-    XER_decode(*(p_td.xer), reader, XER_coding | XER_TOPLEVEL);
+    XER_decode(*(p_td.xer), reader, XER_coding | XER_TOPLEVEL, XER_NONE, 0);
     size_t bytes = reader.ByteConsumed();
     p_buf.set_pos(bytes);
     break;}
@@ -1631,7 +1788,7 @@ char **Record_Of_Type::collect_ns(const XERdescriptor_t& p_td, size_t& num, bool
     if (val_ptr) for (int i = 0; i < get_nof_elements(); ++i) {
       size_t num_new = 0;
       char **new_namespaces = get_at(i)->collect_ns(
-        *get_elem_descr()->xer, num_new, def_ns_1);
+        *p_td.oftype_descr, num_new, def_ns_1);
       merge_ns(collected_ns, num_collected, new_namespaces, num_new);
       def_ns = def_ns || def_ns_1; // alas, no ||=
     }
@@ -1652,10 +1809,10 @@ static const universal_char sp = { 0,0,0,' ' };
 static const universal_char tb = { 0,0,0,9 };
 
 int Record_Of_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf,
-  unsigned int flavor, int indent) const
+  unsigned int flavor, int indent, embed_values_enc_struct_t* emb_val) const
 {
   if (err_descr) {
-    return XER_encode_negtest(err_descr, p_td, p_buf, flavor, indent);
+    return XER_encode_negtest(err_descr, p_td, p_buf, flavor, indent, emb_val);
   }
 
   if (val_ptr == 0) TTCN_error(
@@ -1745,7 +1902,7 @@ int Record_Of_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf,
           check_namespace_restrictions(p_td, (const char*)cs);
         }
         before.XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf,
-          flavor | ANY_ATTRIBUTES, indent);
+          flavor | ANY_ATTRIBUTES, indent, 0);
 
         p_buf.put_c('\'');
         p_buf.put_c(' ');
@@ -1767,7 +1924,7 @@ int Record_Of_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf,
 
       UNIVERSAL_CHARSTRING after(len - j, (const universal_char*)(*elem) + j);
       after.XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf,
-        flavor | ANY_ATTRIBUTES, indent);
+        flavor | ANY_ATTRIBUTES, indent, 0);
       
       // Put this attribute in a dummy element and walk through it to check its validity
       TTCN_Buffer check_buf;
@@ -1783,11 +1940,20 @@ int Record_Of_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf,
   }
   else { // not ANY-ATTRIBUTES
     unsigned int sub_flavor = flavor | XER_RECOF | (p_td.xer_bits & (XER_LIST));
+    TTCN_EncDec_ErrorContext ec_0("Index ");
+    TTCN_EncDec_ErrorContext ec_1;
 
     for (int i = 0; i < nof_elements; ++i) {
+      if (i > 0 && !own_tag && 0 != emb_val &&
+          emb_val->embval_index < emb_val->embval_array->size_of()) {
+        emb_val->embval_array->get_at(emb_val->embval_index)->XER_encode(
+          UNIVERSAL_CHARSTRING_xer_, p_buf, flavor | EMBED_VALUES, indent+1, 0);
+        ++emb_val->embval_index;
+      }
+      ec_1.set_msg("%d: ", i);
       if (exer && (p_td.xer_bits & XER_LIST) && i>0) p_buf.put_c(' ');
-      get_at(i)->XER_encode(*get_elem_descr()->xer, p_buf,
-        sub_flavor, indent+own_tag);
+      get_at(i)->XER_encode(*p_td.oftype_descr, p_buf,
+        sub_flavor, indent+own_tag, emb_val);
     }
 
     if (indenting && nof_elements && !is_exerlist(flavor)) {
@@ -1815,9 +1981,9 @@ int Record_Of_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf,
  * @param indent indentation level
  * @return number of bytes generated
  */
-int Record_Of_Type::encode_element(int i,
+int Record_Of_Type::encode_element(int i, const XERdescriptor_t& p_td,
   const Erroneous_values_t* ev, const Erroneous_descriptor_t* ed,
-  TTCN_Buffer& p_buf, unsigned int sub_flavor, int indent) const
+  TTCN_Buffer& p_buf, unsigned int sub_flavor, int indent, embed_values_enc_struct_t* emb_val) const
 {
   int enc_len = p_buf.get_len();
   TTCN_EncDec_ErrorContext ec;
@@ -1834,7 +2000,7 @@ int Record_Of_Type::encode_element(int i,
       if (ev->before->type_descr==NULL) TTCN_error(
         "internal error: erroneous before type descriptor missing");
       ev->before->errval->XER_encode(*ev->before->type_descr->xer,
-        p_buf, sub_flavor, indent);
+        p_buf, sub_flavor, indent, 0);
     }
   }
 
@@ -1854,16 +2020,16 @@ int Record_Of_Type::encode_element(int i,
         if (ev->value->type_descr==NULL) TTCN_error(
           "internal error: erroneous value type descriptor missing");
         ev->value->errval->XER_encode(*ev->value->type_descr->xer,
-          p_buf, sub_flavor, indent);
+          p_buf, sub_flavor, indent, 0);
       }
     } // else -> omit
   } else {
     ec.set_msg("Component #%d: ", i);
     if (ed) {
-      get_at(i)->XER_encode_negtest(ed, *get_elem_descr()->xer, p_buf, sub_flavor, indent);
+      get_at(i)->XER_encode_negtest(ed, p_td, p_buf, sub_flavor, indent, emb_val);
     } else {
       // the "real" encoder
-      get_at(i)->XER_encode(*get_elem_descr()->xer, p_buf, sub_flavor, indent);
+      get_at(i)->XER_encode(p_td, p_buf, sub_flavor, indent, emb_val);
     }
   }
 
@@ -1878,7 +2044,7 @@ int Record_Of_Type::encode_element(int i,
       if (ev->after->type_descr==NULL) TTCN_error(
         "internal error: erroneous after type descriptor missing");
       ev->after->errval->XER_encode(*ev->after->type_descr->xer,
-        p_buf, sub_flavor, indent);
+        p_buf, sub_flavor, indent, 0);
     }
   }
 
@@ -1887,7 +2053,8 @@ int Record_Of_Type::encode_element(int i,
 
 // XERSTUFF Record_Of_Type::XER_encode_negtest
 int Record_Of_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
-  const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, unsigned flavor, int indent) const
+  const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, unsigned flavor, int indent,
+  embed_values_enc_struct_t* emb_val) const
 {
   if (val_ptr == 0) TTCN_error(
     "Attempt to XER-encode an unbound record of type %s", get_descriptor()->name);
@@ -1949,7 +2116,7 @@ int Record_Of_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr
           if (ev->before->type_descr==NULL) TTCN_error(
             "internal error: erroneous before type descriptor missing");
           else ev->before->errval->XER_encode(*ev->before->type_descr->xer,
-            p_buf, flavor, indent);
+            p_buf, flavor, indent, 0);
         }
       }
 
@@ -1960,7 +2127,7 @@ int Record_Of_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr
             if (ev->value->type_descr==NULL) TTCN_error(
               "internal error: erroneous value type descriptor missing");
             else ev->value->errval->XER_encode(*ev->value->type_descr->xer,
-              p_buf, flavor, indent);
+              p_buf, flavor, indent, 0);
           }
         }
       }
@@ -2001,7 +2168,7 @@ int Record_Of_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr
 
             UNIVERSAL_CHARSTRING before(sp_at, (const universal_char*)(*elem));
             before.XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf,
-              flavor | ANY_ATTRIBUTES, indent);
+              flavor | ANY_ATTRIBUTES, indent, 0);
 
             p_buf.put_c('\'');
             p_buf.put_c(' ');
@@ -2018,7 +2185,7 @@ int Record_Of_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr
 
           UNIVERSAL_CHARSTRING after(len - j, (const universal_char*)(*elem) + j);
           after.XER_encode(UNIVERSAL_CHARSTRING_xer_, p_buf,
-            flavor | ANY_ATTRIBUTES, indent);
+            flavor | ANY_ATTRIBUTES, indent, 0);
         }
       }
 
@@ -2031,7 +2198,7 @@ int Record_Of_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr
             if (ev->after->type_descr==NULL) TTCN_error(
               "internal error: erroneous after type descriptor missing");
             else ev->after->errval->XER_encode(*ev->after->type_descr->xer,
-              p_buf, flavor, indent);
+              p_buf, flavor, indent, 0);
           }
         }
       }
@@ -2050,13 +2217,26 @@ int Record_Of_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr
 
     for (int i = 0; i < nof_elements; ++i) {
       if (i < p_err_descr->omit_before) continue;
+      
+      if (0 != emb_val && i > 0 && !own_tag &&
+          emb_val->embval_index < emb_val->embval_array->size_of()) {
+        const Erroneous_values_t    * ev0_i = NULL;
+        const Erroneous_descriptor_t* ed0_i = NULL;
+        if (emb_val->embval_err) {
+          ev0_i = emb_val->embval_err->next_field_err_values(emb_val->embval_index, emb_val->embval_err_val_idx);
+          ed0_i = emb_val->embval_err->next_field_emb_descr (emb_val->embval_index, emb_val->embval_err_descr_idx);
+        }
+        emb_val->embval_array->encode_element(emb_val->embval_index, UNIVERSAL_CHARSTRING_xer_,
+          ev0_i, ed0_i, p_buf, flavor | EMBED_VALUES, indent + own_tag, 0);
+        ++emb_val->embval_index;
+      }
 
       const Erroneous_values_t*     err_vals =
         p_err_descr->next_field_err_values(i, values_idx);
       const Erroneous_descriptor_t* emb_descr =
         p_err_descr->next_field_emb_descr (i, edescr_idx);
 
-      encode_element(i, err_vals, emb_descr, p_buf, sub_flavor, indent+own_tag);
+      encode_element(i, *p_td.oftype_descr, err_vals, emb_descr, p_buf, sub_flavor, indent+own_tag, emb_val);
 
       // omit_after value -1 becomes "very big"
       if ((unsigned int)i >= (unsigned int)p_err_descr->omit_after) break;
@@ -2073,7 +2253,7 @@ int Record_Of_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr
 }
 
 int Record_Of_Type::XER_decode(const XERdescriptor_t& p_td,
-  XmlReaderWrap& reader, unsigned int flavor)
+  XmlReaderWrap& reader, unsigned int flavor, unsigned int flavor2, embed_values_dec_struct_t* emb_val)
 {
   int exer = is_exer(flavor);
   int xerbits = p_td.xer_bits;
@@ -2123,7 +2303,7 @@ int Record_Of_Type::XER_decode(const XERdescriptor_t& p_td,
       pos += strlen(str) + 1;
       // Construct a new XML Reader with the current token.
       TTCN_Buffer buf2;
-      const XERdescriptor_t& sub_xer = *get_elem_descr()->xer;
+      const XERdescriptor_t& sub_xer = *p_td.oftype_descr;
       buf2.put_c('<');
       write_ns_prefix(sub_xer, buf2);
 
@@ -2152,7 +2332,7 @@ int Record_Of_Type::XER_decode(const XERdescriptor_t& p_td,
       // The call to the non-const operator[], I mean get_at(), creates
       // a new element (because it is indexing one past the last element).
       // Then we call its XER_decode with the temporary XML reader.
-      get_at(get_nof_elements())->XER_decode(sub_xer, reader2, flavor);
+      get_at(get_nof_elements())->XER_decode(sub_xer, reader2, flavor, flavor2, 0);
       if (flavor & EXIT_ON_ERROR && !is_elem_bound(get_nof_elements() - 1)) {
         if (1 == get_nof_elements()) {
           // Failed to decode even the first element
@@ -2210,7 +2390,7 @@ int Record_Of_Type::XER_decode(const XERdescriptor_t& p_td,
              * belong to the embedded type, the record-of has already ended. */
             if (!own_tag && !can_start_v(
               (const char*)reader.LocalName(), (const char*)reader.NamespaceUri(),
-              *get_elem_descr()->xer, flavor | UNTAGGED))
+              p_td, flavor | UNTAGGED))
             {
               for (; success == 1 && reader.Depth() > depth; success = reader.Read()) ;
               // We should now be back at the same depth as we started.
@@ -2218,7 +2398,10 @@ int Record_Of_Type::XER_decode(const XERdescriptor_t& p_td,
             }
             ec_1.set_msg("%d: ", get_nof_elements());
             /* The call to the non-const get_at() creates the element */
-            get_at(get_nof_elements())->XER_decode(*get_elem_descr()->xer, reader, flavor);
+            get_at(get_nof_elements())->XER_decode(*p_td.oftype_descr, reader, flavor, flavor2, emb_val);
+          }
+          if (0 != emb_val && !own_tag && get_nof_elements() > 1) {
+            ++emb_val->embval_index;
           }
         }
         else if (XML_READER_TYPE_END_ELEMENT == type) {
@@ -2231,12 +2414,21 @@ int Record_Of_Type::XER_decode(const XERdescriptor_t& p_td,
           }
           break;
         }
+        else if (XML_READER_TYPE_TEXT == type && 0 != emb_val && !own_tag && get_nof_elements() > 0) {
+          UNIVERSAL_CHARSTRING emb_ustr((const char*)reader.Value());
+          emb_val->embval_array->get_at(emb_val->embval_index)->set_value(&emb_ustr);
+          success = reader.Read();
+        }
         else {
           success = reader.Read();
         }
       } /* next read */
     } /* if not empty element */
   } /* if not LIST */
+  if (!own_tag && exer && (p_td.xer_bits & XER_OPTIONAL) && get_nof_elements() == 0) {
+    // set it to unbound, so the OPTIONAL class sets it to omit
+    clean_up();
+  }
   return 1; // decode successful
 }
 
@@ -2257,25 +2449,31 @@ void Record_Of_Type::set_param(Module_Param& param) {
   }
   
   param.basic_check(Module_Param::BC_VALUE|Module_Param::BC_LIST, is_set()?"set of value":"record of value");
+  
+  Module_Param_Ptr mp = &param;
+  if (param.get_type() == Module_Param::MP_Reference) {
+    mp = param.get_referenced_param();
+  }
+  
   switch (param.get_operation_type()) {
   case Module_Param::OT_ASSIGN:
-    if (param.get_type()==Module_Param::MP_Value_List && param.get_size()==0) {
+    if (mp->get_type()==Module_Param::MP_Value_List && mp->get_size()==0) {
       set_val(NULL_VALUE);
       return;
     }
-    switch (param.get_type()) {
+    switch (mp->get_type()) {
     case Module_Param::MP_Value_List:
-      set_size(param.get_size());
-      for (size_t i=0; i<param.get_size(); ++i) {
-        Module_Param* const curr = param.get_elem(i);
+      set_size(mp->get_size());
+      for (size_t i=0; i<mp->get_size(); ++i) {
+        Module_Param* const curr = mp->get_elem(i);
         if (curr->get_type()!=Module_Param::MP_NotUsed) {
           get_at(i)->set_param(*curr);
         }
       }
       break;
     case Module_Param::MP_Indexed_List:
-      for (size_t i=0; i<param.get_size(); ++i) {
-        Module_Param* const current = param.get_elem(i);
+      for (size_t i=0; i<mp->get_size(); ++i) {
+        Module_Param* const current = mp->get_elem(i);
         get_at(current->get_id()->get_index())->set_param(*current);
       }
       break;
@@ -2284,12 +2482,12 @@ void Record_Of_Type::set_param(Module_Param& param) {
     }
     break;
   case Module_Param::OT_CONCAT:
-    switch (param.get_type()) {
+    switch (mp->get_type()) {
     case Module_Param::MP_Value_List: {
       if (!is_bound()) set_val(NULL_VALUE);
       int start_idx = lengthof();
-      for (size_t i=0; i<param.get_size(); ++i) {
-        Module_Param* const curr = param.get_elem(i);
+      for (size_t i=0; i<mp->get_size(); ++i) {
+        Module_Param* const curr = mp->get_elem(i);
         if ((curr->get_type()!=Module_Param::MP_NotUsed)) {
           get_at(start_idx+(int)i)->set_param(*curr);
         }
@@ -2307,6 +2505,34 @@ void Record_Of_Type::set_param(Module_Param& param) {
   }
 }
 
+Module_Param* Record_Of_Type::get_param(Module_Param_Name& param_name) const
+{
+  if (!is_bound()) {
+    return new Module_Param_Unbound();
+  }
+  if (param_name.next_name()) {
+    // Haven't reached the end of the module parameter name
+    // => the name refers to one of the elements, not to the whole record of
+    char* param_field = param_name.get_current_name();
+    if (param_field[0] < '0' || param_field[0] > '9') {
+      TTCN_error("Unexpected record field name in module parameter reference, "
+        "expected a valid index for %s type `%s'",
+        is_set() ? "set of" : "record of", get_descriptor()->name);
+    }
+    int param_index = -1;
+    sscanf(param_field, "%d", &param_index);
+    return get_at(param_index)->get_param(param_name);
+  }
+  Vector<Module_Param*> values;
+  for (int i = 0; i < val_ptr->n_elements; ++i) {
+    values.push_back(val_ptr->value_elements[i]->get_param(param_name));
+  }
+  Module_Param_Value_List* mp = new Module_Param_Value_List();
+  mp->add_list_with_implicit_ids(&values);
+  values.clear();
+  return mp;
+}
+
 void Record_Of_Type::set_implicit_omit()
 {
   for (int i = 0; i < get_nof_elements(); ++i) {
@@ -2317,22 +2543,30 @@ void Record_Of_Type::set_implicit_omit()
 
 void Record_Of_Type::add_refd_index(int index)
 {
-  refd_indices.push_back(index);
+  if (NULL == refd_ind_ptr) {
+    refd_ind_ptr = new refd_index_struct;
+    refd_ind_ptr->max_refd_index = -1;
+  }
+  refd_ind_ptr->refd_indices.push_back(index);
   if (index > get_max_refd_index()) {
-    max_refd_index = index;
+    refd_ind_ptr->max_refd_index = index;
   }
 }
 
 void Record_Of_Type::remove_refd_index(int index)
 {
-  for (size_t i = refd_indices.size(); i > 0; --i) {
-    if (refd_indices[i - 1] == index) {
-      refd_indices.erase_at(i - 1);
+  for (size_t i = refd_ind_ptr->refd_indices.size(); i > 0; --i) {
+    if (refd_ind_ptr->refd_indices[i - 1] == index) {
+      refd_ind_ptr->refd_indices.erase_at(i - 1);
       break;
     }
   }
-  if (get_max_refd_index() == index) {
-    max_refd_index = -1;
+  if (refd_ind_ptr->refd_indices.empty()) {
+    delete refd_ind_ptr;
+    refd_ind_ptr = NULL;
+  }
+  else if (get_max_refd_index() == index) {
+    refd_ind_ptr->max_refd_index = -1;
   }
 }
 
@@ -2354,7 +2588,6 @@ boolean operator!=(null_type null_value,
 
 boolean Record_Type::is_bound() const
 {
-  if (bound_flag) return TRUE;
   int field_cnt = get_count();
   for (int field_idx=0; field_idx<field_cnt; field_idx++) {
     const Base_Type* temp = get_at(field_idx);
@@ -2368,9 +2601,6 @@ boolean Record_Type::is_bound() const
 
 boolean Record_Type::is_value() const
 {
-  if (!is_bound()) {
-    return FALSE;
-  }
   int field_cnt = get_count();
   for (int field_idx=0; field_idx<field_cnt; field_idx++) {
     const Base_Type* temp = get_at(field_idx);
@@ -2390,7 +2620,6 @@ void Record_Type::clean_up()
   for (int field_idx=0; field_idx<field_cnt; field_idx++) {
     get_at(field_idx)->clean_up();
   }
-  bound_flag = FALSE;
 }
 
 void Record_Type::log() const
@@ -2412,7 +2641,6 @@ void Record_Type::log() const
 }
 
 void Record_Type::set_param(Module_Param& param) {
-  bound_flag = TRUE;
   if (dynamic_cast<Module_Param_Name*>(param.get_id()) != NULL &&
       param.get_id()->next_name()) {
     // Haven't reached the end of the module parameter name
@@ -2434,21 +2662,27 @@ void Record_Type::set_param(Module_Param& param) {
   }
 
   param.basic_check(Module_Param::BC_VALUE, is_set()?"set value":"record value");
-  switch (param.get_type()) {
+  
+  Module_Param_Ptr mp = &param;
+  if (param.get_type() == Module_Param::MP_Reference) {
+    mp = param.get_referenced_param();
+  }
+  
+  switch (mp->get_type()) {
   case Module_Param::MP_Value_List:
-    if (get_count()<(int)param.get_size()) {
-      param.error("%s value of type %s has %d fields but list value has %d fields", is_set()?"Set":"Record", get_descriptor()->name, get_count(), (int)param.get_size());
+    if (get_count()<(int)mp->get_size()) {
+      param.error("%s value of type %s has %d fields but list value has %d fields", is_set()?"Set":"Record", get_descriptor()->name, get_count(), (int)mp->get_size());
     }
-    for (size_t i=0; i<param.get_size(); i++) {
-      Module_Param* mp = param.get_elem(i);
-      if (mp->get_type()!=Module_Param::MP_NotUsed) {
-        get_at((int)i)->set_param(*mp);
+    for (size_t i=0; i<mp->get_size(); i++) {
+      Module_Param* mp_elem = mp->get_elem(i);
+      if (mp_elem->get_type()!=Module_Param::MP_NotUsed) {
+        get_at((int)i)->set_param(*mp_elem);
       }
     }
     break;
   case Module_Param::MP_Assignment_List:
-    for (size_t i=0; i<param.get_size(); ++i) {
-      Module_Param* const current = param.get_elem(i);
+    for (size_t i=0; i<mp->get_size(); ++i) {
+      Module_Param* const current = mp->get_elem(i);
       bool found = false;
       for (int j=0; j<get_count(); ++j) {
         if (!strcmp(fld_name(j), current->get_id()->get_name())) {
@@ -2469,6 +2703,38 @@ void Record_Type::set_param(Module_Param& param) {
   }
 }
 
+Module_Param* Record_Type::get_param(Module_Param_Name& param_name) const
+{
+  if (!is_bound()) {
+    return new Module_Param_Unbound();
+  }
+  if (param_name.next_name()) {
+    // Haven't reached the end of the module parameter name
+    // => the name refers to one of the fields, not to the whole record
+    char* param_field = param_name.get_current_name();
+    if (param_field[0] >= '0' && param_field[0] <= '9') {
+      TTCN_error("Unexpected array index in module parameter reference, "
+        "expected a valid field name for %s type `%s'",
+        is_set() ? "set" : "record", get_descriptor()->name);
+    }
+    int field_cnt = get_count();
+    for (int field_idx = 0; field_idx < field_cnt; field_idx++) {
+      if (strcmp(fld_name(field_idx), param_field) == 0) {
+        return get_at(field_idx)->get_param(param_name);
+      }
+    }
+    TTCN_error("Field `%s' not found in %s type `%s'",
+      param_field, is_set() ? "set" : "record", get_descriptor()->name);
+  }
+  Module_Param_Assignment_List* mp = new Module_Param_Assignment_List();
+  for (int i = 0; i < get_count(); ++i) {
+    Module_Param* mp_field = get_at(i)->get_param(param_name);
+    mp_field->set_id(new Module_Param_FieldName(mcopystr(fld_name(i))));
+    mp->add_elem(mp_field);
+  }
+  return mp;
+}
+
 void Record_Type::set_implicit_omit()
 {
   int field_cnt = get_count();
@@ -2485,10 +2751,6 @@ void Record_Type::set_implicit_omit()
 
 int Record_Type::size_of() const
 {
-  if (!is_bound()) {
-    TTCN_error("Calculating the size of an unbound record/set value of type %s",
-      get_descriptor()->name);
-  }
   int opt_count = optional_count();
   if (opt_count==0) return get_count();
   const int* optional_indexes = get_optional_indexes();
@@ -2512,7 +2774,6 @@ void Record_Type::encode_text(Text_Buf& text_buf) const
 
 void Record_Type::decode_text(Text_Buf& text_buf)
 {
-  bound_flag = TRUE;
   int field_cnt = get_count();
   for (int field_idx=0; field_idx<field_cnt; field_idx++)
     get_at(field_idx)->decode_text(text_buf);
@@ -2521,9 +2782,6 @@ void Record_Type::decode_text(Text_Buf& text_buf)
 boolean Record_Type::is_equal(const Base_Type* other_value) const
 {
   const Record_Type* other_record = static_cast<const Record_Type*>(other_value);
-  if (!is_bound() && !other_record->is_bound()) {
-    return TRUE;
-  }
   int field_cnt = get_count();
   for (int field_idx=0; field_idx<field_cnt; field_idx++) {
     const Base_Type* elem = get_at(field_idx);
@@ -2555,7 +2813,6 @@ void Record_Type::set_value(const Base_Type* other_value)
     }
   }
   err_descr = other_record->err_descr;
-  bound_flag = TRUE;
 }
 
 void Record_Type::encode(const TTCN_Typedescriptor_t& p_td,
@@ -2592,7 +2849,7 @@ void Record_Type::encode(const TTCN_Typedescriptor_t& p_td,
   case TTCN_EncDec::CT_XER: {
     TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name);
     unsigned XER_coding=va_arg(pvar, unsigned);
-    XER_encode(*(p_td.xer),p_buf, XER_coding, 0);
+    XER_encode(*(p_td.xer),p_buf, XER_coding, 0, 0);
     p_buf.put_c('\n');
     break;}
   case TTCN_EncDec::CT_JSON: {
@@ -2678,7 +2935,7 @@ void Record_Type::decode(const TTCN_Typedescriptor_t& p_td,
     for (int success=reader.Read(); success==1; success=reader.Read()) {
       if (reader.NodeType() == XML_READER_TYPE_ELEMENT) break;
     }
-    XER_decode(*(p_td.xer), reader, XER_coding | XER_TOPLEVEL);
+    XER_decode(*(p_td.xer), reader, XER_coding | XER_TOPLEVEL, XER_NONE, 0);
     size_t bytes = reader.ByteConsumed();
     p_buf.set_pos(bytes);
     break;}
@@ -2836,7 +3093,6 @@ ASN_BER_TLV_t* Record_Type::BER_encode_TLV_negtest(const Erroneous_descriptor_t*
 boolean Record_Type::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td,
   const ASN_BER_TLV_t& p_tlv, unsigned L_form)
 {
-  bound_flag = TRUE;
   BER_chk_descr(p_td);
   ASN_BER_TLV_t stripped_tlv;
   BER_decode_strip_tags(*p_td.ber, p_tlv, L_form, stripped_tlv);
@@ -2943,7 +3199,6 @@ boolean Record_Type::BER_decode_TLV(const TTCN_Typedescriptor_t& p_td,
 
 void Record_Type::BER_decode_opentypes(TTCN_Type_list& p_typelist, unsigned L_form)
 {
-  bound_flag = TRUE;
   p_typelist.push(this);
   TTCN_EncDec_ErrorContext ec_0("Component '");
   TTCN_EncDec_ErrorContext ec_1;
@@ -3140,7 +3395,6 @@ int Record_Type::RAW_encode_negtest(const Erroneous_descriptor_t *p_err_descr,
 int Record_Type::RAW_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& buff,
   int limit, raw_order_t top_bit_ord, boolean no_err, int, boolean)
 {
-  bound_flag = TRUE;
   int field_cnt = get_count();
   int opt_cnt = optional_count();
   int mand_num = field_cnt - opt_cnt; // expected mandatory fields
@@ -3414,7 +3668,6 @@ int Record_Type::TEXT_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
 int Record_Type::TEXT_decode(const TTCN_Typedescriptor_t& p_td, TTCN_Buffer& buff,
   Limit_Token_List& limit, boolean no_err, boolean /*first_call*/)
 {
-  bound_flag = TRUE;
   if (is_set()) {
     int decoded_length=0;
     int decoded_field_length=0;
@@ -3851,10 +4104,10 @@ int Record_Type::get_index_byname(const char *name, const char *uri) const {
 }
 
 int Record_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf,
-  unsigned int flavor, int indent) const
+  unsigned int flavor, int indent, embed_values_enc_struct_t*) const
 {
   if (err_descr) {
-    return XER_encode_negtest(err_descr, p_td, p_buf, flavor, indent);
+    return XER_encode_negtest(err_descr, p_td, p_buf, flavor, indent, 0);
   }
   if (!is_bound()) {
     TTCN_EncDec_ErrorContext::error
@@ -3879,8 +4132,16 @@ int Record_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf,
   // start tag, i.e. the ">\n". This is used later to "back up" over it.
   int start_tag_len = 1 + indenting;
   // The EMBED-VALUES member, if applicable
-  const Record_Of_Type* const embed_values = (p_td.xer_bits & EMBED_VALUES)
-  ? static_cast<const Record_Of_Type*>(get_at(0)) : 0;
+  const Record_Of_Type* embed_values = 0;
+  if (p_td.xer_bits & EMBED_VALUES) {
+    embed_values = dynamic_cast<const Record_Of_Type*>(get_at(0));
+    if (NULL == embed_values) {
+      const OPTIONAL<Record_Of_Type>* const embed_opt = static_cast<const OPTIONAL<Record_Of_Type>*>(get_at(0));
+      if(embed_opt->is_present()) {
+        embed_values = &(*embed_opt)();
+      }
+    }
+  }
   // The USE-ORDER member, if applicable
   const Record_Of_Type* const use_order = (p_td.xer_bits & USE_ORDER)
   ? static_cast<const Record_Of_Type*>(get_at(uo_index)) : 0;
@@ -3940,7 +4201,7 @@ int Record_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf,
       - (!indenting || delay_close || (exer && (p_td.xer_bits & HAS_1UNTAGGED))),
       (cbyte*)p_td.names[exer]);
   }
-  else if (flavor & USE_TYPE_ATTR) {
+  else if (flavor & (USE_NIL|USE_TYPE_ATTR)) {
     // reopen the parent's start tag by overwriting the '>'
     size_t buf_len = p_buf.get_len();
     const unsigned char * const buf_data = p_buf.get_data();
@@ -3961,7 +4222,7 @@ int Record_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf,
     const Base_Type * const q_uri = get_at(0);
     if (q_uri->is_present()) {
       p_buf.put_s(11, (cbyte*)" xmlns:b0='");
-      q_uri->XER_encode(*xer_descr(0), p_buf, flavor | XER_LIST, indent+1);
+      q_uri->XER_encode(*xer_descr(0), p_buf, flavor | XER_LIST, indent+1, 0);
       p_buf.put_c('\'');
     }
 
@@ -3973,18 +4234,18 @@ int Record_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf,
       sub_len += 3;
     }
     const Base_Type* const q_name = get_at(1);
-    sub_len += q_name->XER_encode(*xer_descr(1), p_buf, flavor | XER_LIST, indent+1);
+    sub_len += q_name->XER_encode(*xer_descr(1), p_buf, flavor | XER_LIST, indent+1, 0);
     if (p_td.xer_bits & XER_ATTRIBUTE) p_buf.put_c('\'');
   }
   else { // not USE-QNAME
-    if (!exer && (p_td.xer_bits & EMBED_VALUES)) {
+    if (!exer && (p_td.xer_bits & EMBED_VALUES) && embed_values != NULL) {
       // The EMBED-VALUES member as an ordinary record of string
-      sub_len += embed_values->XER_encode(*xer_descr(0), p_buf, flavor, indent+1);
+      sub_len += embed_values->XER_encode(*xer_descr(0), p_buf, flavor, indent+1, 0);
     }
 
     if (!exer && (p_td.xer_bits & USE_ORDER)) {
       // The USE-ORDER member as an ordinary record of enumerated
-      sub_len += use_order->XER_encode(*xer_descr(uo_index), p_buf, flavor, indent+1);
+      sub_len += use_order->XER_encode(*xer_descr(uo_index), p_buf, flavor, indent+1, 0);
     }
 
     if (exer && (indent==0 || (flavor & DEF_NS_SQUASHED))) // write namespaces for toplevel only
@@ -4011,7 +4272,7 @@ int Record_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf,
     for (i = start_at; i < first_nonattr; ++i) {
       boolean is_xer_attr_field = xer_descr(i)->xer_bits & XER_ATTRIBUTE;
       ec_1.set_msg("%s': ", fld_name(i)); // attr
-      int tmp_len = get_at(i)->XER_encode(*xer_descr(i), p_buf, flavor, indent+1);
+      int tmp_len = get_at(i)->XER_encode(*xer_descr(i), p_buf, flavor, indent+1, 0);
       if (is_xer_attr_field && !exer) sub_len += tmp_len; /* do not add if attribute and EXER */
     }
 
@@ -4043,31 +4304,11 @@ int Record_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf,
       p_buf.put_s(start_tag_len , (cbyte*)">\n");
     }
 
-    int expected_embed = (field_cnt - first_nonattr + 1);
     if (exer && (p_td.xer_bits & EMBED_VALUES)) {
-      ec_1.set_msg("%s': ", fld_name(0));
-      int num_opt;
-      if ((p_td.xer_bits & USE_NIL) && !get_at(field_cnt-1)->ispresent()) {
-        expected_embed = 0; //25.2.6 a
-      }
-      else if ((num_opt = optional_count())) {
-        const int * optionals = get_optional_indexes();
-        for (int opt_idx = 0; opt_idx < num_opt; ++opt_idx) {
-          // skip optional attributes
-          if (optionals[opt_idx] < start_at + num_attributes) continue;
-          // reduce for each omitted member
-          if (!get_at(optionals[opt_idx])->is_present()) --expected_embed;
-        }
-      }
-      // Check the correct number of EMBED-VALUES (regular non-attributes + 1)
-      if (embed_values->size_of() != expected_embed)
-        TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT,
-          "Wrong number %d of EMBED-VALUEs, expected %d",
-          embed_values->size_of(), expected_embed);
       /* write the first string */
-      if (expected_embed > 0) {
+      if (embed_values != NULL && embed_values->size_of() > 0) {
         sub_len += embed_values->get_at(0)->XER_encode(UNIVERSAL_CHARSTRING_xer_,
-          p_buf, flavor | EMBED_VALUES, indent+1);
+          p_buf, flavor | EMBED_VALUES, indent+1, 0);
       }
     }
 
@@ -4093,9 +4334,8 @@ int Record_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf,
         ++n_optionals;
       }
 
-      int expected_min = field_cnt - first_nonattr - n_optionals;
       int expected_max = field_cnt - first_nonattr;
-
+      int expected_min = expected_max - n_optionals;
 
       if ((p_td.xer_bits & USE_NIL) && get_at(field_cnt-1)->ispresent()) {
         // The special case when USE_ORDER refers to the fields of a field,
@@ -4147,33 +4387,56 @@ int Record_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf,
      * pseudo-members for USE-ORDER, etc.) */
 
     // early_to_bed can only be true if exer is true (transitive through nil_attribute)
-    if (!early_to_bed) for ( i = begin; i < end; ++i ) {
-      const Base_Type *uoe = 0; // "useOrder enum"
-      const Enum_Type *enm = 0; // the enum value selecting the field
-      if (exer && use_order) {
-        uoe = use_order->get_at(i - begin);
-        enm = static_cast<const Enum_Type *>(uoe);
-      }
-
-      // "actual" index, may be perturbed by USE-ORDER
-      int ai = !(exer && (p_td.xer_bits & USE_ORDER)) ? i :
-      enm->as_int() + useorder_base;
-      ec_1.set_msg("%s': ", ordered->fld_name(ai)); // non-attr
-
-      const XERdescriptor_t& descr = *ordered->xer_descr(ai);
-      sub_len += ordered->get_at(ai)->XER_encode(descr, p_buf,
-        // Pass USE-NIL to the last field (except when USE-ORDER is also in effect,
-        // because the tag-stripping effect of USE-NIL has been achieved
-        // by encoding the sub-fields directly).
-        flavor | ((exer && !use_order && (i == field_cnt-1)) ? (p_td.xer_bits & USE_NIL) : 0),
-        indent+!omit_tag);
-
-      // Now the next embed-values string (NOT affected by USE-ORDER!)
-      if (exer && (p_td.xer_bits & EMBED_VALUES) && (i - begin + 1) < expected_embed) {
-        embed_values->get_at(i - begin + 1)->XER_encode(UNIVERSAL_CHARSTRING_xer_
-          , p_buf, flavor | EMBED_VALUES, indent+1);
-      }
-    } //for
+    if (!early_to_bed) {
+      embed_values_enc_struct_t* emb_val = 0;
+      if (exer && (p_td.xer_bits & EMBED_VALUES) && 
+          embed_values != NULL && embed_values->size_of() > 1) {
+        emb_val = new embed_values_enc_struct_t;
+        emb_val->embval_array = embed_values;
+        emb_val->embval_index = 1;
+        emb_val->embval_err = 0;
+      }
+      
+      for ( i = begin; i < end; ++i ) {
+        const Base_Type *uoe = 0; // "useOrder enum"
+        const Enum_Type *enm = 0; // the enum value selecting the field
+        if (exer && use_order) {
+          uoe = use_order->get_at(i - begin);
+          enm = static_cast<const Enum_Type *>(uoe);
+        }
+
+        // "actual" index, may be perturbed by USE-ORDER
+        int ai = !(exer && (p_td.xer_bits & USE_ORDER)) ? i :
+        enm->as_int() + useorder_base;
+        ec_1.set_msg("%s': ", ordered->fld_name(ai)); // non-attr
+
+        const XERdescriptor_t& descr = *ordered->xer_descr(ai);
+        sub_len += ordered->get_at(ai)->XER_encode(descr, p_buf,
+          // Pass USE-NIL to the last field (except when USE-ORDER is also in effect,
+          // because the tag-stripping effect of USE-NIL has been achieved
+          // by encoding the sub-fields directly).
+          flavor | ((exer && !use_order && (i == field_cnt-1)) ? (p_td.xer_bits & USE_NIL) : 0),
+          indent+!omit_tag, emb_val);
+
+        // Now the next embed-values string (NOT affected by USE-ORDER!)
+        if (exer && (p_td.xer_bits & EMBED_VALUES) && 0 != emb_val &&
+            embed_values != NULL && emb_val->embval_index < embed_values->size_of()) {
+          embed_values->get_at(emb_val->embval_index)->XER_encode(UNIVERSAL_CHARSTRING_xer_
+            , p_buf, flavor | EMBED_VALUES, indent+1, 0);
+          ++emb_val->embval_index;
+        }
+      } //for
+      
+      if (0 != emb_val) {
+        if (embed_values != NULL && emb_val->embval_index < embed_values->size_of()) {
+          ec_1.set_msg("%s': ", fld_name(0));
+          TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT,
+            "Too many EMBED-VALUEs specified: %d (expected %d or less)",
+            embed_values->size_of(), emb_val->embval_index);
+        }
+        delete emb_val;
+      }
+    } // if (!early_to_bed)
   } // if (QNAME)
 
   if (!omit_tag) {
@@ -4226,7 +4489,7 @@ int Record_Type::XER_encode(const XERdescriptor_t& p_td, TTCN_Buffer& p_buf,
  */
 int Record_Type::encode_field(int i,
   const Erroneous_values_t* err_vals, const Erroneous_descriptor_t* emb_descr,
-  TTCN_Buffer& p_buf, unsigned int sub_flavor, int indent) const
+  TTCN_Buffer& p_buf, unsigned int sub_flavor, int indent, embed_values_enc_struct_t* emb_val) const
 {
   int enc_len = 0;
   TTCN_EncDec_ErrorContext ec;
@@ -4240,7 +4503,7 @@ int Record_Type::encode_field(int i,
       if (err_vals->before->type_descr==NULL) TTCN_error(
         "internal error: erroneous before typedescriptor missing");
       enc_len += err_vals->before->errval->XER_encode(
-        *err_vals->before->type_descr->xer, p_buf, sub_flavor, indent);
+        *err_vals->before->type_descr->xer, p_buf, sub_flavor, indent, 0);
     }
   }
 
@@ -4253,18 +4516,18 @@ int Record_Type::encode_field(int i,
         if (err_vals->value->type_descr==NULL) TTCN_error(
           "internal error: erroneous value typedescriptor missing");
         enc_len += err_vals->value->errval->XER_encode(
-          *err_vals->value->type_descr->xer, p_buf, sub_flavor, indent);
+          *err_vals->value->type_descr->xer, p_buf, sub_flavor, indent, 0);
       }
     } // else -> omit
   } else {
     ec.set_msg("Component %s: ", fld_name(i));
     if (emb_descr) {
       enc_len += get_at(i)->XER_encode_negtest(emb_descr, *xer_descr(i), p_buf,
-        sub_flavor, indent);
+        sub_flavor, indent, emb_val);
     } else {
       // the "real" encoder
       enc_len += get_at(i)->XER_encode(*xer_descr(i), p_buf,
-        sub_flavor, indent);
+        sub_flavor, indent, emb_val);
     }
   }
 
@@ -4278,7 +4541,7 @@ int Record_Type::encode_field(int i,
       if (err_vals->after->type_descr==NULL) TTCN_error(
         "internal error: erroneous after typedescriptor missing");
       enc_len += err_vals->after->errval->XER_encode(
-        *err_vals->after->type_descr->xer, p_buf, sub_flavor, indent);
+        *err_vals->after->type_descr->xer, p_buf, sub_flavor, indent, 0);
     }
   }
 
@@ -4287,7 +4550,8 @@ int Record_Type::encode_field(int i,
 
 // XERSTUFF Record_Type::XER_encode_negtest
 int Record_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
-  const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, unsigned int flavor, int indent) const
+  const XERdescriptor_t& p_td, TTCN_Buffer& p_buf, unsigned int flavor, int indent,
+  embed_values_enc_struct_t*) const
 {
   if (!is_bound()) {
     TTCN_EncDec_ErrorContext::error
@@ -4411,7 +4675,7 @@ int Record_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
         if (ev->before->type_descr==NULL) TTCN_error(
           "internal error: erroneous before typedescriptor missing");
         sub_len += ev->before->errval->XER_encode(
-          *ev->before->type_descr->xer, p_buf, flavor, indent);
+          *ev->before->type_descr->xer, p_buf, flavor, indent, 0);
       }
     }
 
@@ -4424,7 +4688,7 @@ int Record_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
           if (ev->value->type_descr==NULL) TTCN_error(
             "internal error: erroneous value typedescriptor missing");
           sub_len += ev->value->errval->XER_encode(
-            *ev->value->type_descr->xer, p_buf, flavor, indent);
+            *ev->value->type_descr->xer, p_buf, flavor, indent, 0);
         }
       } // else -> omit
     } else {
@@ -4438,7 +4702,7 @@ int Record_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
         // the "real" encoder
         if (q_uri->is_present()) {
           p_buf.put_s(11, (cbyte*)" xmlns:b0='");
-          sub_len += q_uri->XER_encode(*xer_descr(0), p_buf, flavor | XER_LIST, indent+1);
+          sub_len += q_uri->XER_encode(*xer_descr(0), p_buf, flavor | XER_LIST, indent+1, 0);
           p_buf.put_c('\'');
         }
       }
@@ -4454,7 +4718,7 @@ int Record_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
         if (ev->after->type_descr==NULL) TTCN_error(
           "internal error: erroneous after typedescriptor missing");
         sub_len += ev->after->errval->XER_encode(
-          *ev->after->type_descr->xer, p_buf, flavor, indent);
+          *ev->after->type_descr->xer, p_buf, flavor, indent, 0);
       }
     }
 
@@ -4475,7 +4739,7 @@ int Record_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
         if (ev->before->type_descr==NULL) TTCN_error(
           "internal error: erroneous before typedescriptor missing");
         sub_len += ev->before->errval->XER_encode(
-          *ev->before->type_descr->xer, p_buf, flavor, indent);
+          *ev->before->type_descr->xer, p_buf, flavor, indent, 0);
       }
     }
 
@@ -4488,7 +4752,7 @@ int Record_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
           if (ev->value->type_descr==NULL) TTCN_error(
             "internal error: erroneous value typedescriptor missing");
           sub_len += ev->value->errval->XER_encode(
-            *ev->value->type_descr->xer, p_buf, flavor, indent);
+            *ev->value->type_descr->xer, p_buf, flavor, indent, 0);
         }
       } // else -> omit
     } else {
@@ -4503,7 +4767,7 @@ int Record_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
           sub_len += 3;
         }
 
-        sub_len += get_at(1)->XER_encode(*xer_descr(1), p_buf, flavor | XER_LIST, indent+1);
+        sub_len += get_at(1)->XER_encode(*xer_descr(1), p_buf, flavor | XER_LIST, indent+1, 0);
       }
     }
 
@@ -4517,7 +4781,7 @@ int Record_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
         if (ev->after->type_descr==NULL) TTCN_error(
           "internal error: erroneous after typedescriptor missing");
         sub_len += ev->after->errval->XER_encode(
-          *ev->after->type_descr->xer, p_buf, flavor, indent);
+          *ev->after->type_descr->xer, p_buf, flavor, indent, 0);
       }
     }
 
@@ -4526,12 +4790,12 @@ int Record_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
   else { // not USE-QNAME
     if (!exer && (p_td.xer_bits & EMBED_VALUES)) {
       // The EMBED-VALUES member as an ordinary record of string
-      sub_len += embed_values->XER_encode(*xer_descr(0), p_buf, flavor, indent+1);
+      sub_len += embed_values->XER_encode(*xer_descr(0), p_buf, flavor, indent+1, 0);
     }
 
     if (!exer && (p_td.xer_bits & USE_ORDER)) {
       // The USE-ORDER member as an ordinary record of enumerated
-      sub_len += use_order->XER_encode(*xer_descr(uo_index), p_buf, flavor, indent+1);
+      sub_len += use_order->XER_encode(*xer_descr(uo_index), p_buf, flavor, indent+1, 0);
     }
 
     if (exer && (indent==0 || (flavor & DEF_NS_SQUASHED))) // write namespaces for toplevel only
@@ -4572,7 +4836,7 @@ int Record_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
       boolean is_xer_attr_field = xer_descr(i)->xer_bits & XER_ATTRIBUTE;
       ec_1.set_msg("%s': ", fld_name(i)); // attr
 
-      tmp_len = encode_field(i, ev, ed, p_buf, flavor, indent + !omit_tag);
+      tmp_len = encode_field(i, ev, ed, p_buf, flavor, indent + !omit_tag, 0);
 
       if (is_xer_attr_field && !exer) sub_len += tmp_len; // do not add if attribute and EXER
 
@@ -4637,39 +4901,19 @@ int Record_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
     int embed_values_val_idx = 0;
     int embed_values_descr_idx = 0;
 
-    int expected_embed = (field_cnt - first_nonattr + 1);
     if (exer && (p_td.xer_bits & EMBED_VALUES)) {
       ed0 = p_err_descr->next_field_emb_descr(0, edescr_idx);
 
-      ec_1.set_msg("%s': ", fld_name(0));
-      int num_opt;
-      if ((p_td.xer_bits & USE_NIL) && !get_at(field_cnt-1)->ispresent()) {
-        expected_embed = 0; //25.2.6 a
-      }
-      else if ((num_opt = optional_count()) > 0) {
-        const int * optionals = get_optional_indexes();
-        for (int opt_idx = 0; opt_idx < num_opt; ++opt_idx) {
-          // skip optional attributes
-          if (optionals[opt_idx] < start_at + num_attributes) continue;
-          // reduce for each omitted member
-          if (!get_at(optionals[opt_idx])->is_present()) --expected_embed;
-        }
-      }
-      // Check the correct number of EMBED-VALUES (regular non-attributes + 1)
-      if (embed_values->size_of() != expected_embed)
-        TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT,
-          "Wrong number %d of EMBED-VALUEs, expected %d",
-          embed_values->size_of(), expected_embed);
       // write the first string
-      if (expected_embed > 0) {
+      if (embed_values->size_of() > 0) {
         const Erroneous_values_t    * ev0_0 = NULL;
         const Erroneous_descriptor_t* ed0_0 = NULL;
         if (ed0) {
           ev0_0 = ed0->next_field_err_values(0, embed_values_val_idx);
           ed0_0 = ed0->next_field_emb_descr (0, embed_values_descr_idx);
         }
-        sub_len += embed_values->encode_element(0, ev0_0, ed0_0,
-          p_buf, flavor | EMBED_VALUES, indent+!omit_tag);
+        sub_len += embed_values->encode_element(0, UNIVERSAL_CHARSTRING_xer_,
+          ev0_0, ed0_0, p_buf, flavor | EMBED_VALUES, indent+!omit_tag, 0);
       }
     }
 
@@ -4757,64 +5001,86 @@ int Record_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
     // fields of this record; and the USE_ORDER case (with or without USE-NIL).
     //
     // early_to_bed can only be true if exer is true (transitive through nil_attribute)
-    if (!early_to_bed) for ( i = begin; i < end; ++i ) {
-
-      const Base_Type *uoe = 0; // "useOrder enum"
-      const Enum_Type *enm = 0; // the enum value selecting the field
-
-      // "actual" index, may be perturbed by USE-ORDER.
-      // We use this value to index the appropriate record.
-      int ai = i;
-
-      const Erroneous_values_t    * ev = NULL;
-      const Erroneous_descriptor_t* ed = NULL;
-      if (exer && use_order) {
-        // If USE-ORDER is in effect, it introduces a level of indirection
-        // into the indexing of fields: "i" is used to select an element
-        // of the use_order member (an enum), whose value is used to select
-        // the field being encoded.
-        uoe = use_order->get_at(i - begin);
-        enm = static_cast<const Enum_Type *>(uoe);
-        ai = enm->as_int() + useorder_base;
-
-        // Because it is not guaranteed that ai will increase monotonically,
-        // we can't use next_field_...().
-        ev = p_err_descr->get_field_err_values(ai);
-        ed = p_err_descr->get_field_emb_descr (ai);
-      }
-      else { // not USE-ORDER, sequential access
-        ev = p_err_descr->next_field_err_values(ai, values_idx);
-        ed = p_err_descr->next_field_emb_descr (ai, edescr_idx);
-      }
-      ec_1.set_msg("%s': ", ordered->fld_name(ai)); // non-attr
-
-      if (ai < p_err_descr->omit_before) continue;
-
-      // omit_after value -1 becomes "very big".
-      if ((unsigned int)ai > (unsigned int)p_err_descr->omit_after) continue;
-      // We can't skip all fields with break, because the next ai may be lower
-      // than omit_after.
-
-      sub_len += ordered->encode_field(ai, ev, ed, p_buf,
-        // Pass USE-NIL to the last field (except when USE-ORDER is also in effect,
-        // because the tag-stripping effect of USE-NIL has been achieved
-        // by encoding the sub-fields directly).
-        flavor | ((exer && !use_order && (i == field_cnt-1)) ? (p_td.xer_bits & USE_NIL) : 0),
-        indent + !omit_tag);
-
-      // Now the next embed-values string (NOT affected by USE-ORDER!)
-      int i1 = i - begin + 1;
-      if (exer && (p_td.xer_bits & EMBED_VALUES) && i1 < expected_embed) {
-        const Erroneous_values_t    * ev0_i = NULL;
-        const Erroneous_descriptor_t* ed0_i = NULL;
-        if (ed0) {
-          ev0_i = ed0->next_field_err_values(i1, embed_values_val_idx);
-          ed0_i = ed0->next_field_emb_descr (i1, embed_values_descr_idx);
+    if (!early_to_bed) {
+      embed_values_enc_struct_t* emb_val = 0;
+      if (exer && (p_td.xer_bits & EMBED_VALUES) && embed_values->size_of() > 1) {
+        emb_val = new embed_values_enc_struct_t;
+        emb_val->embval_array = embed_values;
+        emb_val->embval_index = 1;
+        emb_val->embval_err = ed0;
+        emb_val->embval_err_val_idx = embed_values_val_idx;
+        emb_val->embval_err_descr_idx = embed_values_descr_idx;
+      }
+      
+      for ( i = begin; i < end; ++i ) {
+
+        const Base_Type *uoe = 0; // "useOrder enum"
+        const Enum_Type *enm = 0; // the enum value selecting the field
+
+        // "actual" index, may be perturbed by USE-ORDER.
+        // We use this value to index the appropriate record.
+        int ai = i;
+
+        const Erroneous_values_t    * ev = NULL;
+        const Erroneous_descriptor_t* ed = NULL;
+        if (exer && use_order) {
+          // If USE-ORDER is in effect, it introduces a level of indirection
+          // into the indexing of fields: "i" is used to select an element
+          // of the use_order member (an enum), whose value is used to select
+          // the field being encoded.
+          uoe = use_order->get_at(i - begin);
+          enm = static_cast<const Enum_Type *>(uoe);
+          ai = enm->as_int() + useorder_base;
+
+          // Because it is not guaranteed that ai will increase monotonically,
+          // we can't use next_field_...().
+          ev = p_err_descr->get_field_err_values(ai);
+          ed = p_err_descr->get_field_emb_descr (ai);
+        }
+        else { // not USE-ORDER, sequential access
+          ev = p_err_descr->next_field_err_values(ai, values_idx);
+          ed = p_err_descr->next_field_emb_descr (ai, edescr_idx);
+        }
+        ec_1.set_msg("%s': ", ordered->fld_name(ai)); // non-attr
+
+        if (ai < p_err_descr->omit_before) continue;
+
+        // omit_after value -1 becomes "very big".
+        if ((unsigned int)ai > (unsigned int)p_err_descr->omit_after) continue;
+        // We can't skip all fields with break, because the next ai may be lower
+        // than omit_after.
+
+        sub_len += ordered->encode_field(ai, ev, ed, p_buf,
+          // Pass USE-NIL to the last field (except when USE-ORDER is also in effect,
+          // because the tag-stripping effect of USE-NIL has been achieved
+          // by encoding the sub-fields directly).
+          flavor | ((exer && !use_order && (i == field_cnt-1)) ? (p_td.xer_bits & USE_NIL) : 0),
+          indent + !omit_tag, emb_val);
+
+        // Now the next embed-values string (NOT affected by USE-ORDER!)
+        if (exer && (p_td.xer_bits & EMBED_VALUES) && 0 != emb_val &&
+            emb_val->embval_index < embed_values->size_of()) {
+          const Erroneous_values_t    * ev0_i = NULL;
+          const Erroneous_descriptor_t* ed0_i = NULL;
+          if (ed0) {
+            ev0_i = ed0->next_field_err_values(emb_val->embval_index, emb_val->embval_err_val_idx);
+            ed0_i = ed0->next_field_emb_descr (emb_val->embval_index, emb_val->embval_err_descr_idx);
+          }
+          embed_values->encode_element(emb_val->embval_index, UNIVERSAL_CHARSTRING_xer_,
+            ev0_i, ed0_i, p_buf, flavor | EMBED_VALUES, indent + !omit_tag, 0);
+          ++emb_val->embval_index;
         }
-        embed_values->encode_element(i1, ev0_i, ed0_i,
-          p_buf, flavor | EMBED_VALUES, indent + !omit_tag);
+      } //for
+      if (0 != emb_val) {
+        if (emb_val->embval_index < embed_values->size_of()) {
+          ec_1.set_msg("%s': ", fld_name(0));
+          TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_CONSTRAINT,
+            "Too many EMBED-VALUEs specified: %d (expected %d or less)",
+            embed_values->size_of(), emb_val->embval_index);
+        }
+        delete emb_val;
       }
-    } //for
+    } // if (!early_to_bed)
   } // if (QNAME)
 
 
@@ -4850,9 +5116,9 @@ int Record_Type::XER_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
   return (int)p_buf.get_len() - encoded_length;
 }
 
-int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader, unsigned int flavor)
+int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
+                            unsigned int flavor, unsigned int flavor2, embed_values_dec_struct_t*)
 {
-  bound_flag = TRUE;
   int exer = is_exer(flavor);
   int success, type;
   int depth=-1; // depth of the start tag
@@ -4864,10 +5130,11 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
   boolean tag_closed = (flavor & PARENT_CLOSED) != 0;
   // If the parent has USE-TYPE, our ATTRIBUTE members can be found
   // in the parent's tag (the reader is sitting on it).
-  const boolean parent_tag = exer && (flavor & (/*USE_NIL|*/ USE_TYPE_ATTR));
+  const boolean parent_tag = exer && ((flavor & USE_TYPE_ATTR) || (flavor2 & USE_NIL_PARENT_TAG));
 
   // Filter out flags passed by our parent. These are not for the fields.
   flavor &= XER_MASK; // also removes XER_TOPLEVEL
+  flavor2 = XER_NONE; // Remove only bit: USE_NIL_PARENT_TAG (for now)
 
   const int field_cnt = get_count();
   const int num_attributes = get_xer_num_attr();
@@ -4880,13 +5147,15 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
   // fields); normal processing start at this field.
   const int start_at = uo_index + ((p_td.xer_bits & USE_ORDER) != 0);
   const int first_nonattr = start_at + num_attributes;
-
+  
   // The index of the ANY-ATTRIBUTES member, if any
   int aa_index = -1;
   for (int k = 0; k < first_nonattr; ++k) {
     if (xer_descr(k)->xer_bits & ANY_ATTRIBUTES) {
       aa_index = k;
-      static_cast<Record_Of_Type*>(get_at(aa_index))->set_size(0);
+      if (!get_at(aa_index)->is_optional()) {
+        static_cast<Record_Of_Type*>(get_at(aa_index))->set_size(0);
+      }
       break; // there can be only one, 18.2.2
     }
   }
@@ -4946,12 +5215,15 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
     TTCN_EncDec_ErrorContext ec_0("Component '");
     TTCN_EncDec_ErrorContext ec_1;
     boolean usenil_attribute = FALSE; // true if found and said yes
+    // If nillable and the nillable field is a record type, that has attributes
+    // then it will become true, and skips the processing of the fields after
+    boolean already_processed = FALSE;
     if (!exer) {
       if (!reader.IsEmptyElement()) reader.Read();
       // First, the (would-be) attributes (unaffected by USE-ORDER)
       for (i = 0; i < first_nonattr; i++) {
         ec_1.set_msg("%s': ", fld_name(i));
-        get_at(i)->XER_decode(*xer_descr(i), reader, flavor);
+        get_at(i)->XER_decode(*xer_descr(i), reader, flavor, flavor2, 0);
       } // next field
     }
     else if (own_tag || parent_tag) { // EXER and not UNTAGGED: do attributes
@@ -4979,7 +5251,12 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
       }
 
       /* * * * * * * * * Attributes * * * * * * * * * * * * * */
-      for (success = reader.MoveToFirstAttribute();
+      if(parent_tag && reader.NodeType() == XML_READER_TYPE_ATTRIBUTE) {
+        success = reader.Ok();
+      } else {
+        success = reader.MoveToFirstAttribute();
+      }
+      for (;
         success == 1 && reader.NodeType() == XML_READER_TYPE_ATTRIBUTE;
         success = reader.AdvanceAttribute())
       {
@@ -4993,7 +5270,7 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
         if (field_index != -1) {
           // There is a field. Let it decode the attribute.
           ec_1.set_msg("%s': ", fld_name(field_index));
-          get_at(field_index)->XER_decode(*xer_descr(field_index), reader, flavor);
+          get_at(field_index)->XER_decode(*xer_descr(field_index), reader, flavor, flavor2, 0);
           continue;
         }
 
@@ -5015,8 +5292,13 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
 
             continue;
           } // it is the "nil" attribute
+          // else, let the nillable field decode the next attributes, it is possible
+          // that it belongs to him
+          get_at(field_cnt-1)->XER_decode(*xer_descr(field_cnt-1), reader, flavor | USE_NIL, flavor2 | USE_NIL_PARENT_TAG, 0);
+          already_processed = TRUE;
+          break;
         } // type has USE-NIL
-
+        
         if (parent_tag) {
           const char *prefix = (const char*)reader.Prefix();
           // prefix may be NULL, control_ns->px is never NULL or empty
@@ -5031,7 +5313,16 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
           TTCN_EncDec_ErrorContext ec_2("Attribute %d: ", num_aa);
           // We have a component with ANY-ATTRIBUTE. It must be a record of
           // UNIVERSAL_CHARSTRING. Add the attribute to it.
-          Record_Of_Type *aa = static_cast<Record_Of_Type *>(get_at(aa_index));
+          Record_Of_Type *aa = 0;
+          if (get_at(aa_index)->is_optional()) {
+            if (num_aa == 0) {
+              get_at(aa_index)->set_to_present();
+            }
+            aa = static_cast<Record_Of_Type*>(get_at(aa_index)->get_opt_value());
+          }
+          else {
+            aa = static_cast<Record_Of_Type*>(get_at(aa_index));
+          }
           UNIVERSAL_CHARSTRING *new_elem = static_cast<UNIVERSAL_CHARSTRING *>
           (aa->get_at(num_aa++));
 
@@ -5068,7 +5359,7 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
             continue;
           }
         }
-
+        
         // Nobody wanted the attribute. That is an error.
         ec_0.set_msg(" "); ec_1.set_msg(" ");
         TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,
@@ -5087,14 +5378,25 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
       }
 
       i = first_nonattr; // finished with attributes
-      // AdvanceAttribute did MoveToElement. Move into the content (if any).
-      if (!reader.IsEmptyElement()) reader.Read();
+      // AdvanceAttribute did MoveToElement. Move into the content (if any),
+      // except when the reader is already moved in(already_processed).
+      if (!reader.IsEmptyElement() && !already_processed) reader.Read();
     } // end if (own_tag)
-
+    
     /* * * * * * * * Non-attributes (elements) * * * * * * * * * * * */
-    Record_Of_Type* embed_values = 0;
+    embed_values_dec_struct_t* emb_val = 0;
+    bool emb_val_optional = false;
     if (exer && (p_td.xer_bits & EMBED_VALUES)) {
-      embed_values = static_cast<Record_Of_Type*>(get_at(0));
+      emb_val = new embed_values_dec_struct_t;
+      emb_val->embval_array = dynamic_cast<Record_Of_Type*>(get_at(0));
+      if (NULL == emb_val->embval_array) {
+        OPTIONAL<PreGenRecordOf::PREGEN__RECORD__OF__UNIVERSAL__CHARSTRING>* embed_value = static_cast<OPTIONAL<PreGenRecordOf::PREGEN__RECORD__OF__UNIVERSAL__CHARSTRING>*>(get_at(0));
+        embed_value->set_to_present();
+        emb_val->embval_array = static_cast<Record_Of_Type*>((*embed_value).get_opt_value());
+        emb_val_optional = true;
+      }
+      emb_val->embval_array->set_size(0);
+      emb_val->embval_index = 0;
     }
 
     if (exer && (p_td.xer_bits & USE_ORDER)) {
@@ -5107,90 +5409,79 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
         get_at(oi)->set_to_omit();
         ++n_optionals;
       }
+
       Record_Of_Type *use_order = static_cast<Record_Of_Type*>(get_at(uo_index));
       // Initialize the use_order field to empty. Let it grow on demand.
       // (setting it to the minimum acceptable size may leave unbound elements
       // if the XML was incomplete).
       use_order->set_size(0);
 
-      Record_Type *jumbled = this; // the record affected by USE_ORDER
-      int begin = first_nonattr;
-      int end   = field_cnt; // "one past"
-      if (p_td.xer_bits & USE_NIL) {
-        Base_Type *last_optional = get_at(field_cnt-1);
-        if (!usenil_attribute) { // exer known true
-          last_optional->set_to_present();
-          jumbled = static_cast<Record_Type*>(last_optional->get_opt_value());
-          // We will operate on the members of last_optional,
-          // effectively bypassing last_optional->XER_decode() itself.
-          begin = 0;
-          end   = jumbled->get_count();
-          ec_1.set_msg("%s': ", fld_name(field_cnt-1));
+      // Nothing to order if there are no child elements
+      if (!tag_closed) {
+        Record_Type *jumbled = this; // the record affected by USE_ORDER
+        int begin = first_nonattr;
+        int end   = field_cnt; // "one past"
+        if (p_td.xer_bits & USE_NIL) {
+          Base_Type *last_optional = get_at(field_cnt-1);
+          if (!usenil_attribute) { // exer known true
+            last_optional->set_to_present();
+            jumbled = static_cast<Record_Type*>(last_optional->get_opt_value());
+            // We will operate on the members of last_optional,
+            // effectively bypassing last_optional->XER_decode() itself.
+            begin = 0;
+            end   = jumbled->get_count();
+            ec_1.set_msg("%s': ", fld_name(field_cnt-1));
+          }
         }
-      }
-      if (num_attributes > 0
-        && first_nonattr != field_cnt
-        && i == first_nonattr - 1) { // exer known true
-        // If there were attributes and their processing just finished,
-        // the reader is positioned on the start tag of the record.
-        // Move ahead, unless there are no non-attribute fields.
-        reader.Read();
-      }
-      // Then, the non-attributes
-
-      // The index runs over the members affected by USE-ORDER.
-      // This is [first_nonattr,field_cnt) unless USE-NIL is involved,
-      // in which case it's [0,optional_sequence::field_cnt)
-      int *seen = new int[end-begin];
-      int num_seen = 0;
-      int last_any_elem = begin - 1;
-      for (i = begin; i < end; i++) {
-        for (success = reader.Ok(); success == 1; success = reader.Read()) {
-          type = reader.NodeType();
-          if (embed_values) {
-            if (reader.NodeType()==XML_READER_TYPE_TEXT) {
+        if (num_attributes > 0
+          && first_nonattr != field_cnt
+          && i == first_nonattr - 1) { // exer known true
+          // If there were attributes and their processing just finished,
+          // the reader is positioned on the start tag of the record.
+          // Move ahead, unless there are no non-attribute fields.
+          reader.Read();
+        }
+        // Then, the non-attributes
+
+        // The index runs over the members affected by USE-ORDER.
+        // This is [first_nonattr,field_cnt) unless USE-NIL is involved,
+        // in which case it's [0,optional_sequence::field_cnt)
+        int *seen = new int[end-begin];
+        int num_seen = 0;
+        int last_any_elem = begin - 1;
+        // The index of the latest embedded value can change outside of this function
+        // (if the field is an untagged record of), in this case the next value should
+        // be ignored, as it's already been handled by the record of
+        int last_embval_index = 0;
+        bool early_exit = false;
+        for (i = begin; i < end; i++) {
+          for (success = reader.Ok(); success == 1; success = reader.Read()) {
+            type = reader.NodeType();
+            if (0 != emb_val && reader.NodeType()==XML_READER_TYPE_TEXT) {
               UNIVERSAL_CHARSTRING emb_ustr((const char*)reader.Value());
-              embed_values->get_at(i-begin)->set_value(&emb_ustr);
+              emb_val->embval_array->get_at(emb_val->embval_index)->set_value(&emb_ustr);
+            }
+            // The non-attribute components must not be UNTAGGED
+            if (type == XML_READER_TYPE_ELEMENT) break;
+            if (type == XML_READER_TYPE_END_ELEMENT) {
+              early_exit = true;
+              break;
             }
           }
-          // The non-attribute components must not be UNTAGGED
-          if (type == XML_READER_TYPE_ELEMENT) break;
-          // else if (type==XML_READER_TYPE_END_ELEMENT) panic?
-        }
-        if (success != 1) break;
-        const char *name = (const char *)reader.LocalName();
-        boolean field_name_found = false;
-        // Find out which member it is.
-        // FIXME some hashing should be implemented
-        for (int k = begin; k < end; k++) {
-          if (!(jumbled->xer_descr(k)->xer_bits & ANY_ELEMENT) &&
-              check_name(name, *jumbled->xer_descr(k), 1)) {
-            ec_1.set_msg("%s': ", jumbled->fld_name(k));
-
-            // Check for the same field being decoded twice.
-            // We can't use the field's is_bound()/is_present(),
-            // because the field may be bound on input, e.g. for
-            // prototype(fast) or prototype(backtrack).
-            int in_dex = k - begin;
-            for (int o = 0; o < num_seen ;++o) {
-              if (in_dex == seen[o]) TTCN_EncDec_ErrorContext::error(
-                TTCN_EncDec::ET_INVAL_MSG, "Duplicate element");
+          if (0 != emb_val) {
+            if (last_embval_index == emb_val->embval_index) {
+              ++emb_val->embval_index;
             }
-            seen[num_seen++] = in_dex;
-            // Set the next use-order member.
-            // Non-const get_at creates the object in the record-of.
-            static_cast<Enum_Type*>(use_order->get_at(i - begin))
-            ->from_int(in_dex);
-            Base_Type *b = jumbled->get_at(k);
-            b->XER_decode(*jumbled->xer_descr(k), reader, flavor);
-            field_name_found = true;
-            break;
+            last_embval_index = emb_val->embval_index;
           }
-        }
-        if (!field_name_found) {
-          // Check the anyElement fields
-          for (int k = last_any_elem + 1; k < end; k++) {
-            if (jumbled->xer_descr(k)->xer_bits & ANY_ELEMENT) {
+          if (success != 1 || early_exit) break;
+          const char *name = (const char *)reader.LocalName();
+          bool field_name_found = false;
+          // Find out which member it is.
+          // FIXME some hashing should be implemented
+          for (int k = begin; k < end; k++) {
+            if (!(jumbled->xer_descr(k)->xer_bits & ANY_ELEMENT) &&
+                check_name(name, *jumbled->xer_descr(k), 1)) {
               ec_1.set_msg("%s': ", jumbled->fld_name(k));
 
               // Check for the same field being decoded twice.
@@ -5208,55 +5499,98 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
               static_cast<Enum_Type*>(use_order->get_at(i - begin))
               ->from_int(in_dex);
               Base_Type *b = jumbled->get_at(k);
-              b->XER_decode(*jumbled->xer_descr(k), reader, flavor);
-              last_any_elem = k;
+              b->XER_decode(*jumbled->xer_descr(k), reader, flavor, flavor2, emb_val);
+              field_name_found = true;
               break;
             }
           }
+          if (!field_name_found) {
+            // Check the anyElement fields
+            for (int k = last_any_elem + 1; k < end; k++) {
+              if (jumbled->xer_descr(k)->xer_bits & ANY_ELEMENT) {
+                ec_1.set_msg("%s': ", jumbled->fld_name(k));
+
+                // Check for the same field being decoded twice.
+                // We can't use the field's is_bound()/is_present(),
+                // because the field may be bound on input, e.g. for
+                // prototype(fast) or prototype(backtrack).
+                int in_dex = k - begin;
+                for (int o = 0; o < num_seen ;++o) {
+                  if (in_dex == seen[o]) TTCN_EncDec_ErrorContext::error(
+                    TTCN_EncDec::ET_INVAL_MSG, "Duplicate element");
+                }
+                seen[num_seen++] = in_dex;
+                // Set the next use-order member.
+                // Non-const get_at creates the object in the record-of.
+                static_cast<Enum_Type*>(use_order->get_at(i - begin))
+                ->from_int(in_dex);
+                Base_Type *b = jumbled->get_at(k);
+                b->XER_decode(*jumbled->xer_descr(k), reader, flavor, flavor2, emb_val);
+                last_any_elem = k;
+                field_name_found = true;
+                break;
+              }
+            }
+          }
+          if (!field_name_found) {
+            TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INVAL_MSG,
+              "Bad XML tag '%s' instead of a valid field", name);
+            break;
+          }
+        } // next field
+        if (0 != emb_val) {
+          if (reader.NodeType()==XML_READER_TYPE_TEXT) {
+            UNIVERSAL_CHARSTRING emb_ustr((const char*)reader.Value());
+            emb_val->embval_array->get_at(emb_val->embval_index)->set_value(&emb_ustr);
+          }
+          if (last_embval_index == emb_val->embval_index) {
+            ++emb_val->embval_index;
+          }
         }
-      } // next field
-      if (embed_values) {
-        if (reader.NodeType()==XML_READER_TYPE_TEXT) {
-          UNIVERSAL_CHARSTRING emb_ustr((const char*)reader.Value());
-          embed_values->get_at(i-begin)->set_value(&emb_ustr);
-        }
-      }
-      delete [] seen;
-      ec_1.set_msg(" "); // no active component
-      ec_0.set_msg(" ");
-
-      // Check that we collected the required number of children
-      int num_collected = use_order->size_of();
-      if (p_td.xer_bits & USE_NIL) {
-        int expected = usenil_attribute ? 0 : jumbled->get_count();
-        if (num_collected != expected) {
-          TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INCOMPL_MSG,
-            "Incorrect number of fields %d, expected %d",
-            num_collected, expected);
+        delete [] seen;
+        ec_1.set_msg(" "); // no active component
+        ec_0.set_msg(" ");
+
+        // Check that we collected the required number of children
+        int num_collected = use_order->size_of();
+        if (p_td.xer_bits & USE_NIL) {
+          int expected = usenil_attribute ? 0 : jumbled->get_count();
+          if (num_collected != expected) {
+            TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INCOMPL_MSG,
+              "Incorrect number of fields %d, expected %d",
+              num_collected, expected);
+          }
         }
-      }
-      else {
-        if (num_collected < field_cnt - first_nonattr - n_optionals
-          ||num_collected > field_cnt - first_nonattr) {
-          TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INCOMPL_MSG,
-            "Wrong number of fields! size = %d, expected %d..%d",
-            use_order->size_of(), field_cnt - first_nonattr - n_optionals,
-            field_cnt - first_nonattr);
+        else {
+          if (num_collected < field_cnt - first_nonattr - n_optionals
+            ||num_collected > field_cnt - first_nonattr) {
+            TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INCOMPL_MSG,
+              "Wrong number of fields! size = %d, expected %d..%d",
+              use_order->size_of(), field_cnt - first_nonattr - n_optionals,
+              field_cnt - first_nonattr);
+          }
         }
-      }
+      } // not empty element
     }
     else { // not USE-ORDER, simpler code      
       if (usenil_attribute) {
         reader.MoveToElement(); // value absent, nothing more to do
       } else {
-        int emb_idx = 0;
+        // The index of the latest embedded value can change outside of this function
+        // (if the field is a untagged record of), in this case the next value should
+        // be ignored, as it's already been handled by the record of
+        // Omitted fields can also reset this value
+        int last_embval_index = 0;
         for (; i<field_cnt; i++) {
-          if (embed_values) {
+          if (0 != emb_val) {
             if (reader.NodeType()==XML_READER_TYPE_TEXT) {
               UNIVERSAL_CHARSTRING emb_ustr((const char*)reader.Value());
-              embed_values->get_at(emb_idx)->set_value(&emb_ustr);
+              emb_val->embval_array->get_at(emb_val->embval_index)->set_value(&emb_ustr);
+            }
+            if (last_embval_index == emb_val->embval_index) {
+              ++emb_val->embval_index;
             }
-            emb_idx++;
+            last_embval_index = emb_val->embval_index;
           }
           ec_1.set_msg("%s': ", fld_name(i));
           if (exer && i==field_cnt-1 && p_td.dfeValue && reader.IsEmptyElement()) {
@@ -5276,47 +5610,58 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
                 optional_any_elem_check = opt_field->XER_check_any_elem(reader, next_field_name, tag_closed);
               }
             }
-            if (optional_any_elem_check) {
+            if (optional_any_elem_check && !already_processed) {
               int new_flavor = flavor ;
               if (i == field_cnt-1) new_flavor |= (p_td.xer_bits & USE_NIL);
               if (tag_closed)       new_flavor |= PARENT_CLOSED;
 
-              get_at(i)->XER_decode(*xer_descr(i), reader, new_flavor);
+              get_at(i)->XER_decode(*xer_descr(i), reader, new_flavor, flavor2, emb_val);
             }
           }
+          if (!get_at(i)->is_present()) {
+            // there was no new element, the last embedded value is for the next field
+            // (or the end of the record if this is the last field) 
+            last_embval_index = -1;
+          }
         } // next field
-        if (embed_values) {
+        if (0 != emb_val) {
           if (reader.NodeType()==XML_READER_TYPE_TEXT) {
             UNIVERSAL_CHARSTRING emb_ustr((const char*)reader.Value());
-            embed_values->get_at(emb_idx)->set_value(&emb_ustr);
+            emb_val->embval_array->get_at(emb_val->embval_index)->set_value(&emb_ustr);
+          }
+          if (last_embval_index == emb_val->embval_index) {
+            ++emb_val->embval_index;
           }
         }
       }
     } // if use-order
 
-    if (embed_values) {
-      // Set the embed_values member to the correct number of strings
-      int num_embedded = 0; // if usenil_attribute
-      if (!usenil_attribute) {
-        num_embedded = field_cnt - first_nonattr + 1;
-        const int num_opt = optional_count();
-        const int * optionals = get_optional_indexes();
-        for (int opt_idx = 0; opt_idx < num_opt; ++opt_idx) {
-          // skip optional attributes
-          if (optionals[opt_idx] < start_at + num_attributes) continue;
-          // reduce for each omitted member
-          if (!get_at(optionals[opt_idx])->is_present()) --num_embedded;
+    if (0 != emb_val) {
+      bool all_unbound = true;
+      static const UNIVERSAL_CHARSTRING emptystring(0, (const char*)NULL);
+      for (int j = 0; j < emb_val->embval_index; ++j) {
+        if (!emb_val->embval_array->get_at(j)->is_bound()) {
+          emb_val->embval_array->get_at(j)->set_value(&emptystring);
+        }else if((static_cast<const UNIVERSAL_CHARSTRING*>(emb_val->embval_array->get_at(j)))->lengthof() !=0) {
+          all_unbound = false;
         }
       }
-      embed_values->set_size(num_embedded);
-      static const UNIVERSAL_CHARSTRING emptystring(0, (const char*)NULL);
-      for (int j = 0; j < num_embedded; ++j) {
-        if (!embed_values->get_at(j)->is_bound()) embed_values->get_at(j)->set_value(&emptystring);
+      if(emb_val_optional && all_unbound){
+        static_cast<OPTIONAL<PreGenRecordOf::PREGEN__RECORD__OF__UNIVERSAL__CHARSTRING>*>(get_at(0))->set_to_omit();
       }
+      delete emb_val;
     } // if embed-values
 
   } // if use-qname
-
+  
+  // Check if every non-optional field has been set
+  for (i = 0; i < field_cnt; ++i) {
+    if (!get_at(i)->is_optional() && !get_at(i)->is_bound()) {
+      TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_INCOMPL_MSG,
+        "No data found for non-optional field '%s'", fld_name(i));
+    }
+  }
+  
   if (own_tag) {
     // We had our start tag. Then our fields did their thing.
     // Now we expect the end tag. And it better be our end tag!
@@ -5363,8 +5708,12 @@ int Record_Type::XER_decode(const XERdescriptor_t& p_td, XmlReaderWrap& reader,
   return 1; // decode successful
 }
 
-int Record_Type::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok) const
+int Record_Type::JSON_encode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer& p_tok) const
 {
+  if (err_descr) {             
+    return JSON_encode_negtest(err_descr, p_td, p_tok);                
+  }
+
   if (!is_bound()) {
     TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
       "Encoding an unbound %s value.", is_set() ? "set" : "record");
@@ -5374,15 +5723,123 @@ int Record_Type::JSON_encode(const TTCN_Typedescriptor_t&, JSON_Tokenizer& p_tok
   int enc_len = p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);
   
   int field_count = get_count();
-  for(int i = 0; i < field_count; ++i) {
+  for (int i = 0; i < field_count; ++i) {
+    boolean metainfo_unbound = NULL != fld_descr(i)->json && fld_descr(i)->json->metainfo_unbound;
     if ((NULL != fld_descr(i)->json && fld_descr(i)->json->omit_as_null) || 
-        !get_at(i)->is_optional() || get_at(i)->is_present()) {
-      if (NULL != fld_descr(i)->json && NULL != fld_descr(i)->json->alias) {
-        enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, fld_descr(i)->json->alias);
+        get_at(i)->is_present() || metainfo_unbound) {
+      const char* field_name = (NULL != fld_descr(i)->json && NULL != fld_descr(i)->json->alias) ?
+        fld_descr(i)->json->alias : fld_name(i);
+      enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, field_name);
+      if (metainfo_unbound && !get_at(i)->is_bound()) {
+        enc_len += p_tok.put_next_token(JSON_TOKEN_LITERAL_NULL);
+        char* metainfo_str = mprintf("metainfo %s", field_name);
+        enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, metainfo_str);
+        Free(metainfo_str);
+        enc_len += p_tok.put_next_token(JSON_TOKEN_STRING, "\"unbound\"");
+      }
+      else {
+        enc_len += get_at(i)->JSON_encode(*fld_descr(i), p_tok);
+      }
+    }
+  }
+  
+  enc_len += p_tok.put_next_token(JSON_TOKEN_OBJECT_END, NULL);
+  return enc_len;
+}
+
+int Record_Type::JSON_encode_negtest(const Erroneous_descriptor_t* p_err_descr,
+                                     const TTCN_Typedescriptor_t& p_td,
+                                     JSON_Tokenizer& p_tok) const 
+{
+  if (!is_bound()) {
+    TTCN_EncDec_ErrorContext::error(TTCN_EncDec::ET_UNBOUND,
+      "Encoding an unbound %s value.", is_set() ? "set" : "record");
+    return -1;
+  }
+  
+  int enc_len = p_tok.put_next_token(JSON_TOKEN_OBJECT_START, NULL);
+  
+  int values_idx = 0;
+  int edescr_idx = 0;
+  
+  int field_count = get_count();
+  for (int i = 0; i < field_count; ++i) {
+    if (-1 != p_err_descr->omit_before && p_err_descr->omit_before > i) {
+      continue;
+    }
+    
+    const Erroneous_values_t* err_vals = p_err_descr->next_field_err_values(i, values_idx);
+    const Erroneous_descriptor_t* emb_descr = p_err_descr->next_field_emb_descr(i, edescr_idx);
+    
+    if (NULL != err_vals && NULL != err_vals->before) {
+      if (NULL == err_vals->before->errval) {
+        TTCN_error("internal error: erroneous before value missing");
+      }
+      if (err_vals->before->raw) {
+        enc_len += err_vals->before->errval->JSON_encode_negtest_raw(p_tok);
+      } else {
+        if (NULL == err_vals->before->type_descr) {
+          TTCN_error("internal error: erroneous before typedescriptor missing");
+        }
+        // it's an extra field, so use the erroneous type's name as the field name
+        enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, err_vals->before->type_descr->name);
+        enc_len += err_vals->before->errval->JSON_encode(*(err_vals->before->type_descr), p_tok);
+      }
+    }
+    
+    const char* field_name = (NULL != fld_descr(i)->json && NULL != fld_descr(i)->json->alias) ?
+      fld_descr(i)->json->alias : fld_name(i);
+    if (NULL != err_vals && NULL != err_vals->value) {
+      if (NULL != err_vals->value->errval) {
+        if (err_vals->value->raw) {
+          enc_len += err_vals->value->errval->JSON_encode_negtest_raw(p_tok);
+        } else {
+          if (NULL == err_vals->value->type_descr) {
+            TTCN_error("internal error: erroneous before typedescriptor missing");
+          }
+          // only replace the field's value, keep the field name
+          enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, field_name);
+          enc_len += err_vals->value->errval->JSON_encode(*(err_vals->value->type_descr), p_tok);
+        }
+      }
+    } else {
+      boolean metainfo_unbound = NULL != fld_descr(i)->json && fld_descr(i)->json->metainfo_unbound;
+      if ((NULL != fld_descr(i)->json && fld_descr(i)->json->omit_as_null) || 
+          get_at(i)->is_present() || metainfo_unbound) {
+        enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, field_name);
+        if (metainfo_unbound && !get_at(i)->is_bound()) {
+          enc_len += p_tok.put_next_token(JSON_TOKEN_LITERAL_NULL);
+          char* metainfo_str = mprintf("metainfo %s", field_name);
+          enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, metainfo_str);
+          Free(metainfo_str);
+          enc_len += p_tok.put_next_token(JSON_TOKEN_STRING, "\"unbound\"");
+        }
+        else if (NULL != emb_descr) {
+          enc_len += get_at(i)->JSON_encode_negtest(emb_descr, *fld_descr(i), p_tok);
+        } else {
+          enc_len += get_at(i)->JSON_encode(*fld_descr(i), p_tok);
+        }
+      }
+    }
+    
+    if (NULL != err_vals && NULL != err_vals->after) {
+      if (NULL == err_vals->after->errval) {
+        TTCN_error("internal error: erroneous after value missing");
+      }
+      if (err_vals->after->raw) {
+        enc_len += err_vals->after->errval->JSON_encode_negtest_raw(p_tok);
       } else {
-        enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, fld_name(i));
+        if (NULL == err_vals->after->type_descr) {
+          TTCN_error("internal error: erroneous before typedescriptor missing");
+        }
+        // it's an extra field, so use the erroneous type's name as the field name
+        enc_len += p_tok.put_next_token(JSON_TOKEN_NAME, err_vals->after->type_descr->name);
+        enc_len += err_vals->after->errval->JSON_encode(*(err_vals->after->type_descr), p_tok);
       }
-      enc_len += get_at(i)->JSON_encode(*fld_descr(i), p_tok);
+    }
+    
+    if (-1 != p_err_descr->omit_after && p_err_descr->omit_after <= i) {
+      break;
     }
   }
   
@@ -5400,11 +5857,19 @@ int Record_Type::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer&
   }
   else if (JSON_TOKEN_OBJECT_START != token) {
     return JSON_ERROR_INVALID_TOKEN;
-  }
-  bound_flag = TRUE;
+  } 
   
   const int field_count = get_count();
   
+  // initialize meta info states
+  int* metainfo = new int[field_count];
+  boolean* field_found = new boolean[field_count];
+  for (int i = 0; i < field_count; ++i) {
+    field_found[i] = FALSE;
+    metainfo[i] = (NULL != fld_descr(i)->json && fld_descr(i)->json->metainfo_unbound) ?
+      JSON_METAINFO_NONE : JSON_METAINFO_NOT_APPLICABLE;
+  }
+  
   while (true) {
     // Read name - value token pairs until we reach some other token
     char* name = 0;
@@ -5421,6 +5886,14 @@ int Record_Type::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer&
       break;
     }
     else {
+      // check for meta info
+      boolean is_metainfo = FALSE;
+      if (name_len > 9 && 0 == strncmp(name, "metainfo ", 9)) {
+        name += 9;
+        name_len -= 9;
+        is_metainfo = TRUE;
+      }
+      
       // check field name
       int field_idx;
       for (field_idx = 0; field_idx < field_count; ++field_idx) {
@@ -5432,13 +5905,15 @@ int Record_Type::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer&
         }
         if (strlen(expected_name) == name_len &&
             0 == strncmp(expected_name, name, name_len)) {
+          field_found[field_idx] = TRUE;
           break;
         }
       }
       if (field_count == field_idx) {
         // invalid field name
         char* name2 = mcopystrn(name, name_len);
-        JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_INVALID_NAME_ERROR, name2);
+        JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, is_metainfo ?
+          JSON_DEC_METAINFO_NAME_ERROR : JSON_DEC_INVALID_NAME_ERROR, name2);
         // if this is set to a warning, skip the value of the field
         dec_len += p_tok.get_next_token(&token, NULL, NULL);
         if (JSON_TOKEN_NUMBER != token && JSON_TOKEN_STRING != token &&
@@ -5452,14 +5927,53 @@ int Record_Type::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer&
         continue;
       }
       
-      int ret_val = get_at(field_idx)->JSON_decode(*fld_descr(field_idx), p_tok, p_silent);
-      if (0 > ret_val) {
-        if (JSON_ERROR_INVALID_TOKEN) {
-          JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FIELD_TOKEN_ERROR, fld_name(field_idx));
+      if (is_metainfo) {
+        if (JSON_METAINFO_NOT_APPLICABLE != metainfo[field_idx]) {
+          // check meta info
+          char* info_value = 0;
+          size_t info_len = 0;
+          dec_len += p_tok.get_next_token(&token, &info_value, &info_len);
+          if (JSON_TOKEN_STRING == token && 9 == info_len &&
+              0 == strncmp(info_value, "\"unbound\"", 9)) {
+            metainfo[field_idx] = JSON_METAINFO_UNBOUND;
+          }
+          else {
+            JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_METAINFO_VALUE_ERROR,
+              fld_name(field_idx));
+            return JSON_ERROR_FATAL;
+          }
         }
-        return JSON_ERROR_FATAL;
+        else {
+          JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_METAINFO_NOT_APPLICABLE,
+            fld_name(field_idx));
+          return JSON_ERROR_FATAL;
+        }
+      }
+      else {
+        buf_pos = p_tok.get_buf_pos();
+        int ret_val = get_at(field_idx)->JSON_decode(*fld_descr(field_idx), p_tok, p_silent);
+        if (0 > ret_val) {
+          if (JSON_ERROR_INVALID_TOKEN == ret_val) {
+            // undo the last action on the buffer, check if the invalid token was a null token 
+            p_tok.set_buf_pos(buf_pos);
+            p_tok.get_next_token(&token, NULL, NULL);
+            if (JSON_TOKEN_LITERAL_NULL == token) {
+              if (JSON_METAINFO_NONE == metainfo[field_idx]) {
+                // delay reporting an error for now, there might be meta info later
+                metainfo[field_idx] = JSON_METAINFO_NEEDED;
+                continue;
+              }
+              else if (JSON_METAINFO_UNBOUND == metainfo[field_idx]) {
+                // meta info already found
+                continue;
+              }
+            }
+            JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FIELD_TOKEN_ERROR, fld_name(field_idx));
+          }
+          return JSON_ERROR_FATAL;
+        }
+        dec_len += ret_val;
       }
-      dec_len += ret_val;
     }
   }
   
@@ -5469,10 +5983,17 @@ int Record_Type::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer&
     return JSON_ERROR_FATAL;
   }
   
-  // Check if every field has been set
+  // Check if every field has been set and handle meta info
   for (int field_idx = 0; field_idx < field_count; ++field_idx) {
     Base_Type* field = get_at(field_idx);
-    if (!field->is_bound()) {
+    if (JSON_METAINFO_UNBOUND == metainfo[field_idx]) {
+      field->clean_up();
+    }
+    else if (JSON_METAINFO_NEEDED == metainfo[field_idx]) {
+      // no meta info was found for this field, report the delayed error
+      JSON_ERROR(TTCN_EncDec::ET_INVAL_MSG, JSON_DEC_FIELD_TOKEN_ERROR, fld_name(field_idx));
+    }
+    else if (!field_found[field_idx]) {
       if (NULL != fld_descr(field_idx)->json && NULL != fld_descr(field_idx)->json->default_value) {
         get_at(field_idx)->JSON_decode(*fld_descr(field_idx), DUMMY_BUFFER, p_silent);
       }
@@ -5485,6 +6006,8 @@ int Record_Type::JSON_decode(const TTCN_Typedescriptor_t& p_td, JSON_Tokenizer&
     }
   }
   
+  delete[] metainfo;
+  
   return dec_len;
 }
 
@@ -5518,12 +6041,24 @@ void Empty_Record_Type::log() const
 
 void Empty_Record_Type::set_param(Module_Param& param) {
   param.basic_check(Module_Param::BC_VALUE, "empty record/set value (i.e. { })");
-  if (param.get_type()!=Module_Param::MP_Value_List || param.get_size()>0) {
+  Module_Param_Ptr mp = &param;
+  if (param.get_type() == Module_Param::MP_Reference) {
+    mp = param.get_referenced_param();
+  }
+  if (mp->get_type()!=Module_Param::MP_Value_List || mp->get_size()>0) {
     param.type_error("empty record/set value (i.e. { })", get_descriptor()->name);
   }
   bound_flag = TRUE;
 }
 
+Module_Param* Empty_Record_Type::get_param(Module_Param_Name& /* param_name */) const
+{
+  if (!is_bound()) {
+    return new Module_Param_Unbound();
+  }
+  return new Module_Param_Value_List();
+}
+
 void Empty_Record_Type::encode_text(Text_Buf& /*text_buf*/) const
 {
   if (!bound_flag)
@@ -5588,7 +6123,7 @@ void Empty_Record_Type::encode(const TTCN_Typedescriptor_t& p_td,
   case TTCN_EncDec::CT_XER: {
     TTCN_EncDec_ErrorContext ec("While XER-encoding type '%s': ", p_td.name);
     unsigned XER_coding=va_arg(pvar, unsigned);
-    XER_encode(*(p_td.xer),p_buf, XER_coding, 0);
+    XER_encode(*(p_td.xer),p_buf, XER_coding, 0, 0);
     p_buf.put_c('\n');
     break;}
   case TTCN_EncDec::CT_JSON: {
@@ -5661,7 +6196,7 @@ void Empty_Record_Type::decode(const TTCN_Typedescriptor_t& p_td,
     for (int success=reader.Read(); success==1; success=reader.Read()) {
       if (reader.NodeType() == XML_READER_TYPE_ELEMENT) break;
     }
-    XER_decode(*(p_td.xer), reader, XER_coding | XER_TOPLEVEL);
+    XER_decode(*(p_td.xer), reader, XER_coding | XER_TOPLEVEL, XER_NONE, 0);
     size_t bytes = reader.ByteConsumed();
     p_buf.set_pos(bytes);
     break;}
@@ -5770,7 +6305,7 @@ int Empty_Record_Type::TEXT_decode(const TTCN_Typedescriptor_t& p_td,
 }
 
 int Empty_Record_Type::XER_encode(const XERdescriptor_t& p_td,
-  TTCN_Buffer& p_buf, unsigned int flavor, int indent) const
+  TTCN_Buffer& p_buf, unsigned int flavor, int indent, embed_values_enc_struct_t*) const
 {
   int encoded_length=(int)p_buf.get_len();
   int indenting = !is_canonical(flavor);
@@ -5784,7 +6319,7 @@ int Empty_Record_Type::XER_encode(const XERdescriptor_t& p_td,
 }
 
 int Empty_Record_Type::XER_decode(const XERdescriptor_t& p_td,
-  XmlReaderWrap& reader, unsigned int flavor)
+  XmlReaderWrap& reader, unsigned int flavor, unsigned int /*flavor2*/, embed_values_dec_struct_t*)
 {
   int exer = is_exer(flavor);
   bound_flag = true;
This page took 0.055972 seconds and 5 git commands to generate.