diff --git a/docs/Formula.md b/docs/Formula.md
index d731f5159bd748c10e2d7ffac72ad3c08b6f48ff..a7311769106974f61d41630ec5cd8ab4e8b5808d 100644
--- a/docs/Formula.md
+++ b/docs/Formula.md
@@ -105,8 +105,20 @@ The read part of every attribute is internally extracted in a vector of double w
 - A single element of a two-dimensional array attribute (Image) can be extracted with two indexes between square brackets (e.g. ```name/of/dev/attr[ind_row][ind_column]```).
 - A one-dimensional array can be extracted from a two-dimensional array attribute (Image) with a single index between square brackets (e.g. ```name/of/dev/attr[ind_row]```).
 
+## Lists and ranges of indexes to slice arrays
+Indexes can be specified as a comma separated list and/or hyphen-separated range (e.g. ```[i0,i1-i2,...]```).
+In this way:
+- A slice can be extracted from a one-dimensional array with a list and/or range of indexes between square brackets (e.g. ```name/of/dev/1Dattr[i0,i1-i2,...]```).
+- A subset of rows can be extracted from a two-dimensional array with a list and/or range of indexes for the first dimension (e.g. ```name/of/dev/2Dattr[i0,i1-i2,...]```).
+- A single column slice can be extracted from a two-dimensional array with a list and/or range of indexes for the first dimension and a single index for the second dimension (e.g. ```name/of/dev/2Dattr[i0,i1-i2,...][i3]```).
+- A single row slice can be extracted from a two-dimensional array with a single index for the first dimension and list/range of indexes for the second dimension (e.g. ```name/of/dev/2Dattr[i0][i1-i2,i3,...]```).
+- An array slice can be extracted from a two-dimensional array with a list and/or range of indexes for both the first and second dimensions (e.g. ```name/of/dev/2Dattr[i0-i1,...][i2,i3,...]```).
+- To specify all elements of one dimension index -1 can be used (e.g. Column 3 of all rows of 2D array ```name/of/dev/2Dattr[-1][3]```).
+
 If any index exceeds actual dimensions of the array, the formula is evaluated to ERROR with an out of bounds exception.
 
+No check is done on the order and uniqueness of indexes, so it is allowed to concatenate duplicated and out of order elements/rows/columns (e.g. ```name/of/dev/2Dattr[0-2,1,0,..]``` evaluates to an array with rows 0,1,2,1,0 of 2Dattr)
+
 ## Limitations
 
 - It is not possible to specify array constants (e.g. ```name/of/dev/attr > [val1,val2]```).
diff --git a/src/AlarmHandler.cpp b/src/AlarmHandler.cpp
index 8b50b963bef78486307cf490100500ef302cbc0e..4d6b8d5d4f86405d8a1522e2aeb13b97c5c82517 100644
--- a/src/AlarmHandler.cpp
+++ b/src/AlarmHandler.cpp
@@ -491,6 +491,8 @@ void AlarmHandler::init_device()
 	rule_names[formula_grammar::val_qualityID] = "ValQuality";
 	rule_names[formula_grammar::val_alarm_enum_stID] = "ValAlarmEnumStatus";
 	rule_names[formula_grammar::propertyID] = "EventProperty";
+	rule_names[formula_grammar::index_rangeID] = "RangeIndex";
+	rule_names[formula_grammar::index_listID] = "ListIndex";
 
 	/*
 	 * get device attribute properties and initialize internal
@@ -3813,6 +3815,10 @@ void AlarmHandler::do_alarm(bei_t& e)
 			push_archive_event("alarmSummary",attr_alarmSummary_read, alarmSummary_sz);
 			push_archive_event("alarmDisabled",attr_alarmDisabled_read, alarmDisabled_sz);
 		}
+		else
+		{
+			events->veclock.readerOut();
+		}
 		return;
 	}
 	//here not event error	
@@ -3948,6 +3954,7 @@ void AlarmHandler::do_alarm(bei_t& e)
 	}
 	else
 	{
+		events->veclock.readerOut();
 		DEBUG_STREAM << "AlarmHandler::"<<__func__<<": event=" << e.ev_name << "NOT FOUND IN EVENT TABLE" << endl;
 	}
 }  /* do_alarm() */
@@ -3987,7 +3994,7 @@ bool AlarmHandler::do_alarm_eval(string alm_name, string ev_name, Tango::TimeVal
 			it->second.to_be_evaluated = false;
 			it->second.attr_values.erase(it->second.attr_values.size()-1);
 			it->second.attr_values += string("}");
-			DEBUG_STREAM << "AlarmHandler::"<<__func__<<": Evaluation of " << it->second.formula << "; result=" << print_vector(res.value) << " quality=" << res.quality << " valid=" << (int)res.valid << endl;
+			DEBUG_STREAM << "AlarmHandler::"<<__func__<<": Evaluation of " << it->second.formula << "; result=" << print_array(res.value,res.dim_x,res.dim_y) << " quality=" << res.quality << " valid=" << (int)res.valid << endl;
 			changed = alarms.update(tmpname, ts, res, it->second.attr_values, it->second.grp2str(), it->second.msg, it->second.formula); 		//update internal structure and log to db
 			changed = changed || (prev_error && res.valid);
 			DEBUG_STREAM << "AlarmHandler::"<<__func__<<": changed=" << (int)changed << " error=" << (int)it->second.error << endl;
@@ -4168,6 +4175,7 @@ bool AlarmHandler::do_alarm_eval(string alm_name, string ev_name, Tango::TimeVal
 	}
 	else
 	{
+		alarms.vlock->readerOut();
 		ostringstream o;
 		//o << j->first << ": not found formula in alarm table" << ends;
 		o << (alm_name) << ": not found formula in alarm table";
@@ -4516,7 +4524,7 @@ formula_res_t AlarmHandler::eval_formula(tree_parse_info_t tree, string &attr_va
 	formula_res_t res = eval_expression(tree.trees.begin(), attr_values);
 	res.extract_result(); //from Array res.value to Scalar res.value
 #ifdef _DEBUG_FORMULA
-	DEBUG_STREAM << __func__ << ": 		 finally value=" << print_vector(res.value) << " valid=" << (int)res.valid << " error='" << res.error << "' ex_desc='" << res.ex_desc<<"' quality=" << res.quality << endl;
+	DEBUG_STREAM << __func__ << ": 		 finally value=" << print_array(res.value,res.dim_x,res.dim_y) << " valid=" << (int)res.valid << " error='" << res.error << "' ex_desc='" << res.ex_desc<<"' quality=" << res.quality << endl;
 #endif
 	if(res.valid)
 	{
@@ -4528,7 +4536,40 @@ formula_res_t AlarmHandler::eval_formula(tree_parse_info_t tree, string &attr_va
     return res;
 }
 
-formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values, vector<double> ev_ind)
+void AlarmHandler::eval_index_range(iter_t const& i, string &attr_values, vector<double> & ind)
+{
+	if(i->value.id() == formula_grammar::index_rangeID || i->value.id() == formula_grammar::indexID)
+	{
+		if(i->children.size() == 0)
+		{
+			std::string val_s(i->value.begin(), i->value.end());
+			long value = strtol(val_s.c_str(), NULL, 10);
+			if(value>=0)
+			{
+				ind.push_back(value);
+			}
+			else if(value == -1)
+			{
+				ind = {(double)(value)};
+			}
+		}
+		else if(i->children.size() == 2)
+		{
+			iter_t child = i->children.begin();
+			string val_s1(child->value.begin(), child->value.end());
+			long ind_start = strtol(val_s1.c_str(), NULL, 10);
+			string val_s2((child+1)->value.begin(), (child+1)->value.end());
+			long ind_end = strtol(val_s2.c_str(), NULL, 10);
+			if(ind_start>=0 && ind_end>=ind_start)
+			{
+				for(int ind_range=ind_start; ind_range<=ind_end; ind_range++)
+					ind.push_back((double)ind_range);
+			}
+		}
+	}
+}
+
+formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values, vector< vector<double> > ev_ind)
 {
 
     ostringstream err;
@@ -4545,9 +4586,11 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
         string val_d(i->value.begin(), i->value.end());
 		formula_res_t res;
 		res.value = {(strtod(val_d.c_str(), 0))};
+		res.dim_x=1;
+		res.dim_y=0;
 		res.valid = true;
 #ifdef _DEBUG_FORMULA
-		DEBUG_STREAM << "		node value real = " << val_d << "(value="<<print_vector(res.value)<<" quality="<<res.quality<<")" << endl;
+		DEBUG_STREAM << "		node value real = " << val_d << "(value="<<print_array(res.value,res.dim_x,res.dim_y)<<" quality="<<res.quality<<")" << endl;
 #endif
 		return res;
     }
@@ -4564,6 +4607,8 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
 #endif
 		formula_res_t res;
 		res.value = {(strtod(val_d.c_str(), 0))};
+		res.dim_x=1;
+		res.dim_y=0;
 		res.valid = true;
         return res;
     } 
@@ -4581,6 +4626,8 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
 #endif
 		formula_res_t res;
 		res.value = {(double)st};
+		res.dim_x=1;
+		res.dim_y=0;
 		res.valid = true;
         return res;
     }
@@ -4598,6 +4645,8 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
 #endif
 		formula_res_t res;
 		res.value = {(double)st};
+		res.dim_x=1;
+		res.dim_y=0;
 		res.valid = true;
         return res;
     }
@@ -4616,6 +4665,8 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
 #endif
 		formula_res_t res;
 		res.value = {(double)quality};
+		res.dim_x=1;
+		res.dim_y=0;
 		res.valid = true;
         return res;
 	}
@@ -4710,74 +4761,97 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
         	err <<  "in node event_ID(" << string(i->value.begin(), i->value.end()) << ") children=" << i->children.size();;
         	throw err.str(); 
         }
-		size_t child_ind=0;
-		while((child_ind < i->children.size() -1) && ((i->children.begin()+child_ind+1)->value.id() == formula_grammar::indexID))
+		vector<vector<double> > indexes;
+		iter_t child = i->children.begin();
+		if(child->value.id() != formula_grammar::nameID)
+		{
+        	err <<  "in node "<< rule_names[i->value.id()]<<"(" << string(i->value.begin(), i->value.end()) << ") expecting " << rule_names[formula_grammar::nameID] << " as first child";
+        	throw err.str(); 
+		}
+		child++;
+		while(child != i->children.end() && child->value.id() != formula_grammar::propertyID) //eval indexes
 		{
-			formula_res_t ind_tmp;
-			ind_tmp = eval_expression(i->children.begin()+child_ind+1, attr_values);		//array index
-			if(ind_tmp.value.size() == 1 && ind_tmp.value[0]>=0)
+			if(child->value.id() == formula_grammar::index_rangeID || child->value.id() == formula_grammar::indexID)
 			{
-				ind.value.push_back(ind_tmp.value[0]);
+				vector<double> ind_range;
+				eval_index_range(child, attr_values, ind_range);
+				if(!ind_range.empty())			
+					indexes.push_back(ind_range);
 			}
-			child_ind++;
+			else if(child->value.id() == formula_grammar::index_listID)
+			{
+				vector<double> ind_list;
+				iter_t granchild = child->children.begin();
+				while(granchild != child->children.end() && granchild->value.id() == formula_grammar::index_rangeID) //eval indexes
+				{
+					eval_index_range(granchild, attr_values, ind_list);
+					granchild++;
+				}
+				if(!ind_list.empty())
+					indexes.push_back(ind_list);
+			}
+			child++;
 		}
-		if(child_ind+1 == i->children.size() -1  && (i->children.begin()+child_ind+1)->value.id() == formula_grammar::propertyID)
+
+		if(child - i->children.begin() == (long int)i->children.size() -1  && child->value.id() == formula_grammar::propertyID)
 		{
-			if(string((i->children.begin()+child_ind+1)->value.begin(), (i->children.begin()+child_ind+1)->value.end()) == ".quality")
+			if(string(child->value.begin(), child->value.end()) == ".quality")
 			{
 				formula_res_t res;
 				res = eval_expression(i->children.begin(), attr_values);
 				res.value = {(double)res.quality};
+				res.dim_x=1;
+				res.dim_y=0;
 				ostringstream temp_attr_val;
-				temp_attr_val << "\"" <<  res.attr_name << string((i->children.begin()+child_ind+1)->value.begin(), (i->children.begin()+child_ind+1)->value.end()) << "\":[" <<print_vector(res.value) << "],";
+				temp_attr_val << "\"" <<  res.attr_name << string(child->value.begin(), child->value.end()) << "\":" <<print_array(res.value,res.dim_x,res.dim_y) << ",";
 				attr_values += temp_attr_val.str();
 #ifdef _DEBUG_FORMULA
-				DEBUG_STREAM << "		node event.quality -> " << print_vector(res.value) << endl;
+				DEBUG_STREAM << "		node event.quality -> " << print_array(res.value,res.dim_x,res.dim_y) << endl;
 #endif
 				return res;
 			}
-			else if(string((i->children.begin()+child_ind+1)->value.begin(), (i->children.begin()+child_ind+1)->value.end()) == ".alarm")
+			else if(string(child->value.begin(), child->value.end()) == ".alarm")
 			{
 				formula_res_t res;
-				if(!ind.value.empty())
-					res = eval_expression(i->children.begin(), attr_values, ind.value);
+				if(!indexes.empty())
+					res = eval_expression(i->children.begin(), attr_values, indexes);
 				else
 					res = eval_expression(i->children.begin(), attr_values);
 				std::transform(res.value.begin(), res.value.end(), res.value.begin(),
 								[](double n) { return (double)((n == _UNACK) || (n == _ACKED)); });
 				ostringstream temp_attr_val;
-				temp_attr_val << "\"" <<  res.attr_name << string((i->children.begin()+child_ind+1)->value.begin(), (i->children.begin()+child_ind+1)->value.end()) << "\":[" <<print_vector(res.value) << "],";
+				temp_attr_val << "\"" <<  res.attr_name << string(child->value.begin(), child->value.end()) << "\":" <<print_array(res.value,res.dim_x,res.dim_y) << ",";
 				attr_values += temp_attr_val.str();
 #ifdef _DEBUG_FORMULA
-				DEBUG_STREAM << "		node event.alarm -> " << print_vector(res.value)<< endl;
+				DEBUG_STREAM << "		node event.alarm -> " << print_array(res.value,res.dim_x,res.dim_y)<< endl;
 #endif
 				return res;
 			}
-			else if(string((i->children.begin()+child_ind+1)->value.begin(), (i->children.begin()+child_ind+1)->value.end()) == ".normal")
+			else if(string(child->value.begin(), child->value.end()) == ".normal")
 			{
 				formula_res_t res;
-				if(!ind.value.empty())
-					res = eval_expression(i->children.begin(), attr_values, ind.value);
+				if(!indexes.empty())
+					res = eval_expression(i->children.begin(), attr_values, indexes);
 				else
 					res = eval_expression(i->children.begin(), attr_values);
 				std::transform(res.value.begin(), res.value.end(), res.value.begin(),
 								[](double n) { return (double)((n == _NORM) || (n == _RTNUN)); });
 				ostringstream temp_attr_val;
-				temp_attr_val << "\"" <<  res.attr_name << string((i->children.begin()+child_ind+1)->value.begin(), (i->children.begin()+child_ind+1)->value.end()) << "\":[" <<print_vector(res.value) << "],";
+				temp_attr_val << "\"" <<  res.attr_name << string(child->value.begin(), child->value.end()) << "\":" <<print_array(res.value,res.dim_x,res.dim_y) << ",";
 				attr_values += temp_attr_val.str();
 #ifdef _DEBUG_FORMULA
-				DEBUG_STREAM << "		node event.normal -> " << print_vector(res.value) << endl;
+				DEBUG_STREAM << "		node event.normal -> " << print_array(res.value,res.dim_x,res.dim_y) << endl;
 #endif
 				return res;
 			}
 		}
-		else if(child_ind+1 < i->children.size() -1)//unsupported more indexes/qualities
+		else if(child - i->children.begin() < (long int)i->children.size() -1)//unsupported more indexes/qualities
 		{
-        	err <<  "expecting indexes or properties after attribute name, found instead: "<< string((i->children.begin()+child_ind+1)->value.begin(), (i->children.begin()+child_ind+1)->value.end());
+        	err <<  "expecting indexes or properties after attribute name, found instead: "<< string(child->value.begin(), child->value.end());
         	throw err.str(); 
         }
-		if(!ind.value.empty())
-			return eval_expression(i->children.begin(), attr_values, ind.value);
+		if(!indexes.empty())
+			return eval_expression(i->children.begin(), attr_values, indexes);
 		else
 			return eval_expression(i->children.begin(), attr_values);
     }    
@@ -4862,76 +4936,327 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
 			{
 				if(!ev_ind.empty())
 				{
-					size_t ev_ind_1d = ev_ind[0];
 					temp_attr_val << "\"" <<  it->name;
-					for(auto ei : ev_ind)
+					for(auto vei : ev_ind)
 					{
-						temp_attr_val << "[" << ei << "]";
+						if(!vei.empty())
+						{
+							temp_attr_val << "[" << print_vector(vei) << "]";
+						}
 					}
 					temp_attr_val << "\":";
-					if(ev_ind.size() ==1 && it->dim_y <=1)//single element of 1D array
+					if(it->dim_y <=1)//1D array
 					{
-						res.dim_x = 1;
-						res.dim_y = 0;
-						if(ev_ind[0] >= it->value.size())
+						if(ev_ind.size() ==1 && ev_ind[0].size() == 1 && ev_ind[0][0] != -1)//single element of 1D array (e.g. [0])
 						{
-							err << "Requested element " << ev_ind[0] << " is out of bounds with dim=" << it->value.size();
-							events->veclock.readerOut();
-							DEBUG_STREAM << __func__ << ": " << err.str() << endl;
-							Tango::Except::throw_exception(	//throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
-								(const char *)"OUT_OF_RANGE",
-								err.str(),
-								it->name);
+							res.dim_x = 1;
+							res.dim_y = 0;
+							if(ev_ind[0][0] >= it->value.size())
+							{
+								err << "Requested element " << ev_ind[0][0] << " is out of bounds with dim=" << it->value.size();
+								events->veclock.readerOut();
+								DEBUG_STREAM << __func__ << ": " << err.str() << endl;
+								Tango::Except::throw_exception(	//throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
+									(const char *)"OUT_OF_RANGE",
+									err.str(),
+									it->name);
+							}
+							res.value = {it->value.at(ev_ind[0][0])};//throw  std::out_of_range
+							temp_attr_val << "[" << res.value[0] << "],";
 						}
-						res.value = {it->value.at(ev_ind[0])};//throw  std::out_of_range
-						temp_attr_val << "[" << res.value[0] << "],";
-					}
-					else if(ev_ind.size() == 1 && it->dim_y > 1)//single row of 2D array
-					{
-						res.dim_y = 0;
-						if(ev_ind[0] >= it->dim_y)
+						else if(ev_ind.size() ==1 && ev_ind[0].size() > 1)//multiple elements of 1D array (e.g. [0,1,2])
 						{
-							err << "Requested row " << ev_ind[0] << " is out of bounds with dim_y=" << it->dim_y;
-							events->veclock.readerOut();
+							res.dim_y = 0;
+							for(auto ei0 : ev_ind[0])
+							{
+								if(ei0 < 0 || ei0 >= it->value.size())
+								{
+									err << "Requested element " << ei0 << " is out of bounds with dim=" << it->value.size();
+									temp_attr_val << "[]";
+									events->veclock.readerOut();
+									DEBUG_STREAM << __func__ << ": " << err.str() << endl;
+									Tango::Except::throw_exception(	//throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
+										(const char *)"OUT_OF_RANGE",
+										err.str(),
+										it->name);
+								}
+								else
+								{
+									res.value.push_back(it->value.at(ei0));//throw  std::out_of_range
+								}
+							}
+							res.dim_x = res.value.size();
+							temp_attr_val << print_array(res.value, res.dim_x, res.dim_y) << ",";
+						}
+						else if(ev_ind.size() ==1 && ev_ind[0].size() == 1 && ev_ind[0][0]==-1)//all elements of 1D array (e.g. [-1])
+						{
+							res.dim_y = 0;
+							res.value = it->value;
+							res.dim_x = it->dim_x;
+							temp_attr_val << print_array(res.value, res.dim_x, res.dim_y) <<",";						
+						}
+						else
+						{
+							err << "UNSUPPORTED additional indexes in 1D array: " << ev_ind.size() << " indexes given, dim_x=" << it->dim_x << " dim_y=" << it->dim_y;
 							DEBUG_STREAM << __func__ << ": " << err.str() << endl;
-							Tango::Except::throw_exception(	//throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
-								(const char *)"OUT_OF_RANGE",
-								err.str(),
-								it->name);
+							events->veclock.readerOut();
+							throw err.str();
 						}
-						auto vstart = it->value.begin();
-						auto vend = it->value.begin();
-						advance(vstart,(int)(ev_ind[0] * (it->dim_x)));
-						advance(vend,(int)(ev_ind[0]+1)*it->dim_x);
-						res.value = value_t(vstart,vend);
-						temp_attr_val << "[" << print_vector(res.value) << "],";
 					}
-					else if(ev_ind.size() == 2 && it->dim_y > 1)//single element of 2D array
+					else if(it->dim_y > 1)//2D array
 					{
-						res.dim_x = 1;
-						res.dim_y = 0;
-						if(ev_ind[0] >= it->dim_y)
+						//single row of 2D array (e.g. [0] or [0][-1])
+						if((ev_ind.size() == 1 || //only first index
+							(ev_ind.size() == 2 && ev_ind[1].size() == 1 && ev_ind[1][0] == -1)) //or also second index = -1
+						&& ev_ind[0].size() == 1 && ev_ind[0][0] != -1) // and first index not -1
 						{
-							err << "Requested row " << ev_ind[0] << " is out of bounds with dim_y=" << it->dim_y;
-							events->veclock.readerOut();
-							DEBUG_STREAM << __func__ << ": " << err.str() << endl;
-							Tango::Except::throw_exception(	//throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
-								(const char *)"OUT_OF_RANGE",
-								err.str(),
-								it->name);
+							res.dim_y = 0;
+							if(ev_ind[0][0] >= it->dim_y)
+							{
+								err << "Requested row " << ev_ind[0][0] << " is out of bounds with dim_y=" << it->dim_y;
+								events->veclock.readerOut();
+								DEBUG_STREAM << __func__ << ": " << err.str() << endl;
+								Tango::Except::throw_exception(	//throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
+									(const char *)"OUT_OF_RANGE",
+									err.str(),
+									it->name);
+							}
+							auto vstart = it->value.begin();//start iterator of a row in a vector containing a 2D array
+							auto vend = it->value.begin();//end iterator of a row in a vector containing a 2D array
+							advance(vstart,(int)(ev_ind[0][0] * (it->dim_x)));
+							advance(vend,(int)(ev_ind[0][0]+1) * it->dim_x);
+							res.value = value_t(vstart,vend);
+							temp_attr_val << "" << print_array(res.value,res.dim_x,res.dim_y) << ",";
 						}
-						if(ev_ind[1] >= it->dim_x)
+						else if((ev_ind.size() == 1 || //only first index
+							(ev_ind.size() == 2 && ev_ind[1].size() == 1 && ev_ind[1][0] == -1)) //or also second index = -1
+							&& ev_ind[0].size() > 1)//multiple rows of 2D array (e.g. [0,1,2] or [0,1,2][-1])
 						{
-							err << "Requested column " << ev_ind[1] << " is out of bounds with dim_x=" << it->dim_x;
-							events->veclock.readerOut();
+							res.dim_x = it->dim_x;
+							res.dim_y = ev_ind[0].size();
+
+							for(auto ei0 : ev_ind[0])
+							{
+								if(ei0 < 0 || ei0 >= it->value.size())
+								{
+									err << "Requested element " << ei0 << " is out of bounds with dim=" << it->value.size();
+									temp_attr_val << "[]";
+									events->veclock.readerOut();
+									DEBUG_STREAM << __func__ << ": " << err.str() << endl;
+									Tango::Except::throw_exception(	//throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
+										(const char *)"OUT_OF_RANGE",
+										err.str(),
+										it->name);
+								}
+								else
+								{
+									auto vstart = it->value.begin();//start iterator of a row in a vector containing a 2D array
+									auto vend = it->value.begin();//end iterator of a row in a vector containing a 2D array
+									advance(vstart,(int)(ei0 * (it->dim_x)));
+									advance(vend,(int)(ei0+1) * it->dim_x);
+									value_t row = value_t(vstart,vend);
+									res.value.insert(
+										res.value.end(),
+										std::make_move_iterator(row.begin()),
+										std::make_move_iterator(row.end())
+										);
+
+								}
+							}
+							temp_attr_val << print_array(res.value,res.dim_x,res.dim_y) << ",";
+						}
+						else if((ev_ind.size() == 1 || //only first index
+							(ev_ind.size() == 2 && ev_ind[1].size() == 1 && ev_ind[1][0] == -1)) //or also second index = -1
+							&& ev_ind[0].size() == 1 && ev_ind[0][0] == -1)//all rows of 2D array (e.g. [-1] or [-1][-1])
+						{
+							res.dim_x = it->dim_x;
+							res.dim_y = it->dim_y;
+							res.value = it->value;
+							temp_attr_val << print_array(res.value,res.dim_x,res.dim_y) << ",";
+						}
+						else if(ev_ind.size() == 2 && ev_ind[0].size() == 1 && ev_ind[0][0] != -1 && ev_ind[1].size() == 1 && ev_ind[1][0] != -1)//single element of 2D array (e.g. [0][1])
+						{
+							res.dim_x = 1;
+							res.dim_y = 0;
+							if(ev_ind[0][0] >= it->dim_y)
+							{
+								err << "Requested row " << ev_ind[0][0] << " is out of bounds with dim_y=" << it->dim_y;
+								temp_attr_val << "[]";
+								events->veclock.readerOut();
+								DEBUG_STREAM << __func__ << ": " << err.str() << endl;
+								Tango::Except::throw_exception(	//throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
+									(const char *)"OUT_OF_RANGE",
+									err.str(),
+									it->name);
+							}
+							if(ev_ind[1][0] >= it->dim_x)
+							{
+								err << "Requested column " << ev_ind[1][0] << " is out of bounds with dim_x=" << it->dim_x;
+								temp_attr_val << "[]";
+								events->veclock.readerOut();
+								DEBUG_STREAM << __func__ << ": " << err.str() << endl;
+								Tango::Except::throw_exception(	//throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
+									(const char *)"OUT_OF_RANGE",
+									err.str(),
+									it->name);
+							}
+							res.value = {it->value.at(ev_ind[0][0]*it->dim_x + ev_ind[1][0])};//throw  std::out_of_range
+							temp_attr_val << "[" <<res.value[0] << "],";//throw  std::out_of_range
+						}
+						else if(ev_ind.size() == 2 && ev_ind[0].size() > 1 && ev_ind[1].size() == 1 && ev_ind[1][0] != -1)//single column slice of 2D array (e.g. [0,1,2][3])
+						{
+							res.dim_x = 1;
+							long ei1 = ev_ind[1][0];
+							if(ei1 >= it->dim_x)
+							{
+								err << "Requested column " << ei1 << " is out of bounds with dim_x=" << it->dim_x;
+								temp_attr_val << "[]";
+								events->veclock.readerOut();
+								DEBUG_STREAM << __func__ << ": " << err.str() << endl;
+								Tango::Except::throw_exception(	//throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
+									(const char *)"OUT_OF_RANGE",
+									err.str(),
+									it->name);
+							}
+							for(auto ei0 : ev_ind[0])
+							{
+								if(ei0 < 0 || ei0 >= it->dim_y)
+								{
+									err << "Requested row " << ei0 << " is out of bounds with dim_y=" << it->dim_y;
+									temp_attr_val << "[]";
+									events->veclock.readerOut();
+									DEBUG_STREAM << __func__ << ": " << err.str() << endl;
+									Tango::Except::throw_exception(	//throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
+										(const char *)"OUT_OF_RANGE",
+										err.str(),
+										it->name);
+								}
+								res.value.push_back(it->value.at(ei0*it->dim_x + ei1));//throw  std::out_of_range
+							}
+							res.dim_y = ev_ind[0].size();
+							temp_attr_val <<print_array(res.value,res.dim_x,res.dim_y) <<",";
+						}
+						else if(ev_ind.size() == 2 && ev_ind[0].size() == 1 && ev_ind[0][0] == -1 && ev_ind[1].size() == 1 && ev_ind[1][0] != -1)//single column of 2D array (e.g. [-1][3])
+						{
+							res.dim_x = 1;
+							long ei1 = ev_ind[1][0];
+							if(ei1 >= it->dim_x)
+							{
+								err << "Requested column " << ei1 << " is out of bounds with dim_x=" << it->dim_x;
+								temp_attr_val << "[]";
+								events->veclock.readerOut();
+								DEBUG_STREAM << __func__ << ": " << err.str() << endl;
+								Tango::Except::throw_exception(	//throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
+									(const char *)"OUT_OF_RANGE",
+									err.str(),
+									it->name);
+							}
+							for(long ei0 = 0; ei0 < it->dim_y; ei0++)
+							{
+								res.value.push_back(it->value.at(ei0*it->dim_x + ei1));//throw  std::out_of_range
+							}
+							res.dim_y = it->dim_y;
+							temp_attr_val <<print_array(res.value,res.dim_x,res.dim_y) <<",";
+						}
+						else if(ev_ind.size() == 2 && ev_ind[0].size() == 1  && ev_ind[0][0] != -1 && ev_ind[1].size() > 1)//single row slice of 2D array (e.g. [0][1,2,3])
+						{
+							res.dim_y = 0;
+							long ei0 = ev_ind[0][0];
+							if(ei0 >= it->dim_y)
+							{
+								err << "Requested row " << ei0 << " is out of bounds with dim_y=" << it->dim_y;
+								temp_attr_val << "[]";
+								events->veclock.readerOut();
+								DEBUG_STREAM << __func__ << ": " << err.str() << endl;
+								Tango::Except::throw_exception(	//throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
+									(const char *)"OUT_OF_RANGE",
+									err.str(),
+									it->name);
+							}
+							for(auto ei1 : ev_ind[1])
+							{
+								if(ei1 < 0 || ei1 >= it->dim_x)
+								{
+									err << "Requested column " << ei1 << " is out of bounds with dim_x=" << it->dim_x;
+									temp_attr_val << "[]";
+									events->veclock.readerOut();
+									DEBUG_STREAM << __func__ << ": " << err.str() << endl;
+									Tango::Except::throw_exception(	//throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
+										(const char *)"OUT_OF_RANGE",
+										err.str(),
+										it->name);
+								}
+								res.value.push_back(it->value.at(ei0*it->dim_x + ei1));//throw  std::out_of_range
+							}
+							res.dim_x = ev_ind[1].size();
+							temp_attr_val <<print_array(res.value,res.dim_x,res.dim_y) <<",";							
+						}
+						else if(ev_ind.size() == 2 && ev_ind[0].size() > 1 && ev_ind[1].size() > 1)//subarray of 2D array (e.g. [0,1][2,3])
+						{
+							for(auto ei0 : ev_ind[0])
+							{
+								if(ei0 < 0 || ei0 >= it->dim_y)
+								{
+									err << "Requested row " << ei0 << " is out of bounds with dim_y=" << it->dim_y;
+									temp_attr_val << "[]";
+									events->veclock.readerOut();
+									DEBUG_STREAM << __func__ << ": " << err.str() << endl;
+									Tango::Except::throw_exception(	//throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
+										(const char *)"OUT_OF_RANGE",
+										err.str(),
+										it->name);
+								}
+								for(auto ei1 : ev_ind[1])
+								{
+									if(ei1 < 0 || ei1 >= it->dim_x)
+									{
+										err << "Requested column " << ei1 << " is out of bounds with dim_x=" << it->dim_x;
+										temp_attr_val << "[]";
+										events->veclock.readerOut();
+										DEBUG_STREAM << __func__ << ": " << err.str() << endl;
+										Tango::Except::throw_exception(	//throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
+											(const char *)"OUT_OF_RANGE",
+											err.str(),
+											it->name);
+									}
+									res.value.push_back(it->value.at(ei0*it->dim_x + ei1));//throw  std::out_of_range
+								}
+							}
+							res.dim_x = ev_ind[1].size();
+							res.dim_y = ev_ind[0].size();
+							temp_attr_val <<print_array(res.value,res.dim_x,res.dim_y) <<",";
+						}
+						else if(ev_ind.size() == 2 && ev_ind[0].size() == 1 && ev_ind[0][0] == -1 && ev_ind[1].size() > 1)//subarray of 2D array (e.g. [-1][2,3])
+						{
+							for(long ei0 = 0; ei0 < it->dim_y; ei0++)
+							{
+								for(auto ei1 : ev_ind[1])
+								{
+									if(ei1 < 0 || ei1 >= it->dim_x)
+									{
+										err << "Requested column " << ei1 << " is out of bounds with dim_x=" << it->dim_x;
+										temp_attr_val << "[]";
+										events->veclock.readerOut();
+										DEBUG_STREAM << __func__ << ": " << err.str() << endl;
+										Tango::Except::throw_exception(	//throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
+											(const char *)"OUT_OF_RANGE",
+											err.str(),
+											it->name);
+									}
+									res.value.push_back(it->value.at(ei0*it->dim_x + ei1));//throw  std::out_of_range
+								}
+							}
+							res.dim_x = ev_ind[1].size();
+							res.dim_y = it->dim_y;
+							temp_attr_val <<print_array(res.value,res.dim_x,res.dim_y) <<",";
+						}
+						else //ev_ind.size() > 2
+						{
+							err << "UNSUPPORTED additional indexes in 2D array: " << ev_ind.size() << " indexes given, dim_x=" << it->dim_x << " dim_y=" << it->dim_y;
 							DEBUG_STREAM << __func__ << ": " << err.str() << endl;
-							Tango::Except::throw_exception(	//throw exception to have error not delayed otherwise it is subject to err_delay (delayed error notification)
-								(const char *)"OUT_OF_RANGE",
-								err.str(),
-								it->name);
+							events->veclock.readerOut();
+							throw err.str();
 						}
-						res.value = {it->value.at(ev_ind[0]*it->dim_x + ev_ind[1])};//throw  std::out_of_range
-						temp_attr_val << "[" <<res.value[0] << "],";//throw  std::out_of_range
 					}
 					else //TODO N-DIMENSIONAL arrays
 					{
@@ -4944,7 +5269,7 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
 				else
 				{
 					res.value = it->value;
-					temp_attr_val << "\"" <<  it->name << "\":[" <<print_vector(res.value) << "],";
+					temp_attr_val << "\"" <<  it->name << "\":" <<print_array(res.value,res.dim_x,res.dim_y) << ",";
 				}
 			}
 			else
@@ -4977,6 +5302,8 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
      	formula_res_t res;
 		res.valid = true;
      	res.value = {(strtod(val_d.c_str(), 0))};
+		res.dim_x=1;
+		res.dim_y=0;
         return res;
     }   
     else if (i->value.id() == formula_grammar::logical_exprID)
@@ -5263,11 +5590,15 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
 				if (string(i->value.begin(), i->value.end()) == string("!="))
 				{
 					res.value = {(double)(attr_val != val_string)};
+					res.dim_x=1;
+					res.dim_y=0;
 					return res;
 				}
 				else if (string(i->value.begin(), i->value.end()) == string("=="))
 				{
 					res.value = {(double)(attr_val == val_string)};
+					res.dim_x=1;
+					res.dim_y=0;
 					return res;
 				}
 				else
@@ -5369,11 +5700,15 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
 		{
 			res = eval_expression(i->children.begin(), attr_values);
 			res.value = {(double)res.quality};//ignore values and keep quality as result
+			res.dim_x=1;
+			res.dim_y=0;
 			return res;
 		}
 		else if ((string(i->value.begin(), i->value.end()) == string("AND") || string(i->value.begin(), i->value.end()) == string("OR")))
 		{
 			res = eval_expression(i->children.begin(), attr_values);
+			res.dim_x=1;
+			res.dim_y=0;
 			if(string(i->value.begin(), i->value.end()) == string("AND"))
 			{
 				res.value = {(double)std::accumulate(res.value.begin(), res.value.end(), (bool)true, [](bool acc, double n) { return (bool)(acc && (bool)(n));})};
@@ -5383,7 +5718,7 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
 				res.value = {(double)std::accumulate(res.value.begin(), res.value.end(), (bool)false, [](bool acc, double n) { return (bool)(acc || (bool)(n));})};
 			}
 #ifdef _DEBUG_FORMULA
-			DEBUG_STREAM << "		node funcID("<<string(i->value.begin(), i->value.end())<<") value="<<print_vector(res.value)<<" quality="<<res.quality<< endl;
+			DEBUG_STREAM << "		node funcID("<<string(i->value.begin(), i->value.end())<<") value="<<print_array(res.value,res.dim_x,res.dim_y)<<" quality="<<res.quality<< endl;
 #endif
 			return res;
 		}
@@ -5496,6 +5831,8 @@ formula_res_t AlarmHandler::eval_expression(iter_t const& i, string &attr_values
     }
     formula_res_t res;
     res.value = {(double)0.0};
+	res.dim_x=1;
+	res.dim_y=0;
 	res.valid = false;
     return res;
 }
@@ -5686,7 +6023,6 @@ void AlarmHandler::prepare_alarm_attr()
 		time_sec= ai->second.ts.tv_sec;
 		//gmtime_r(&time_sec,&time_tm); //-> UTC
 		localtime_r(&time_sec,&time_tm);
-		time_buf[64];
 		strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S", &time_tm);
 
 #ifndef ALM_SUM_STR
diff --git a/src/AlarmHandler.h b/src/AlarmHandler.h
index d8b6007263cb8a37dda7660794787613ea49b381..617337276dec25530ff8cb234b9a25189045cf34 100644
--- a/src/AlarmHandler.h
+++ b/src/AlarmHandler.h
@@ -607,7 +607,8 @@ private:
 	formula_res_t eval_formula(tree_parse_info_t tree, string &attr_values);
 	void find_event_formula(tree_parse_info_t tree, vector<string> &);
 	
-	formula_res_t eval_expression(iter_t const& i, string &attr_values, vector<double> ev_ind={});			//recursive tree node evaluation
+	formula_res_t eval_expression(iter_t const& i, string &attr_values, vector< vector<double> > ev_ind={});			//recursive tree node evaluation
+	void eval_index_range(iter_t const& i, string &attr_values, vector<double> & ind);
 	void eval_node_event(iter_t const& i, vector<string> & ev);		//recursive tree node evaluation		
 
 	void prepare_alarm_attr();	//for read attribute alarm and push_change_event
diff --git a/src/alarm_table.cpp b/src/alarm_table.cpp
index 6c1932c1f8cc225a4ce0655b16fee3b6493ea87b..f1a6d45f90f36898b7b65d759eb7f40e227260f2 100644
--- a/src/alarm_table.cpp
+++ b/src/alarm_table.cpp
@@ -374,14 +374,14 @@ bool alarm_table::update(const string& alm_name, Tango::TimeVal ts, formula_res_
 		found->second.quality = res.quality;
 		bool status_on_delay;
 		if(found->second.on_delay > 0)		//if enabled on delay
-			status_on_delay = ((bool)(res.value[0] != 0)) && (found->second.on_counter >= 1) && ((ts.tv_sec - found->second.on_delay) > found->second.ts_on_delay.tv_sec);	//formula gives true and on delay has passed
+			status_on_delay = ((bool)(!res.value.empty() && res.value[0] != 0)) && (found->second.on_counter >= 1) && ((ts.tv_sec - found->second.on_delay) > found->second.ts_on_delay.tv_sec);	//formula gives true and on delay has passed
 		else
-			status_on_delay = (bool)(res.value[0] != 0);
+			status_on_delay = (bool)(!res.value.empty() && res.value[0] != 0);
 		bool status_off_delay;
 		if(found->second.off_delay > 0)		//if enabled off delay
-			status_off_delay = (!(bool)(res.value[0] != 0)) && (found->second.off_counter >= 1) && ((ts.tv_sec - found->second.off_delay) > found->second.ts_off_delay.tv_sec);	//formula gives false and off delay has passed
+			status_off_delay = (!(bool)(!res.value.empty() && res.value[0] != 0)) && (found->second.off_counter >= 1) && ((ts.tv_sec - found->second.off_delay) > found->second.ts_off_delay.tv_sec);	//formula gives false and off delay has passed
 		else
-			status_off_delay = !(bool)(res.value[0] != 0);
+			status_off_delay = !(bool)(!res.value.empty() && res.value[0] != 0);
 		//if status changed:
 		// - from S_NORMAL to S_ALARM considering also on delay
 		//or
@@ -389,12 +389,12 @@ bool alarm_table::update(const string& alm_name, Tango::TimeVal ts, formula_res_
 		if((status_on_delay && (found->second.stat == S_NORMAL)) || (status_off_delay && (found->second.stat == S_ALARM)))
 		{
 			ret_changed=true;
-			if((bool)(res.value[0] != 0))
+			if((bool)(!res.value.empty() && res.value[0] != 0))
 				found->second.ack = NOT_ACK;	//if changing from NORMAL to ALARM -> NACK
 			//a.grp = found->second.grp2str();
 			//a.msg = (int)(res.value[0]) ? found->second.msg : "";
 			found->second.ts = ts;	/* store event timestamp into alarm timestamp */ //here update ts only if status changed
-			if((bool)(res.value[0] != 0))
+			if((bool)(!res.value.empty() && res.value[0] != 0))
 			{
 				found->second.is_new = 1;		//here set this alarm as new, read attribute set it to 0	//12-06-08: StopNew command set it to 0
 				if(found->second.dp_a && ((ts.tv_sec - startup_complete.tv_sec) > 10))		//action from S_NORMAL to S_ALARM
@@ -525,7 +525,7 @@ bool alarm_table::update(const string& alm_name, Tango::TimeVal ts, formula_res_
 			found->second.error = true;
 		}
 
-		if((bool)(res.value[0] != 0)) {
+		if((bool)(!res.value.empty() && res.value[0] != 0)) {
 			found->second.on_counter++;
 			found->second.off_counter = 0;
 		} else {
diff --git a/src/alarm_table.h b/src/alarm_table.h
index d3701ec44af780ad8a29fb7d9b9f41cdced421a2..7db0b96d43042c2e61482e5013bb82b570c8daba 100644
--- a/src/alarm_table.h
+++ b/src/alarm_table.h
@@ -45,7 +45,7 @@
 #endif
 
 //#include "log_thread.h"
-
+#define MAX_ARRAY_PRINTED_CHARS 1000
 #define LOG_STREAM		TANGO_LOG
 
 using namespace std;
@@ -119,12 +119,59 @@ string print_vector(const std::vector<T>& v, const char * const separator = ",")
     {
         std::copy(v.begin(),
                   --v.end(),
-                  std::ostream_iterator<T>(out/*std::cout*/, separator));
+                  std::ostream_iterator<T>(out, separator));
         out << v.back();
     }
 	return out.str();
 }
 
+template <typename T>
+string print_array(const std::vector<T>& v, long dim_x, long dim_y, const char * const separator = ",")
+{
+	ostringstream out;
+	if(dim_y <1)
+	{
+		out <<"["<< print_vector(v);
+		out.seekp(0, ios::end);
+		stringstream::pos_type offset = out.tellp();
+		if(offset > MAX_ARRAY_PRINTED_CHARS)
+		{
+			out.seekp(MAX_ARRAY_PRINTED_CHARS, ios::beg);//limit size
+			out << "...]" << ends;
+		}
+		else
+			out << "]";
+		return out.str();
+	}
+	out << "[";	
+	for(long i=0; i<dim_y; i++)
+	{
+		auto vstart = v.begin();//start iterator of a row in a vector containing a 2D array
+		auto vend = v.begin();//end iterator of a row in a vector containing a 2D array
+		advance(vstart,(int)(i * (dim_x)));
+		advance(vend,(int)((i+1) * dim_x));
+		value_t row = value_t(vstart,vend);
+		out <<"["<< print_vector(row);
+		out.seekp(0, ios::end);
+		stringstream::pos_type offset = out.tellp();
+		if(offset > MAX_ARRAY_PRINTED_CHARS)
+		{
+			out.seekp(MAX_ARRAY_PRINTED_CHARS, ios::beg);//limit size
+			out << "...]]" << ends;
+			break;
+		}
+		else
+			out << "]";
+		if(i < dim_y-1)
+		{
+			out << ",";
+		}
+    }
+
+	out << "]";
+	return out.str();
+}
+
 struct vectorUtils
 {
 static double fBitAnd(long a, long b){	return (double)(a & b);}
@@ -236,7 +283,12 @@ struct formula_res_t
 	}
 	void extract_result()
 	{
-		value = {(double)std::accumulate(value.begin(), value.end(), (bool)false, [](bool a, double b) { return (bool)(a || (bool)b); })};
+		if(!value.empty())
+		{
+			value = {(double)std::accumulate(value.begin(), value.end(), (bool)false, [](bool a, double b) { return (bool)(a || (bool)b); })};
+			dim_x=1;
+			dim_y=0;
+		}
 	}
 
 	formula_res_t operator==(const formula_res_t& e)
diff --git a/src/event_table.cpp b/src/event_table.cpp
index 2f9f97731dc9670edbc4d958c0c03b45d69ff65b..af8cf4fa6683eb1ae2595bc61028db505e48e8b0 100644
--- a/src/event_table.cpp
+++ b/src/event_table.cpp
@@ -201,6 +201,8 @@ event::event(string& s, value_t& v, Tango::TimeVal& t) : \
 	event_id = SUB_ERR;
 	err_counter = 0;
 	valid = false;
+	dim_x=0;
+	dim_y=0;
 }
 
 event::event(string& s) : name(s)
@@ -222,7 +224,9 @@ event::event(string& s) : name(s)
 	type = -1;
 	event_id = SUB_ERR;
 	err_counter = 0;
-	valid = false;	
+	valid = false;
+	dim_x=0;
+	dim_y=0;
 }
 
 bool event::operator==(const event& e)
@@ -289,27 +293,10 @@ void event_table::summary(list<string> &evs)
 
 			ev_summary << KEY(EVENT_TIME_KEY) << time_buf << SEP;
 			ostringstream tmp_val;
-			//if(i->valid)
-			{
-				tmp_val << "[" ;
-				if(i->type != Tango::DEV_STRING)
-				{
-					if(i->read_size > 0 && i->value.size() > 0)
-					{
-						for(size_t k=0; k<i->read_size && k<i->value.size(); k++)
-						{
-							tmp_val << i->value[k];
-							if(k < i->read_size-1 && k<i->value.size()-1)
-								tmp_val << ",";
-						}
-					}
-				}
-				else
-				{
-					tmp_val << "\""<<i->value_string<<"\"";
-				}
-				tmp_val << "]";
-			}
+			if(i->type != Tango::DEV_STRING)
+				tmp_val << print_array(i->value,i->dim_x,i->dim_y);
+			else
+				tmp_val << "[\""<<i->value_string<<"\"]";
 			ev_summary << KEY(ATTR_VALUES_KEY) << tmp_val.str() << SEP;
 			ostringstream tmp_ex;
 			//tmp_ex.str("");
@@ -838,6 +825,9 @@ void event_table::add(string &signame, vector<string> contexts, int to_do, bool
 			signal->running = false;
 			signal->stopped = true;
 			signal->paused = false;
+			signal->valid = false;
+			signal->dim_x=0;
+			signal->dim_y=0;		
 			//DEBUG_STREAM << "event_table::"<<__func__<<": signame="<<signame<<" created signal"<< endl;
 		}
 		else if(found && start)
diff --git a/src/formula_grammar.h b/src/formula_grammar.h
index 8a83118f0c19bcd2401af1cfa6fb68bd76fd90c9..54aca74707d3f67681c8ceb6bbffe035e84e1bd3 100644
--- a/src/formula_grammar.h
+++ b/src/formula_grammar.h
@@ -125,6 +125,8 @@ struct formula_grammar : public grammar<formula_grammar>
     static const int val_qualityID = 23;
     static const int val_alarm_enum_stID = 24;
     static const int propertyID = 25;
+	static const int index_rangeID = 26; 
+	static const int index_listID = 27; 
 
     
     symbols<unsigned int> tango_states;
@@ -207,9 +209,18 @@ struct formula_grammar : public grammar<formula_grammar>
             			]
             		]
 //            	=	repeat_p(3)[(+symbol) >> ch_p('/')] >> (+symbol) 
-            	; 
+            	;
+            index_range
+            	= 	
+					( uint_p >> !(discard_node_d[ch_p('-')] >> uint_p))	// n or n-m
+            	;
+            index_list
+            	= 	(index_range >> *(discard_node_d[ch_p(',')] >> index_range)) // n-m,k,s-t,..
+            	;
             index
-            	= 	inner_node_d[ch_p('[') >> uint_p >> ch_p(']')]
+				=  discard_node_d[ch_p('[')] >> 
+				(str_p("-1") | index_list) >> 
+				discard_node_d[ch_p(']')]
             	;
             property
             	= 	str_p(".quality")
@@ -399,6 +410,8 @@ struct formula_grammar : public grammar<formula_grammar>
         rule<ScannerT, parser_context<>, parser_tag<expr_atomID> > expr_atom;
         rule<ScannerT, parser_context<>, parser_tag<funcID> > function;
 		rule<ScannerT, parser_context<>, parser_tag<nameID> > name;
+		rule<ScannerT, parser_context<>, parser_tag<index_rangeID> > index_range;
+		rule<ScannerT, parser_context<>, parser_tag<index_listID> > index_list;
 		rule<ScannerT, parser_context<>, parser_tag<indexID> > index;
 		rule<ScannerT, parser_context<>, parser_tag<val_stringID> > val_string;
 		rule<ScannerT, parser_context<>, parser_tag<func_dualID> > function_dual;