diff --git a/compiler2/record.c b/compiler2/record.c index ee286762438e7a53f472d99d0d599885c92a3731..aad4dc9036cc470183804557807f13d67141fc51 100644 --- a/compiler2/record.c +++ b/compiler2/record.c @@ -625,6 +625,7 @@ char* generate_raw_coding(char* src, " myleaf.body.node.nodes[%lu]->coding_descr = &%s_descr_;\n" " myleaf.body.node.nodes[%lu]->calcof.lengthto.num_of_fields = %d;\n" " myleaf.body.node.nodes[%lu]->calcof.lengthto.unit = %d;\n" + " myleaf.body.node.nodes[%lu]->calcof.lengthto.offset = %d;\n" " myleaf.body.node.nodes[%lu]->calcof.lengthto.fields = " "init_lengthto_fields_list(%d);\n" " myleaf.body.node.nodes[%lu]->length = %d;\n", @@ -632,6 +633,7 @@ char* generate_raw_coding(char* src, (unsigned long)i, sdef->elements[i].typedescrname, (unsigned long)i, sdef->elements[i].raw.lengthto_num, (unsigned long)i, sdef->elements[i].raw.unit, + (unsigned long)i, sdef->elements[i].raw.lengthto_offset, (unsigned long)i, sdef->elements[i].raw.lengthto_num, (unsigned long)i, sdef->elements[i].raw.fieldlength); for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) { @@ -724,6 +726,8 @@ char* generate_raw_coding(char* src, "calcof.lengthto.num_of_fields = %d;\n" " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]->" "calcof.lengthto.unit = %d;\n" + " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]->" + "calcof.lengthto.offset = %d;\n" " myleaf.body.node.nodes[%lu]->body.node.nodes[%d]->" "calcof.lengthto.fields = " "init_lengthto_fields_list(%d);\n", @@ -736,6 +740,8 @@ char* generate_raw_coding(char* src, (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, sdef->elements[i].raw.unit, (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, + sdef->elements[i].raw.lengthto_offset, + (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, sdef->elements[i].raw.lengthto_num); for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) { if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { @@ -791,10 +797,13 @@ char* generate_raw_coding(char* src, " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]->" "calcof.lengthto.unit = %d;\n" " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]->" + "calcof.lengthto.offset = %d;\n" + " myleaf.body.node.nodes[%lu]->body.node.nodes[sel_field]->" "calcof.lengthto.fields = init_lengthto_fields_list(%d);\n", (unsigned long)i,(unsigned long)i, (unsigned long)i,sdef->elements[i].raw.lengthto_num, (unsigned long)i,sdef->elements[i].raw.unit, + (unsigned long)i,sdef->elements[i].raw.lengthto_offset, (unsigned long)i,sdef->elements[i].raw.lengthto_num); for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) { if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { @@ -1188,6 +1197,7 @@ char *generate_raw_coding_negtest(char *src, const struct_def *sdef, " myleaf.body.node.nodes[idx_map[%lu]]->coding_descr = &%s_descr_;\n" " myleaf.body.node.nodes[idx_map[%lu]]->calcof.lengthto.num_of_fields = %d;\n" " myleaf.body.node.nodes[idx_map[%lu]]->calcof.lengthto.unit = %d;\n" + " myleaf.body.node.nodes[idx_map[%lu]]->calcof.lengthto.offset = %d;\n" " myleaf.body.node.nodes[idx_map[%lu]]->calcof.lengthto.fields = " "init_lengthto_fields_list(%d);\n" " myleaf.body.node.nodes[idx_map[%lu]]->length = %d;\n", @@ -1195,6 +1205,7 @@ char *generate_raw_coding_negtest(char *src, const struct_def *sdef, (unsigned long)i, sdef->elements[i].typedescrname, (unsigned long)i, sdef->elements[i].raw.lengthto_num, (unsigned long)i, sdef->elements[i].raw.unit, + (unsigned long)i, sdef->elements[i].raw.lengthto_offset, (unsigned long)i, sdef->elements[i].raw.lengthto_num, (unsigned long)i, sdef->elements[i].raw.fieldlength); for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) { @@ -1350,6 +1361,8 @@ char *generate_raw_coding_negtest(char *src, const struct_def *sdef, " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]->" "calcof.lengthto.unit = %d;\n" " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]->" + "calcof.lengthto.offset = %d;\n" + " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[%d]->" "calcof.lengthto.fields = init_lengthto_fields_list(%d);\n", (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, @@ -1359,6 +1372,8 @@ char *generate_raw_coding_negtest(char *src, const struct_def *sdef, (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, sdef->elements[i].raw.unit, (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, + sdef->elements[i].raw.lengthto_offset, + (unsigned long)i, sdef->elements[i].raw.lengthindex->nthfield, sdef->elements[i].raw.lengthto_num); for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) { if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { @@ -1438,10 +1453,13 @@ char *generate_raw_coding_negtest(char *src, const struct_def *sdef, " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field]->" "calcof.lengthto.unit = %d;\n" " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field]->" + "calcof.lengthto.offset = %d;\n" + " myleaf.body.node.nodes[idx_map[%lu]]->body.node.nodes[sel_field]->" "calcof.lengthto.fields = init_lengthto_fields_list(%d);\n", (unsigned long)i, (unsigned long)i, (unsigned long)i, sdef->elements[i].raw.lengthto_num, (unsigned long)i, sdef->elements[i].raw.unit, + (unsigned long)i, sdef->elements[i].raw.lengthto_offset, (unsigned long)i, sdef->elements[i].raw.lengthto_num); for (a = 0; a < sdef->elements[i].raw.lengthto_num; a++) { if (sdef->elements[sdef->elements[i].raw.lengthto[a]].isOptional) { @@ -4883,6 +4901,16 @@ static char *genRawDecodeRecordField(char *src, const struct_def *sdef, ,sdef->elements[i].raw.lengthindex->nthfieldname ); } + if (sdef->elements[i].raw.lengthto_offset != 0) { + src = mputprintf(src, " field_%s%s.%s%s() = field_%s%s.%s%s() - %d;\n", + sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "", + sdef->elements[i].raw.lengthindex->nthfieldname, + sdef->elements[i].raw.lengthindex->fieldtype == OPTIONAL_FIELD ? "()" : "", + sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "", + sdef->elements[i].raw.lengthindex->nthfieldname, + sdef->elements[i].raw.lengthindex->fieldtype == OPTIONAL_FIELD ? "()" : "", + sdef->elements[i].raw.lengthto_offset); + } src=mputprintf(src, " value_of_length_field%d+=field_%s%s.%s%s().get_long_long_val()*%d;\n" ,i,sdef->elements[i].name,sdef->elements[i].isOptional?"()":"" @@ -4901,12 +4929,20 @@ static char *genRawDecodeRecordField(char *src, const struct_def *sdef, src = mputprintf(src, " switch (field_%s%s.get_selection()) {\n", sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : ""); for (m = 1; m < sdef->elements[i].raw.union_member_num + 1; m++) { - src = mputprintf(src, " case %s%s%s:\n" + src = mputprintf(src, " case %s%s%s:\n", sdef->elements[i].raw.member_name[0], + "::ALT_", sdef->elements[i].raw.member_name[m]); + if (sdef->elements[i].raw.lengthto_offset != 0) { + src = mputprintf(src, " field_%s%s.%s() = field_%s%s.%s() - %d;\n", + sdef->elements[i].name, + sdef->elements[i].isOptional ? "()" : "", + sdef->elements[i].raw.member_name[m], sdef->elements[i].name, + sdef->elements[i].isOptional ? "()" : "", + sdef->elements[i].raw.member_name[m], sdef->elements[i].raw.lengthto_offset); + } + src = mputprintf(src, " value_of_length_field%d += field_%s%s.%s().get_long_long_val() * %d;\n" - " break;\n", sdef->elements[i].raw.member_name[0], - "::ALT_", - sdef->elements[i].raw.member_name[m], i, sdef->elements[i].name, - sdef->elements[i].isOptional ? "()" : "", + " break;\n", i, sdef->elements[i].name, + sdef->elements[i].isOptional ? "()" : "", sdef->elements[i].raw.member_name[m], sdef->elements[i].raw.unit == -1 ? 1 : sdef->elements[i].raw.unit); } @@ -4915,6 +4951,12 @@ static char *genRawDecodeRecordField(char *src, const struct_def *sdef, " }\n", i); } else{ + if (sdef->elements[i].raw.lengthto_offset != 0) { + src = mputprintf(src, " field_%s%s = field_%s%s - %d;\n", + sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "", + sdef->elements[i].name, sdef->elements[i].isOptional ? "()" : "", + sdef->elements[i].raw.lengthto_offset); + } src=mputprintf(src, " value_of_length_field%d+=field_%s%s.get_long_long_val()*%d;\n" ,i,sdef->elements[i].name,sdef->elements[i].isOptional?"()":"" diff --git a/compiler2/ttcn3/RawAST.cc b/compiler2/ttcn3/RawAST.cc index 7cff2f2746b23f5e89e32accd606378fadd22697..001981d0b0c21c94cdd5901d2c7ea1494eea0be6 100644 --- a/compiler2/ttcn3/RawAST.cc +++ b/compiler2/ttcn3/RawAST.cc @@ -49,6 +49,7 @@ RawAST::RawAST(RawAST *other, int default_length){ ext_bit_groups=NULL; lengthto_num=0; lengthto=NULL; + lengthto_offset = 0; pointerto=NULL; ptrbase=NULL; ptroffset=other->ptroffset; @@ -90,6 +91,7 @@ void RawAST::init_rawast(int default_length){ fieldorder=XDEFDEFAULT; lengthto_num=0; lengthto=NULL; + lengthto_offset = 0; pointerto=NULL; ptrbase=NULL; ptroffset=0; @@ -218,6 +220,7 @@ void copy_rawAST_to_struct(RawAST *from, raw_attrib_struct *to){ if (from->lengthto_num > 0) to->lengthto = static_cast<int*>( Malloc(from->lengthto_num * sizeof(int)) ); else to->lengthto = NULL; + to->lengthto_offset = from->lengthto_offset; to->pointerto=-1; to->ptroffset=from->ptroffset; to->unit=from->unit; diff --git a/compiler2/ttcn3/RawAST.hh b/compiler2/ttcn3/RawAST.hh index b2b938472c6d4a08859e4376eb523c4aa420b4db..99c3421ebbfd0feafc4adbdb9f0351eeb4c2bca9 100644 --- a/compiler2/ttcn3/RawAST.hh +++ b/compiler2/ttcn3/RawAST.hh @@ -97,6 +97,7 @@ public: int fieldorder; /**< XDEFMSB, XDEFLSB */ int lengthto_num; Common::Identifier **lengthto; /**< list of fields to generate length for */ + int lengthto_offset; Common::Identifier *pointerto; /**< pointer to the specified field is contained in this field */ int ptroffset; /**< offset to the pointer value in bits diff --git a/compiler2/ttcn3/rawAST.y b/compiler2/ttcn3/rawAST.y index d93437b56d5a22f6b9015096691b961036aa0fc0..252b650454cddde2e3db789a7d0a002e8df9075c 100644 --- a/compiler2/ttcn3/rawAST.y +++ b/compiler2/ttcn3/rawAST.y @@ -568,7 +568,13 @@ XExtensionBitGroupDef: XExtensionBitGroupKeyword '(' XYesOrNoOrReverse ',' /* LengthTo */ XLengthToDef : XLengthToKeyword '(' XRecordFieldRefList ')' - { }; + { } +| XLengthToKeyword '(' XRecordFieldRefList ')' '+' XNumber +{ rawstruct->lengthto_offset = $6; } + +| XLengthToKeyword '(' XRecordFieldRefList ')' '-' XNumber +{ rawstruct->lengthto_offset = -$6; } +; /* PointerTo */ XPointerToDef : XPointerToKeyword '(' XRecordFieldRef ')' diff --git a/compiler2/ttcn3/rawASTspec.h b/compiler2/ttcn3/rawASTspec.h index 8029fcb8a5f34a9b7c8e3e3a18a7b762caf07faa..73fdbaa4941f38ebb72013c6f744a01ab6ac3d62 100644 --- a/compiler2/ttcn3/rawASTspec.h +++ b/compiler2/ttcn3/rawASTspec.h @@ -91,6 +91,7 @@ typedef struct{ int fieldorder; /* XDEFMSB, XDEFLSB */ int lengthto_num; int *lengthto; /* list of fields to generate length for */ + int lengthto_offset; int pointerto; /* pointer to the specified field is contained in this field */ int ptrunit; /* number of bits in pointerto value */ diff --git a/core/RAW.cc b/core/RAW.cc index eb489c26b3b6f47416a5436e8f6f17938d2a56b9..7c1974814c617b4bd6bc953cd5fa05a2e4bb30ca 100644 --- a/core/RAW.cc +++ b/core/RAW.cc @@ -180,6 +180,7 @@ void RAW_enc_tree::calc_fields() atm = get_node(calcof.lengthto.fields[0]); if (atm) szumm = atm->body.node.num_of_nodes; } + szumm += calcof.lengthto.offset; INTEGER temp(szumm); temp.RAW_encode(*coding_descr, *this); break; } diff --git a/core/RAW.hh b/core/RAW.hh index e80c254c169fb822553baca24fe4b5bc089714e7..410566776e8bb465ec9c55b9ef1943dccded4061 100644 --- a/core/RAW.hh +++ b/core/RAW.hh @@ -87,6 +87,7 @@ struct RAW_enc_lengthto{ int num_of_fields; RAW_enc_tr_pos* fields; int unit; + int offset; }; struct RAW_coding_par{ diff --git a/regression_test/RAW/Lengthto_Offset/.gitignore b/regression_test/RAW/Lengthto_Offset/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..3b9a476f0225b5e2017cee7c49901daac623d4ee --- /dev/null +++ b/regression_test/RAW/Lengthto_Offset/.gitignore @@ -0,0 +1,6 @@ +Lengthto_Offset +Lengthto_Offset.exe +Lengthto_Offset*.cc +Lengthto_Offset*.hh +Lengthto_Offset*.log +compile diff --git a/regression_test/RAW/Lengthto_Offset/Lengthto_Offset.cfg b/regression_test/RAW/Lengthto_Offset/Lengthto_Offset.cfg new file mode 100644 index 0000000000000000000000000000000000000000..d0d3be25959ae1f3fcbfa7737edb6f57197d9e6d --- /dev/null +++ b/regression_test/RAW/Lengthto_Offset/Lengthto_Offset.cfg @@ -0,0 +1,18 @@ +############################################################################### +# Copyright (c) 2000-2017 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: +# Baranyi, Botond +# +############################################################################### +[LOGGING] +LogFile := "Lengthto_Offset.log" +FileMask := LOG_ALL +ConsoleMask := TTCN_ERROR | TTCN_TESTCASE | TTCN_STATISTICS +LogSourceInfo := Yes +[EXECUTE] +Lengthto_Offset.control diff --git a/regression_test/RAW/Lengthto_Offset/Lengthto_Offset.ttcn b/regression_test/RAW/Lengthto_Offset/Lengthto_Offset.ttcn new file mode 100644 index 0000000000000000000000000000000000000000..079a7aa579e2163915f3750eb0beb674a800be09 --- /dev/null +++ b/regression_test/RAW/Lengthto_Offset/Lengthto_Offset.ttcn @@ -0,0 +1,114 @@ +/****************************************************************************** + * Copyright (c) 2000-2017 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: + * Baranyi, Botond – initial implementation + * + ******************************************************************************/ + +module Lengthto_Offset { + +type component CT {} + +type record Rec1 { + integer len, + octetstring data +} +with { + variant (len) "LENGTHTO(data) + 1"; +} + +testcase tc1() runs on CT { + var Rec1 val := { 0, '12345678'O }; + var bitstring enc_exp := oct2bit('0512345678'O); + var bitstring enc := encvalue(val); + if (enc_exp != enc) { + setverdict(fail, "Encoding failed. Expected: ", bit2oct(enc_exp), ", got: ", bit2oct(enc)); + } + + var Rec1 dec_exp := { lengthof(val.data), val.data }; + var Rec1 dec; + var integer res := decvalue(enc_exp, dec); + if (res != 0) { + setverdict(fail, "Invalid decoding result: ", res); + } + else if (dec_exp != dec) { + setverdict(fail, "Decoding failed. Expected: ", dec_exp, ", got: ", dec); + } + setverdict(pass); +} + +type record Rec2 { + integer len, + bitstring data1, + octetstring data2 +} +with { + variant (len) "LENGTHTO(data1, data2) - 2"; + variant (data1) "FIELDLENGTH(8)"; +} + +testcase tc2() runs on CT { + var Rec2 val := { 0, '10010101'B, '12345678'O }; + var bitstring enc_exp := oct2bit('039512345678'O); + var bitstring enc := encvalue(val); + if (enc_exp != enc) { + setverdict(fail, "Encoding failed. Expected: ", bit2oct(enc_exp), ", got: ", bit2oct(enc)); + } + + var Rec2 dec_exp := { lengthof(val.data1) / 8 + lengthof(val.data2), val.data1, val.data2 }; + var Rec2 dec; + var integer res := decvalue(enc_exp, dec); + if (res != 0) { + setverdict(fail, "Invalid decoding result: ", res); + } + else if (dec_exp != dec) { + setverdict(fail, "Decoding failed. Expected: ", dec_exp, ", got: ", dec); + } + setverdict(pass); +} + +type record Rec3 { + union { integer i1, integer i2 } len, + bitstring data1, + octetstring data2 +} +with { + variant (len) "LENGTHTO(data1, data2) + 10"; + variant (data1) "FIELDLENGTH(8)"; +} + +testcase tc3() runs on CT { + var Rec3 val := { { i1 := 0 }, '10010101'B, '12345678'O }; + var bitstring enc_exp := oct2bit('0F9512345678'O); + var bitstring enc := encvalue(val); + if (enc_exp != enc) { + setverdict(fail, "Encoding failed. Expected: ", bit2oct(enc_exp), ", got: ", bit2oct(enc)); + } + + var Rec3 dec_exp := { { i1 := lengthof(val.data1) / 8 + lengthof(val.data2) }, val.data1, val.data2 }; + var Rec3 dec; + var integer res := decvalue(enc_exp, dec); + if (res != 0) { + setverdict(fail, "Invalid decoding result: ", res); + } + else if (dec_exp != dec) { + setverdict(fail, "Decoding failed. Expected: ", dec_exp, ", got: ", dec); + } + setverdict(pass); +} + +control { + execute(tc1()); + execute(tc2()); + execute(tc3()); +} + +} +with { + encode "RAW"; +} diff --git a/regression_test/RAW/Lengthto_Offset/Makefile b/regression_test/RAW/Lengthto_Offset/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..f1f68d941c534144e7785f13cbbf11be783446e2 --- /dev/null +++ b/regression_test/RAW/Lengthto_Offset/Makefile @@ -0,0 +1,63 @@ +############################################################################## +# Copyright (c) 2000-2017 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: +# Baranyi, Botond +# +############################################################################## +TOPDIR := ../.. +include $(TOPDIR)/Makefile.regression + +.PHONY: all clean dep run + +TTCN3_LIB = ttcn3$(RT2_SUFFIX)$(DYNAMIC_SUFFIX) + +TTCN3_MODULES = Lengthto_Offset.ttcn + +GENERATED_SOURCES = $(TTCN3_MODULES:.ttcn=.cc) +GENERATED_HEADERS = $(GENERATED_SOURCES:.cc=.hh) +ifdef CODE_SPLIT +GENERATED_SOURCES := $(foreach file, $(GENERATED_SOURCES:.cc=), $(addprefix $(file), .cc _seq.cc _set.cc _seqof.cc _setof.cc _union.cc)) +else ifdef SPLIT_TO_SLICES +POSTFIXES := $(foreach file, $(SPLIT_TO_SLICES), $(addsuffix $(file), _part_)) +POSTFIXES := $(foreach file, $(POSTFIXES), $(addprefix $(file), .cc)) +GENERATED_SOURCES2 := $(foreach file, $(GENERATED_SOURCES:.cc=), $(addprefix $(file), $(POSTFIXES))) +GENERATED_SOURCES += $(GENERATED_SOURCES2) +endif + +USER_SOURCES = + +# All object files needed for the executable test suite: +OBJECTS = $(GENERATED_SOURCES:.cc=.o) $(USER_SOURCES:.cc=.o) + +# The name of the executable test suite: +TARGET = Lengthto_Offset$(EXESUFFIX) + +all: $(TARGET) ; + +$(TARGET): $(OBJECTS) + $(CXX) $(LDFLAGS) -o $@ $(OBJECTS) -L$(TTCN3_DIR)/lib -l$(TTCN3_LIB) \ + -L$(OPENSSL_DIR)/lib -lcrypto $($(PLATFORM)_LIBS) + +$(GENERATED_SOURCES) $(GENERATED_HEADERS): compile + @if [ ! -f $@ ]; then $(RM) compile; $(MAKE) compile; fi + +compile: $(TTCN3_MODULES) $(ASN1_MODULES) + $(TTCN3_COMPILER) $(COMPILER_FLAGS) $^ + touch $@ + +clean distclean: + $(RM) $(TARGET) $(OBJECTS) $(GENERATED_HEADERS) \ + $(GENERATED_SOURCES) compile *.log + +dep: $(GENERATED_SOURCES) + makedepend $(CPPFLAGS) $(USER_SOURCES) $(GENERATED_SOURCES) + +run: $(TARGET) Lengthto_Offset.cfg + ./$^ + +# DO NOT DELETE diff --git a/regression_test/RAW/Makefile b/regression_test/RAW/Makefile index 626e9b73a9e89db62e63c4cf9ec6e259372bbe65..648c6c103bd221deb2c2b2d05304be9429dc6273 100644 --- a/regression_test/RAW/Makefile +++ b/regression_test/RAW/Makefile @@ -18,7 +18,7 @@ TOPDIR := .. include $(TOPDIR)/Makefile.regression -RDIRS = Examples HN25015 HQ26535 HQ49956 HS16977 ustr Annex_E_variants Bug521125 +RDIRS = Examples HN25015 HQ26535 HQ49956 HS16977 ustr Annex_E_variants Bug521125 Lengthto_Offset all dep clean run distclean: for dir in $(RDIRS); do (cd $$dir && $(MAKE) $@) || exit; done