Skip to content
Snippets Groups Projects
Value.cc 616 KiB
Newer Older
Elemer Lelik's avatar
Elemer Lelik committed
/******************************************************************************
 * Copyright (c) 2000-2021 Ericsson Telecom AB
Elemer Lelik's avatar
Elemer Lelik committed
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v2.0
Elemer Lelik's avatar
Elemer Lelik committed
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
Elemer Lelik's avatar
Elemer Lelik committed
 *
 * Contributors:
 *   Baji, Laszlo
 *   Balasko, Jeno
 *   Baranyi, Botond
 *   Beres, Szabolcs
 *   Bibo, Zoltan
 *   Cserveni, Akos
 *   Delic, Adam
 *   Dimitrov, Peter
 *   Feher, Csaba
 *   Forstner, Matyas
 *   Gecse, Roland
 *   Kovacs, Ferenc
 *   Ormandi, Matyas
 *   Raduly, Csaba
 *   Szabados, Kristof
Elemer Lelik's avatar
Elemer Lelik committed
 *   Szabo, Janos Zoltan – initial implementation
 *   Szalai, Gabor
 *   Tatarka, Gabor
 *   Zalanyi, Balazs Andor
 *
 ******************************************************************************/
#include "../common/dbgnew.hh"
#include "Value.hh"
#include "Identifier.hh"
#include "Valuestuff.hh"
#include "PredefFunc.hh"
#include "CompField.hh"
#include "CompType.hh"
#include "EnumItem.hh"
#include "TypeCompat.hh"
#include "asn1/Block.hh"
#include "asn1/TokenBuf.hh"
#include "Real.hh"
#include "Int.hh"
#include "main.hh"
#include "Setting.hh"
#include "Type.hh"
#include "ttcn3/TtcnTemplate.hh"
#include "ttcn3/ArrayDimensions.hh"
#include "ustring.hh"
#include "../common/pattern.hh"

#include "ttcn3/PatternString.hh"
#include "ttcn3/Statement.hh"

#include "ttcn3/Attributes.hh"
#include "ttcn3/JsonAST.hh"
Elemer Lelik's avatar
Elemer Lelik committed
#include "../common/JSON_Tokenizer.hh"
Elemer Lelik's avatar
Elemer Lelik committed
#include "ttcn3/Ttcn2Json.hh"
#include "ttcn3/Ttcnstuff.hh"

#include <regex.h>
#include <limits.h>

namespace Common {

  static void clean_up_string_elements(map<size_t, Value>*& string_elements)
  {
    if (string_elements) {
      for (size_t i = 0; i < string_elements->size(); i++)
	delete string_elements->get_nth_elem(i);
      string_elements->clear();
      delete string_elements;
      string_elements = 0;
    }
  }

  // =================================
  // ===== Value
  // =================================

  Value::Value(const Value& p)
    : GovernedSimple(p), valuetype(p.valuetype), my_governor(p.my_governor)
  {
    switch(valuetype) {
    case V_ERROR:
    case V_NULL:
    case V_OMIT:
    case V_TTCN3_NULL:
    case V_DEFAULT_NULL:
    case V_FAT_NULL:
    case V_NOTUSED:
      break;
    case V_BOOL:
      u.val_bool=p.u.val_bool;
      break;
    case V_INT:
      u.val_Int=new int_val_t(*(p.u.val_Int));
      break;
    case V_NAMEDINT:
    case V_ENUM:
    case V_UNDEF_LOWERID:
      u.val_id=p.u.val_id->clone();
      break;
    case V_REAL:
      u.val_Real=p.u.val_Real;
      break;
    case V_BSTR:
    case V_HSTR:
    case V_OSTR:
    case V_CSTR:
    case V_ISO2022STR:
      set_val_str(new string(*p.u.str.val_str));
      break;
    case V_USTR:
      set_val_ustr(new ustring(*p.u.ustr.val_ustr));
      u.ustr.convert_str = p.u.ustr.convert_str;
      break;
    case V_CHARSYMS:
      u.char_syms = p.u.char_syms->clone();
      break;
    case V_OID:
    case V_ROID:
      u.oid_comps=new vector<OID_comp>;
      for(size_t i=0; i<p.u.oid_comps->size(); i++)
        add_oid_comp((*p.u.oid_comps)[i]->clone());
      break;
    case V_CHOICE:
      u.choice.alt_name=p.u.choice.alt_name->clone();
      u.choice.alt_value=p.u.choice.alt_value->clone();
      break;
    case V_SEQOF:
    case V_SETOF:
    case V_ARRAY:
      u.val_vs=p.u.val_vs->clone();
      break;
    case V_SEQ:
    case V_SET:
      u.val_nvs=p.u.val_nvs->clone();
      break;
    case V_REFD:
      u.ref.ref=p.u.ref.ref->clone();
      u.ref.refd_last=0;
      break;
    case V_NAMEDBITS:
      for(size_t i=0; i<p.u.ids->size(); i++) {
        Identifier *id = p.u.ids->get_nth_elem(i);
        u.ids->add(id->get_name(), id->clone());
      }
      break;
    case V_UNDEF_BLOCK:
      u.block=p.u.block->clone();
      break;
    case V_VERDICT:
      u.verdict=p.u.verdict;
      break;
    case V_EXPR:
      u.expr.v_optype = p.u.expr.v_optype;
      u.expr.state = EXPR_NOT_CHECKED;
      switch(u.expr.v_optype) {
      case OPTYPE_RND: // -
      case OPTYPE_COMP_NULL:
      case OPTYPE_COMP_MTC:
      case OPTYPE_COMP_SYSTEM:
      case OPTYPE_COMP_SELF:
      case OPTYPE_COMP_RUNNING_ANY:
      case OPTYPE_COMP_RUNNING_ALL:
      case OPTYPE_COMP_ALIVE_ANY:
      case OPTYPE_COMP_ALIVE_ALL:
      case OPTYPE_TMR_RUNNING_ANY:
      case OPTYPE_GETVERDICT:
      case OPTYPE_TESTCASENAME:
Elemer Lelik's avatar
Elemer Lelik committed
      case OPTYPE_PROF_RUNNING:
        break;
      case OPTYPE_GET_PORT_REF:
        u.expr.type = p.u.expr.type; // the type is not owned, don't copy it
        break;
      case OPTYPE_COMP_RUNNING: // v1 [r2] b4
      case OPTYPE_COMP_ALIVE:
        u.expr.r2 = p.u.expr.r2 != NULL ? p.u.expr.r2->clone() : NULL;
        u.expr.b4 = p.u.expr.b4;
        // no break
      case OPTYPE_UNARYPLUS: // v1
      case OPTYPE_UNARYMINUS:
      case OPTYPE_NOT:
      case OPTYPE_NOT4B:
      case OPTYPE_BIT2HEX:
      case OPTYPE_BIT2INT:
      case OPTYPE_BIT2OCT:
      case OPTYPE_BIT2STR:
      case OPTYPE_BSON2JSON:
      case OPTYPE_CBOR2JSON:
      case OPTYPE_CHAR2INT:
      case OPTYPE_CHAR2OCT:
      case OPTYPE_FLOAT2INT:
      case OPTYPE_FLOAT2STR:
      case OPTYPE_HEX2BIT:
      case OPTYPE_HEX2INT:
      case OPTYPE_HEX2OCT:
      case OPTYPE_HEX2STR:
      case OPTYPE_INT2CHAR:
      case OPTYPE_INT2FLOAT:
      case OPTYPE_INT2STR:
      case OPTYPE_INT2UNICHAR:
      case OPTYPE_JSON2BSON:
      case OPTYPE_JSON2CBOR:
      case OPTYPE_OCT2BIT:
      case OPTYPE_OCT2CHAR:
      case OPTYPE_OCT2HEX:
      case OPTYPE_OCT2INT:
      case OPTYPE_OCT2STR:
      case OPTYPE_STR2BIT:
      case OPTYPE_STR2FLOAT:
      case OPTYPE_STR2HEX:
      case OPTYPE_STR2INT:
      case OPTYPE_STR2OCT:
      case OPTYPE_UNICHAR2INT:
      case OPTYPE_UNICHAR2CHAR:
      case OPTYPE_ENUM2INT:
      case OPTYPE_RNDWITHVAL:
      case OPTYPE_GET_STRINGENCODING:
      case OPTYPE_DECODE_BASE64:
      case OPTYPE_REMOVE_BOM:
        u.expr.v1=p.u.expr.v1->clone();
        break;
      case OPTYPE_HOSTID: // [v1]
        u.expr.v1=p.u.expr.v1?p.u.expr.v1->clone():0;
        break;
      case OPTYPE_ADD: // v1 v2
      case OPTYPE_SUBTRACT:
      case OPTYPE_MULTIPLY:
      case OPTYPE_DIVIDE:
      case OPTYPE_MOD:
      case OPTYPE_REM:
      case OPTYPE_CONCAT:
      case OPTYPE_EQ:
      case OPTYPE_LT:
      case OPTYPE_GT:
      case OPTYPE_NE:
      case OPTYPE_GE:
      case OPTYPE_LE:
      case OPTYPE_AND:
      case OPTYPE_OR:
      case OPTYPE_XOR:
      case OPTYPE_AND4B:
      case OPTYPE_OR4B:
      case OPTYPE_XOR4B:
      case OPTYPE_SHL:
      case OPTYPE_SHR:
      case OPTYPE_ROTL:
      case OPTYPE_ROTR:
      case OPTYPE_INT2BIT:
      case OPTYPE_INT2HEX:
      case OPTYPE_INT2OCT:
        u.expr.v1=p.u.expr.v1->clone();
        u.expr.v2=p.u.expr.v2->clone();
        break;
      case OPTYPE_UNICHAR2OCT: // v1 [v2]
      case OPTYPE_OCT2UNICHAR:
      case OPTYPE_ENCODE_BASE64:
        u.expr.v1=p.u.expr.v1->clone();
        u.expr.v2=p.u.expr.v2?p.u.expr.v2->clone():0;
        break;
      case OPTYPE_UNDEF_RUNNING: // r1 [r2] b4
      case OPTYPE_TMR_RUNNING: // r1 [r2] b4
        u.expr.r1=p.u.expr.r1->clone();
        u.expr.r2 = p.u.expr.r2 != NULL ? p.u.expr.r2->clone() : NULL;
        u.expr.b4 = p.u.expr.b4;
        break;
      case OPTYPE_DECODE: // r1 r2 [v3] [v4]
        u.expr.r1 = p.u.expr.r1->clone();
        u.expr.r2 = p.u.expr.r2->clone();
        u.expr.v2 = p.u.expr.v3 != NULL ? p.u.expr.v3->clone() : NULL;
        u.expr.v3 = p.u.expr.v4 != NULL ? p.u.expr.v4->clone() : NULL;
        break;
      case OPTYPE_SUBSTR:
        u.expr.ti1=p.u.expr.ti1->clone();
        u.expr.v2 = p.u.expr.v2 != NULL ? p.u.expr.v2->clone() : NULL;
        u.expr.v3 = p.u.expr.v3 != NULL ? p.u.expr.v3->clone() : NULL;
        break;
      case OPTYPE_REGEXP:
        u.expr.ti1=p.u.expr.ti1->clone();
        u.expr.t2=p.u.expr.t2->clone();
        u.expr.v3=p.u.expr.v3->clone();
        break;
      case OPTYPE_DECOMP: // v1 v2 v3
        u.expr.v1=p.u.expr.v1->clone();
        u.expr.v2=p.u.expr.v2->clone();
        u.expr.v3=p.u.expr.v3->clone();
        break;
      case OPTYPE_REPLACE:
        u.expr.ti1 = p.u.expr.ti1->clone();
        u.expr.v2 = p.u.expr.v2->clone();
        u.expr.v3 = p.u.expr.v3->clone();
        u.expr.ti4 = p.u.expr.ti4->clone();
        break;
      case OPTYPE_VALUEOF: // ti1 [subrefs2]
        u.expr.subrefs2 = p.u.expr.subrefs2 != NULL ? u.expr.subrefs2->clone() : NULL;
        // fall through
      case OPTYPE_LENGTHOF: // ti1
      case OPTYPE_SIZEOF:  // ti1
      case OPTYPE_ISPRESENT:
      case OPTYPE_TTCN2STRING:
      case OPTYPE_ISVALUE:
      case OPTYPE_ISBOUND:
        u.expr.ti1=p.u.expr.ti1->clone();
        break;
      case OPTYPE_ENCVALUE_UNICHAR: // ti1 [v2] [v3] [v4]
        u.expr.ti1=p.u.expr.ti1->clone();
        u.expr.v2=p.u.expr.v2?p.u.expr.v2->clone():0;
        u.expr.v3 = p.u.expr.v3 != NULL ? p.u.expr.v3->clone() : NULL;
        u.expr.v4 = p.u.expr.v4 != NULL ? p.u.expr.v4->clone() : NULL;
      case OPTYPE_DECVALUE_UNICHAR: // r1 r2 [v3] [v4] [v5]
        u.expr.r1 = p.u.expr.r1->clone();
        u.expr.r2 = p.u.expr.r2->clone();
        u.expr.v3 = p.u.expr.v3 != NULL ? p.u.expr.v3->clone() : NULL;
        u.expr.v4 = p.u.expr.v4 != NULL ? p.u.expr.v4->clone() : NULL;
        u.expr.v5 = p.u.expr.v5 != NULL ? p.u.expr.v5->clone() : NULL;
      case OPTYPE_TMR_READ:
      case OPTYPE_ACTIVATE:
        u.expr.r1=p.u.expr.r1->clone();
        break;
      case OPTYPE_EXECUTE: // r1 [v2]
        u.expr.r1=p.u.expr.r1->clone();
        u.expr.v2=p.u.expr.v2?p.u.expr.v2->clone():0;
        break;
      case OPTYPE_CHECKSTATE_ANY: // [r1] v2
      case OPTYPE_CHECKSTATE_ALL:
        u.expr.r1=p.u.expr.r1?p.u.expr.r1->clone():0;
        u.expr.v2=p.u.expr.v2->clone();
        break;
      case OPTYPE_UNDEF_CREATE:
      case OPTYPE_CLASS_CREATE:
        u.expr.r1 = p.u.expr.r1->clone();
        if (p.u.expr.state != EXPR_CHECKED) {
          u.expr.t_list2 = p.u.expr.t_list2->clone();
        }
        else {
          u.expr.ap_list2 = p.u.expr.ap_list2->clone();
          u.expr.state = EXPR_CHECKED;
        }
        if (u.expr.v_optype == OPTYPE_UNDEF_CREATE) {
          u.expr.b4 = p.u.expr.b4;
        }
        break;
      case OPTYPE_COMP_CREATE: // r1 [v2] [v3]
        u.expr.r1=p.u.expr.r1->clone();
        u.expr.v2=p.u.expr.v2?p.u.expr.v2->clone():0;
        u.expr.v3=p.u.expr.v3?p.u.expr.v3->clone():0;
        u.expr.b4 = p.u.expr.b4;
        break;
      case OPTYPE_MATCH: // v1 t2
        u.expr.v1=p.u.expr.v1->clone();
        u.expr.t2=p.u.expr.t2->clone();
        break;
      case OPTYPE_ISCHOSEN: // r1 i2
        u.expr.r1=p.u.expr.r1->clone();
        u.expr.i2=p.u.expr.i2->clone();
        break;
      case OPTYPE_ISCHOSEN_V: // v1 i2
        u.expr.v1=p.u.expr.v1->clone();
        u.expr.i2=p.u.expr.i2->clone();
        break;
      case OPTYPE_ISCHOSEN_T: // t1 i2
        u.expr.t1=p.u.expr.t1->clone();
        u.expr.i2=p.u.expr.i2->clone();
        break;
      case OPTYPE_ACTIVATE_REFD:
        u.expr.v1 = p.u.expr.v1->clone();
        if(p.u.expr.state!=EXPR_CHECKED)
          u.expr.t_list2 = p.u.expr.t_list2->clone();
        else {
          u.expr.ap_list2 = p.u.expr.ap_list2->clone();
          u.expr.state = EXPR_CHECKED;
          }
        break;
      case OPTYPE_EXECUTE_REFD:
        u.expr.v1 = p.u.expr.v1->clone();
        if(p.u.expr.state!=EXPR_CHECKED)
          u.expr.t_list2 = p.u.expr.t_list2->clone();
        else {
          u.expr.ap_list2 = p.u.expr.ap_list2->clone();
          u.expr.state = EXPR_CHECKED;
          }
        u.expr.v3 = p.u.expr.v3 ? p.u.expr.v3->clone() : 0;
        break;
      case OPTYPE_LOG2STR:
      case OPTYPE_ANY2UNISTR:
        u.expr.logargs = p.u.expr.logargs->clone();
        break;
      case OPTYPE_ISTEMPLATEKIND:
        u.expr.ti1 = p.u.expr.ti1->clone();
        u.expr.v2 = p.u.expr.v2->clone();
        break;
      case OPTYPE_OF_CLASS:
      case OPTYPE_CLASS_CASTING:
        u.expr.type = p.u.expr.type->clone();
        u.expr.r2 = p.u.expr.r2->clone();
        break;
      case OPTYPE_CLASS_CASTING_REF:
        u.expr.r1 = p.u.expr.r1->clone();
        u.expr.r2 = p.u.expr.r2->clone();
        break;
      default:
        FATAL_ERROR("Value::Value()");
      } // switch
      break;
    case V_MACRO:
      u.macro = p.u.macro;
      break;
    case V_FUNCTION:
    case V_ALTSTEP:
    case V_TESTCASE:
      u.refd_fat = p.u.refd_fat;
      break;
    case V_INVOKE:
      u.invoke.v = p.u.invoke.v->clone();
      u.invoke.t_list = p.u.invoke.t_list?p.u.invoke.t_list->clone():0;
      u.invoke.ap_list = p.u.invoke.ap_list?p.u.invoke.ap_list->clone():0;
      break;
    case V_REFER:
      u.refered = p.u.refered->clone();
      break;
    case V_ANY_VALUE:
    case V_ANY_OR_OMIT:
      u.len_res = p.u.len_res != NULL ? p.u.len_res->clone() : NULL;
      break;
    default:
      FATAL_ERROR("Value::Value()");
    } // switch
  }

  void Value::chk_expr_immutability() {
    switch (valuetype) {
      case V_REFD: {/**< referenced */
        Ttcn::Reference* ttcn_ref = dynamic_cast<Ttcn::Reference*>(u.ref.ref);
        if (ttcn_ref != NULL) {
          ttcn_ref->chk_immutability();
        }
        break;}
      case V_EXPR: /**< expressions */
        switch (u.expr.v_optype) {
          case OPTYPE_TESTCASENAME: // -
            break;
          case OPTYPE_NOW: // -
            error("Operation 'now' cannot be used in alt guards.");
            break;
          case OPTYPE_RND: // -
          case OPTYPE_RNDWITHVAL: /** \todo -> SEED */ // v1
            warning("Random number generation 'rnd()' change the actual snapshot.");
            break;
          case OPTYPE_UNARYPLUS: // v1
          case OPTYPE_UNARYMINUS: // v1
          case OPTYPE_NOT: // v1
          case OPTYPE_NOT4B: // v1
          case OPTYPE_BIT2HEX: // v1  6
          case OPTYPE_BIT2INT: // v1
          case OPTYPE_BIT2OCT: // v1
          case OPTYPE_BIT2STR: // v1
          case OPTYPE_CHAR2INT: // v1  10
          case OPTYPE_CHAR2OCT: // v1
          case OPTYPE_FLOAT2INT: // v1
          case OPTYPE_FLOAT2STR: // v1
          case OPTYPE_HEX2BIT: // v1
          case OPTYPE_HEX2INT: // v1
          case OPTYPE_HEX2OCT: // v1
          case OPTYPE_HEX2STR: // v1
          case OPTYPE_INT2CHAR: // v1
          case OPTYPE_INT2FLOAT: // v1
          case OPTYPE_INT2STR: // v1   20
          case OPTYPE_INT2UNICHAR: // v1
          case OPTYPE_OCT2BIT: // v1
          case OPTYPE_OCT2CHAR: // v1
          case OPTYPE_OCT2HEX: // v1
          case OPTYPE_OCT2INT: // v1
          case OPTYPE_OCT2STR: // v1
          case OPTYPE_STR2BIT: // v1
          case OPTYPE_STR2FLOAT: // v1
          case OPTYPE_STR2HEX: // v1
          case OPTYPE_STR2INT: // v1    30
          case OPTYPE_STR2OCT: // v1
          case OPTYPE_UNICHAR2INT: // v1
          case OPTYPE_UNICHAR2CHAR: // v1
          case OPTYPE_ENUM2INT: // v1
          case OPTYPE_REMOVE_BOM: //v1
          case OPTYPE_GET_STRINGENCODING: //v1
          case OPTYPE_DECODE_BASE64: //v1
          case OPTYPE_CBOR2JSON: // v1
          case OPTYPE_JSON2CBOR: // v1
          case OPTYPE_BSON2JSON: // v1
          case OPTYPE_JSON2BSON: // v1
            u.expr.v1->chk_expr_immutability();
            break;
          case OPTYPE_UNICHAR2OCT: // v1 [v2]
          case OPTYPE_OCT2UNICHAR: // v1 [v2]
          case OPTYPE_ENCODE_BASE64: //v1 [v2]
            u.expr.v1->chk_expr_immutability();
            if (u.expr.v2) u.expr.v2->chk_expr_immutability();
            break;
          case OPTYPE_ADD: // v1 v2
          case OPTYPE_SUBTRACT: // v1 v2
          case OPTYPE_MULTIPLY: // v1 v2
          case OPTYPE_DIVIDE: // v1 v2      40
          case OPTYPE_MOD: // v1 v2
          case OPTYPE_REM: // v1 v2
          case OPTYPE_CONCAT: // v1 v2
          case OPTYPE_EQ: // v1 v2 ==
          case OPTYPE_LT: // v1 v2 <
          case OPTYPE_GT: // v1 v2 >
          case OPTYPE_NE: // v1 v2 !=
          case OPTYPE_GE: // v1 v2 >=
          case OPTYPE_LE: // v1 v2 <=
          case OPTYPE_AND: // v1 v2    50
          case OPTYPE_OR: // v1 v2
          case OPTYPE_XOR: // v1 v2
          case OPTYPE_AND4B: // v1 v2
          case OPTYPE_OR4B: // v1 v2
          case OPTYPE_XOR4B: // v1 v2
          case OPTYPE_SHL: // v1 v2
          case OPTYPE_SHR: // v1 v2
          case OPTYPE_ROTL: // v1 v2
          case OPTYPE_ROTR: // v1 v2
          case OPTYPE_INT2BIT: // v1 v2    60
          case OPTYPE_INT2HEX: // v1 v2
          case OPTYPE_INT2OCT: // v1 v2
            u.expr.v1->chk_expr_immutability();
            u.expr.v2->chk_expr_immutability();
            break;
          case OPTYPE_ENCODE: // ti1 [v2] [v3] 35
          case OPTYPE_DECODE: // r1 r2 [v3] [v4]
            // not yet done.
            break;
          case OPTYPE_SUBSTR:
            u.expr.ti1->chk_immutability();
            u.expr.v2->chk_expr_immutability();
            u.expr.v3->chk_expr_immutability();
            break;
          case OPTYPE_REGEXP: 
            u.expr.ti1->chk_immutability();
            u.expr.t2->chk_immutability();
            u.expr.v3->chk_expr_immutability();
            break;
          case OPTYPE_DECOMP: // not implemented (reference guide)
            u.expr.v1->chk_expr_immutability();
            u.expr.v2->chk_expr_immutability();
            u.expr.v3->chk_expr_immutability();
            break;
          case OPTYPE_REPLACE: // ti1 v2 v3 ti4
            u.expr.ti1->chk_immutability();
            u.expr.v2->chk_expr_immutability();
            u.expr.v3->chk_expr_immutability();
            u.expr.ti4->chk_immutability();
            break;
          case OPTYPE_ISVALUE: // ti1   68
          case OPTYPE_ISBOUND: // ti1
          case OPTYPE_ISPRESENT: // ti1
          case OPTYPE_LENGTHOF: // ti1
          case OPTYPE_SIZEOF: // ti1 
          case OPTYPE_VALUEOF: // ti1
          case OPTYPE_TTCN2STRING: // ti1
            u.expr.ti1->chk_immutability();
            break;
          case OPTYPE_ISCHOSEN: // r1 i2
            break;
          case OPTYPE_ISCHOSEN_V: // v1 i2
            u.expr.v1->chk_expr_immutability();
            break;
          case OPTYPE_ISCHOSEN_T: // t1 i2
            u.expr.t1->chk_immutability();
            break;
          case OPTYPE_MATCH: // v1 t2
            u.expr.v1->chk_expr_immutability();
            u.expr.t2->chk_immutability();
            break;
          case OPTYPE_UNDEF_RUNNING:
          case OPTYPE_COMP_NULL:
          case OPTYPE_COMP_MTC:
          case OPTYPE_COMP_SYSTEM:
          case OPTYPE_COMP_SELF:
          case OPTYPE_UNDEF_CREATE:
          case OPTYPE_CLASS_CREATE: // todo
          case OPTYPE_COMP_CREATE: // r1 [v2] [v3] b4
            break;
          case OPTYPE_COMP_RUNNING: // v1 [r2] b4
          case OPTYPE_COMP_RUNNING_ANY: // -
          case OPTYPE_COMP_RUNNING_ALL: // -
          case OPTYPE_COMP_ALIVE: // v1
          case OPTYPE_COMP_ALIVE_ANY: // -
          case OPTYPE_COMP_ALIVE_ALL: // -
            warning("State of component(s) may change during the actual snapshot.");
            break;
          case OPTYPE_TMR_READ: // r1     90
          case OPTYPE_TMR_RUNNING: // r1 [r2] b4
          case OPTYPE_TMR_RUNNING_ANY: // -
            warning("State of timer(s) may change during the actual snapshot.");
            break;
          case OPTYPE_GETVERDICT: // -
          case OPTYPE_ACTIVATE: // r1
          case OPTYPE_ACTIVATE_REFD: //v1 t_list2
          case OPTYPE_EXECUTE: // r1 [v2]
          case OPTYPE_EXECUTE_REFD: // v1 t_list2 [v3]
          case OPTYPE_LOG2STR: // logargs
          case OPTYPE_PROF_RUNNING: // -     99
          case OPTYPE_ENCVALUE_UNICHAR: // ti1 [v2] [v3] [v4]
          case OPTYPE_DECVALUE_UNICHAR: // r1 r2 [v3] [v4] [v5]
          case OPTYPE_GET_PORT_REF: // -optypes
          case OPTYPE_ANY2UNISTR: // logarg: length = 1
            break;
          case OPTYPE_CHECKSTATE_ANY: // [r1] v2: port or any
          case OPTYPE_CHECKSTATE_ALL: // [r1] v2: port or all
            warning("State of port(s) may change during the actual snapshot.");
            break;
          case OPTYPE_HOSTID: // [v1]
            if (u.expr.v1) u.expr.v1->chk_expr_immutability();
            break;
          case OPTYPE_ISTEMPLATEKIND: // ti1 v2
            u.expr.v2->chk_expr_immutability();
            u.expr.ti1->chk_immutability();
            break;
          case OPTYPE_OF_CLASS:
          case OPTYPE_CLASS_CASTING:
            u.expr.r2->chk_immutability();
            break;
          case OPTYPE_CLASS_CASTING_REF:
            u.expr.r1->chk_immutability();
            u.expr.r2->chk_immutability();
            break;
          default:
            FATAL_ERROR("Value::chk_expr_immutability()");
        }
        break;
      case V_ERROR: /**< erroneous */
      case V_UNDEF_LOWERID: /**< undefined loweridentifier */
      case V_NULL: /**< NULL (for ASN.1 NULL type: also in TTCN-3) */
      case V_BOOL: /**< boolean */
      case V_NAMEDINT: /**< integer / named number */
      case V_NAMEDBITS: /**< named bits (identifiers) */
      case V_INT: /**< integer */
      case V_REAL: /**< real/float */
      case V_ENUM: /**< enumerated */
      case V_BSTR: /**< bitstring */
      case V_HSTR: /**< hexstring */
      case V_OSTR: /**< octetstring */
      case V_CSTR: /**< charstring */
      case V_USTR: /**< universal charstring */
      case V_ISO2022STR: /**< ISO-2022 string (treat as octetstring) */
      case V_CHARSYMS: /**< parsed ASN.1 universal string notation */
      case V_OID: /**< object identifier */
      case V_ROID: /**< relative object identifier */
      case V_CHOICE: /**< choice; set directly by the ASN.1 parser */
      case V_SEQOF: /**< sequence (record) of */
      case V_SETOF: /**< set of */
      case V_ARRAY: /**< array */
      case V_SEQ: /**< sequence (record) */
        // TODO test?
      case V_SET: /**< set */
      case V_OPENTYPE: /**< open type */
      case V_UNDEF_BLOCK: /**< undefined {block} */
      case V_OMIT: /**< special value for optional values */
      case V_VERDICT: /**< verdict */
      case V_TTCN3_NULL: /**< TTCN-3 null (for component or default references) */
      case V_DEFAULT_NULL: /**< null default reference */
      case V_FAT_NULL: /**< null for function: altstep and testcase */
      case V_MACRO: /**< macros (%%something) */
      case V_NOTUSED: /**< not used symbol ('-') */
      case V_FUNCTION: /**< function */
      case V_ALTSTEP: /**< altstep */
      case V_TESTCASE: /**< testcase */
      case V_INVOKE: /**< invoke operation */
      case V_REFER: /**< refer(function) */
      case V_ANY_VALUE: /**< any value (?) - used by template concatenation */
      case V_ANY_OR_OMIT: /**< any or omit (*) - used by template concatenation */
        break;
      default:
        FATAL_ERROR("Value::chk_expr_immutability()");
    } // switch
  }

  void Value::clean_up()
  {
    switch (valuetype) {
    case V_ERROR:
    case V_NULL:
    case V_BOOL:
    case V_REAL:
    case V_OMIT:
    case V_VERDICT:
    case V_TTCN3_NULL:
    case V_DEFAULT_NULL:
    case V_FAT_NULL:
    case V_MACRO:
    case V_NOTUSED:
    case V_FUNCTION:
    case V_ALTSTEP:
    case V_TESTCASE:
      break;
    case V_INT:
      delete u.val_Int;
      break;
    case V_NAMEDINT:
    case V_ENUM:
    case V_UNDEF_LOWERID:
      delete u.val_id;
      break;
    case V_BSTR:
    case V_HSTR:
    case V_OSTR:
    case V_CSTR:
    case V_ISO2022STR:
      delete u.str.val_str;
      clean_up_string_elements(u.str.str_elements);
      break;
    case V_USTR:
      delete u.ustr.val_ustr;
      clean_up_string_elements(u.ustr.ustr_elements);
      break;
    case V_CHARSYMS:
      delete u.char_syms;
      break;
    case V_OID:
    case V_ROID:
      if (u.oid_comps) {
	for(size_t i=0; i<u.oid_comps->size(); i++)
          delete (*u.oid_comps)[i];
	u.oid_comps->clear();
	delete u.oid_comps;
      }
      break;
    case V_EXPR:
      clean_up_expr();
      break;
    case V_CHOICE:
      delete u.choice.alt_name;
      delete u.choice.alt_value;
      break;
    case V_SEQOF:
    case V_SETOF:
    case V_ARRAY:
      delete u.val_vs;
      break;
    case V_SEQ:
    case V_SET:
      delete u.val_nvs;
      break;
    case V_REFD:
      delete u.ref.ref;
      break;
    case V_REFER:
      delete u.refered;
      break;
    case V_INVOKE:
      delete u.invoke.v;
      delete u.invoke.t_list;
      delete u.invoke.ap_list;
      break;
    case V_NAMEDBITS:
      if(u.ids) {
        for(size_t i=0; i<u.ids->size(); i++) delete u.ids->get_nth_elem(i);
        u.ids->clear();
        delete u.ids;
      }
      break;
    case V_UNDEF_BLOCK:
      delete u.block;
      break;
    case V_ANY_VALUE:
    case V_ANY_OR_OMIT:
      delete u.len_res;
      break;
    default:
      FATAL_ERROR("Value::clean_up()");
    } // switch
  }

  void Value::clean_up_expr()
  {
    switch (u.expr.state) {
    case EXPR_CHECKING:
    case EXPR_CHECKING_ERR:
      FATAL_ERROR("Value::clean_up_expr()");
    default:
      break;
    }
    switch (u.expr.v_optype) {
    case OPTYPE_RND: // -
    case OPTYPE_COMP_NULL:
    case OPTYPE_COMP_MTC:
    case OPTYPE_COMP_SYSTEM:
    case OPTYPE_COMP_SELF:
    case OPTYPE_COMP_RUNNING_ANY:
    case OPTYPE_COMP_RUNNING_ALL:
    case OPTYPE_COMP_ALIVE_ANY:
    case OPTYPE_COMP_ALIVE_ALL:
    case OPTYPE_TMR_RUNNING_ANY:
    case OPTYPE_GETVERDICT:
    case OPTYPE_TESTCASENAME:
Elemer Lelik's avatar
Elemer Lelik committed
    case OPTYPE_PROF_RUNNING:
    case OPTYPE_GET_PORT_REF: // type (not owned)
      break;
    case OPTYPE_COMP_RUNNING: // v1 [r2] b4
    case OPTYPE_COMP_ALIVE:
      delete u.expr.r2;
      // no break
    case OPTYPE_UNARYPLUS: // v1
    case OPTYPE_UNARYMINUS:
    case OPTYPE_NOT:
    case OPTYPE_NOT4B:
    case OPTYPE_BIT2HEX:
    case OPTYPE_BIT2INT:
    case OPTYPE_BIT2OCT:
    case OPTYPE_BIT2STR:
    case OPTYPE_BSON2JSON:
    case OPTYPE_CBOR2JSON:
    case OPTYPE_CHAR2INT:
    case OPTYPE_CHAR2OCT:
    case OPTYPE_FLOAT2INT:
    case OPTYPE_FLOAT2STR:
    case OPTYPE_HEX2BIT:
    case OPTYPE_HEX2INT:
    case OPTYPE_HEX2OCT:
    case OPTYPE_HEX2STR:
    case OPTYPE_INT2CHAR:
    case OPTYPE_INT2FLOAT:
    case OPTYPE_INT2STR:
    case OPTYPE_INT2UNICHAR:
    case OPTYPE_JSON2BSON:
    case OPTYPE_JSON2CBOR:
    case OPTYPE_OCT2BIT:
    case OPTYPE_OCT2CHAR:
    case OPTYPE_OCT2HEX:
    case OPTYPE_OCT2INT:
    case OPTYPE_OCT2STR:
    case OPTYPE_STR2BIT:
    case OPTYPE_STR2FLOAT:
    case OPTYPE_STR2HEX:
    case OPTYPE_STR2INT:
    case OPTYPE_STR2OCT:
    case OPTYPE_UNICHAR2INT:
    case OPTYPE_UNICHAR2CHAR:
    case OPTYPE_ENUM2INT:
    case OPTYPE_RNDWITHVAL:
    case OPTYPE_REMOVE_BOM:
    case OPTYPE_GET_STRINGENCODING:
    case OPTYPE_DECODE_BASE64:
    case OPTYPE_HOSTID:
      delete u.expr.v1;
      break;
    case OPTYPE_ADD: // v1 v2
    case OPTYPE_SUBTRACT:
    case OPTYPE_MULTIPLY:
    case OPTYPE_DIVIDE:
    case OPTYPE_MOD:
    case OPTYPE_REM:
    case OPTYPE_CONCAT:
    case OPTYPE_EQ:
    case OPTYPE_LT:
    case OPTYPE_GT:
    case OPTYPE_NE:
    case OPTYPE_GE:
    case OPTYPE_LE:
    case OPTYPE_AND:
    case OPTYPE_OR:
    case OPTYPE_XOR:
    case OPTYPE_AND4B:
    case OPTYPE_OR4B:
    case OPTYPE_XOR4B:
    case OPTYPE_SHL:
    case OPTYPE_SHR:
    case OPTYPE_ROTL:
    case OPTYPE_ROTR:
    case OPTYPE_INT2BIT:
    case OPTYPE_INT2HEX:
    case OPTYPE_INT2OCT:
    case OPTYPE_UNICHAR2OCT:
    case OPTYPE_OCT2UNICHAR:
    case OPTYPE_ENCODE_BASE64:
      delete u.expr.v1;
      delete u.expr.v2;
      break;
    case OPTYPE_UNDEF_RUNNING: // r1 [r2] b4
    case OPTYPE_TMR_RUNNING: // r1 [r2] b4
    case OPTYPE_CLASS_CASTING_REF:
      delete u.expr.r1;
      delete u.expr.r2;
      break;
    case OPTYPE_DECODE: // r1 r2 [v3] [v4]
      delete u.expr.r1;
      delete u.expr.r2;
      delete u.expr.v3;
      delete u.expr.v4;
      break;
    case OPTYPE_SUBSTR:
      delete u.expr.ti1;
      delete u.expr.v2;
      delete u.expr.v3;
      break;
    case OPTYPE_REGEXP:
      delete u.expr.ti1;
      delete u.expr.t2;
      delete u.expr.v3;
      break;
    case OPTYPE_DECOMP: // v1 v2 v3
      delete u.expr.v1;
      delete u.expr.v2;
      delete u.expr.v3;
      break;
    case OPTYPE_REPLACE:
      delete u.expr.ti1;
      delete u.expr.v2;
      delete u.expr.v3;
      delete u.expr.ti4;
      break;
    case OPTYPE_VALUEOF: // ti1 [subrefs2]
      delete u.expr.subrefs2;
      // fall through
    case OPTYPE_LENGTHOF: // ti1
    case OPTYPE_SIZEOF:  // ti1
    case OPTYPE_ISVALUE:
    case OPTYPE_ISBOUND:
    case OPTYPE_ISPRESENT:
    case OPTYPE_TTCN2STRING:
      delete u.expr.ti1;
      break;
    case OPTYPE_ISTEMPLATEKIND: // ti1 v2
      delete u.expr.ti1;
      delete u.expr.v2;
      break;
    case OPTYPE_ENCVALUE_UNICHAR: // ti1 [v2] [v3] [v4]
      delete u.expr.ti1;
      delete u.expr.v2;
      delete u.expr.v3;
      delete u.expr.v4;
      break;
    case OPTYPE_DECVALUE_UNICHAR: // r1 r2 [v3] [v4] [v5]
      delete u.expr.r1;
      delete u.expr.r2;
      delete u.expr.v3;
      delete u.expr.v4;
      delete u.expr.v5;
    case OPTYPE_TMR_READ:
    case OPTYPE_ACTIVATE:
      delete u.expr.r1;
      break;
    case OPTYPE_EXECUTE: // r1 [v2]
      delete u.expr.r1;
      delete u.expr.v2;
      break;
    case OPTYPE_CHECKSTATE_ANY: // [r1] v2
    case OPTYPE_CHECKSTATE_ALL:
      delete u.expr.r1;
      delete u.expr.v2;
      break;
    case OPTYPE_UNDEF_CREATE:
    case OPTYPE_CLASS_CREATE:
      delete u.expr.r1;
      if (u.expr.state != EXPR_CHECKED) {
        delete u.expr.t_list2;
      }
      else {
        delete u.expr.ap_list2;
      }
      break;
    case OPTYPE_COMP_CREATE: // r1 [v2] [v3] b4
      delete u.expr.r1;
      delete u.expr.v2;
      delete u.expr.v3;
      break;
    case OPTYPE_MATCH: // v1 t2
      delete u.expr.v1;
      delete u.expr.t2;
      break;
    case OPTYPE_ISCHOSEN: // r1 i2
      delete u.expr.r1;
      delete u.expr.i2;
      break;
    case OPTYPE_ISCHOSEN_V: // v1 i2
      delete u.expr.v1;
      delete u.expr.i2;
      break;
    case OPTYPE_ISCHOSEN_T: // t1 i2
      delete u.expr.t1;
      delete u.expr.i2;
      break;
    case OPTYPE_ACTIVATE_REFD: //v1 t_list2
      delete u.expr.v1;
      if(u.expr.state!=EXPR_CHECKED)
        delete u.expr.t_list2;
      else
        delete u.expr.ap_list2;
      break;
    case OPTYPE_EXECUTE_REFD: //v1 t_list2 [v3]