]> xenbits.xensource.com Git - people/andrewcoop/hwloc.git/commitdiff
Add hwloc_obj_type_sscanf() to extend hwloc_obj_type_of_string()
authorBrice Goglin <Brice.Goglin@inria.fr>
Mon, 3 Feb 2014 19:21:59 +0000 (20:21 +0100)
committerBrice Goglin <Brice.Goglin@inria.fr>
Fri, 7 Feb 2014 12:59:33 +0000 (13:59 +0100)
The former was already used in hwloc-calc.h to parse things like
"L2iCache" or "Group3". Make it officially part of the API and
deprecate the old hwloc_obj_type_of_string().

12 files changed:
NEWS
doc/Makefile.am
include/hwloc.h
include/hwloc/deprecated.h
include/hwloc/rename.h
src/topology-xml.c
src/traversal.c
utils/hwloc-calc.c
utils/hwloc-calc.h
utils/hwloc-distrib.c
utils/hwloc-info.c
utils/lstopo.c

diff --git a/NEWS b/NEWS
index 2ff1fb54b9158712bbf8d6cb264aea0012a710aa..93ceb9af186eca3e56bf17f9a9a20f23123baae5 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -20,6 +20,9 @@ in v0.9.1).
 Version 1.9.0
 -------------
 * API
+  + Add hwloc_obj_type_sscanf() to extend hwloc_obj_type_of_string() with
+    type-specific attributes such as Cache/Group depth and Cache type.
+    hwloc_obj_type_of_string() is moved to hwloc/deprecated.h.
   + Add hwloc_linux_get_tid_last_cpu_location() for retrieving the
     last CPU where a Linux thread given by TID ran.
 * Backends
index 037d1722ab724212808aa88be42fb37a1da68c6a..b19de94eaa545e2d75e5479cf60edc67e8fa2872 100644 (file)
@@ -385,7 +385,7 @@ man3_object_stringsdir = $(man3dir)
 man3_object_strings_DATA = \
         $(DOX_MAN_DIR)/man3/hwlocality_object_strings.3 \
         $(DOX_MAN_DIR)/man3/hwloc_obj_type_string.3 \
-        $(DOX_MAN_DIR)/man3/hwloc_obj_type_of_string.3 \
+        $(DOX_MAN_DIR)/man3/hwloc_obj_type_sscanf.3 \
         $(DOX_MAN_DIR)/man3/hwloc_obj_type_snprintf.3 \
         $(DOX_MAN_DIR)/man3/hwloc_obj_attr_snprintf.3 \
         $(DOX_MAN_DIR)/man3/hwloc_obj_cpuset_snprintf.3 \
index 83bdbe4e98c8e19646c4ace031114fe6a1706f51..ca086ffd80860a38c6b9cf0b22d7c0569fe509c7 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright © 2009 CNRS
- * Copyright © 2009-2013 Inria.  All rights reserved.
+ * Copyright © 2009-2014 Inria.  All rights reserved.
  * Copyright © 2009-2012 Université Bordeaux 1
  * Copyright © 2009-2011 Cisco Systems, Inc.  All rights reserved.
  * See COPYING in top-level directory.
@@ -1173,11 +1173,36 @@ hwloc_get_next_obj_by_type (hwloc_topology_t topology, hwloc_obj_type_t type,
 /** \brief Return a stringified topology object type */
 HWLOC_DECLSPEC const char * hwloc_obj_type_string (hwloc_obj_type_t type) __hwloc_attribute_const;
 
-/** \brief Return an object type from the string
+/** \brief Return an object type and attributes from a type string.
  *
- * \return -1 if unrecognized.
+ * Convert strings such as "socket" or "cache" into the corresponding types.
+ * Matching is case-insensitive, and only the first letters are actually
+ * required to match.
+ *
+ * Types that have specific attributes, for instance caches and groups,
+ * may be returned in \p depthattrp and \p typeattrp. They are ignored
+ * when these pointers are \c NULL.
+ *
+ * For instance "L2i" or "L2iCache" would return
+ * type HWLOC_OBJ_CACHE in \p typep, 2 in \p depthattrp,
+ * and HWLOC_OBJ_CACHE_TYPE_INSTRUCTION in \p typeattrp
+ * (this last pointer should point to a hwloc_obj_cache_type_t).
+ * "Group3" would return type HWLOC_OBJ_GROUP type and 3 in \p depthattrp.
+ * Attributes that are not specified in the string (for instance "Group"
+ * without a depth, or "L2Cache" without a cache type) are set to -1.
+ *
+ * \p typeattrd is only filled if the size specified in \p typeattrsize
+ * is large enough. It is currently only used for caches, and the required
+ * size is at least the size of hwloc_obj_cache_type_t.
+ *
+ * \return 0 if a type was correctly identified, otherwise -1.
+ *
+ * \note This is an extended version of the now deprecated hwloc_obj_type_of_string()
  */
-HWLOC_DECLSPEC hwloc_obj_type_t hwloc_obj_type_of_string (const char * string) __hwloc_attribute_pure;
+HWLOC_DECLSPEC int hwloc_obj_type_sscanf(const char *string,
+                                        hwloc_obj_type_t *typep,
+                                        int *depthattrp,
+                                        void *typeattrp, size_t typeattrsize);
 
 /** \brief Stringify the type of a given topology object into a human-readable form.
  *
index 544ca8f0a4d5f12dc936a3b0f92b49c3cc499135..5b1f671fd118e9d45c567e0ed603ff0c3a08e2c5 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright © 2009 CNRS
- * Copyright © 2009-2013 Inria.  All rights reserved.
+ * Copyright © 2009-2014 Inria.  All rights reserved.
  * Copyright © 2009-2012 Université Bordeaux 1
  * Copyright © 2009-2010 Cisco Systems, Inc.  All rights reserved.
  * See COPYING in top-level directory.
 extern "C" {
 #endif
 
+/** \brief Return an object type from the string
+ *
+ * \return -1 if unrecognized.
+ */
+HWLOC_DECLSPEC hwloc_obj_type_t hwloc_obj_type_of_string (const char * string) __hwloc_attribute_pure;
+
 /** \brief Stringify a given topology object into a human-readable form.
  *
  * \note This function is deprecated in favor of hwloc_obj_type_snprintf()
index b7dd666b7e7ec8d4d26800aeaefe5a81b130b0ef..cdce0b24b81a09ba28aea2b354056b0de0828074 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright © 2009-2011 Cisco Systems, Inc.  All rights reserved.
- * Copyright © 2010-2013 Inria.  All rights reserved.
+ * Copyright © 2010-2014 Inria.  All rights reserved.
  * See COPYING in top-level directory.
  */
 
@@ -176,7 +176,7 @@ extern "C" {
 #define hwloc_get_obj_by_type HWLOC_NAME(get_obj_by_type )
 
 #define hwloc_obj_type_string HWLOC_NAME(obj_type_string )
-#define hwloc_obj_type_of_string HWLOC_NAME(obj_type_of_string )
+#define hwloc_obj_type_sscanf HWLOC_NAME(obj_type_sscanf)
 #define hwloc_obj_type_snprintf HWLOC_NAME(obj_type_snprintf )
 #define hwloc_obj_attr_snprintf HWLOC_NAME(obj_attr_snprintf )
 #define hwloc_obj_cpuset_snprintf HWLOC_NAME(obj_cpuset_snprintf)
@@ -493,6 +493,7 @@ extern "C" {
 
 /* hwloc/deprecated.h */
 
+#define hwloc_obj_type_of_string HWLOC_NAME(obj_type_of_string )
 #define hwloc_obj_snprintf HWLOC_NAME(obj_snprintf)
 
 /* private/debug.h */
index fd5d7e40cc5892d10e51dd51daf9e20de48ef8f5..cf1d3a1a6cdc0a9f295bb85dad763637df9af188 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright © 2009 CNRS
- * Copyright © 2009-2013 Inria.  All rights reserved.
+ * Copyright © 2009-2014 Inria.  All rights reserved.
  * Copyright © 2009-2011 Université Bordeaux 1
  * Copyright © 2009-2011 Cisco Systems, Inc.  All rights reserved.
  * See COPYING in top-level directory.
@@ -559,8 +559,7 @@ hwloc__xml_import_object(hwloc_topology_t topology,
     if (state->next_attr(state, &attrname, &attrvalue) < 0)
       break;
     if (!strcmp(attrname, "type")) {
-      obj->type = hwloc_obj_type_of_string(attrvalue);
-      if (obj->type == (hwloc_obj_type_t)-1)
+      if (hwloc_obj_type_sscanf(attrvalue, &obj->type, NULL, NULL, 0) < 0)
         return -1;
     } else {
       /* type needed first */
index 6e678342e2a575028ea4b3665b74f75838b76f43..91b0c22658f80405f44eca2779e44ed897576897 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright © 2009 CNRS
- * Copyright © 2009-2012 inria.  All rights reserved.
+ * Copyright © 2009-2014 Inria.  All rights reserved.
  * Copyright © 2009-2010 Université Bordeaux 1
  * Copyright © 2009-2011 Cisco Systems, Inc.  All rights reserved.
  * See COPYING in top-level directory.
@@ -213,6 +213,74 @@ hwloc_obj_type_of_string (const char * string)
   return (hwloc_obj_type_t) -1;
 }
 
+int
+hwloc_obj_type_sscanf(const char *string, hwloc_obj_type_t *typep, int *depthattrp, void *typeattrp, size_t typeattrsize)
+{
+  hwloc_obj_type_t type = (hwloc_obj_type_t) -1;
+  int depthattr = -1;
+  hwloc_obj_cache_type_t cachetypeattr = (hwloc_obj_cache_type_t) -1; /* unspecified */
+  char *end;
+
+  /* types without depthattr */
+  if (!hwloc_strncasecmp(string, "system", 2)) {
+    type = HWLOC_OBJ_SYSTEM;
+  } else if (!hwloc_strncasecmp(string, "machine", 2)) {
+    type = HWLOC_OBJ_MACHINE;
+  } else if (!hwloc_strncasecmp(string, "node", 1)
+            || !hwloc_strncasecmp(string, "numa", 1)) { /* matches node and numanode */
+    type = HWLOC_OBJ_NODE;
+  } else if (!hwloc_strncasecmp(string, "socket", 2)) {
+    type = HWLOC_OBJ_SOCKET;
+  } else if (!hwloc_strncasecmp(string, "core", 2)) {
+    type = HWLOC_OBJ_CORE;
+  } else if (!hwloc_strncasecmp(string, "pu", 2)) {
+    type = HWLOC_OBJ_PU;
+  } else if (!hwloc_strncasecmp(string, "misc", 2)) {
+    type = HWLOC_OBJ_MISC;
+  } else if (!hwloc_strncasecmp(string, "bridge", 2)) {
+    type = HWLOC_OBJ_BRIDGE;
+  } else if (!hwloc_strncasecmp(string, "pci", 2)) {
+    type = HWLOC_OBJ_PCI_DEVICE;
+  } else if (!hwloc_strncasecmp(string, "os", 2)) {
+    type = HWLOC_OBJ_OS_DEVICE;
+
+  /* types with depthattr */
+  } else if (!hwloc_strncasecmp(string, "cache", 2)) {
+    type = HWLOC_OBJ_CACHE;
+
+  } else if ((string[0] == 'l' || string[0] == 'L') && string[1] >= '0' && string[1] <= '9') {
+    type = HWLOC_OBJ_CACHE;
+    depthattr = strtol(string+1, &end, 10);
+    if (*end == 'd') {
+      cachetypeattr = HWLOC_OBJ_CACHE_DATA;
+    } else if (*end == 'i') {
+      cachetypeattr = HWLOC_OBJ_CACHE_INSTRUCTION;
+    } else if (*end == 'u') {
+      cachetypeattr = HWLOC_OBJ_CACHE_UNIFIED;
+    }
+
+  } else if (!hwloc_strncasecmp(string, "group", 2)) {
+    int length;
+    type = HWLOC_OBJ_GROUP;
+    length = strcspn(string, "0123456789");
+    if (length <= 5 && !hwloc_strncasecmp(string, "group", length)
+       && string[length] >= '0' && string[length] <= '9') {
+      depthattr = strtol(string+length, &end, 10);
+    }
+  } else
+    return -1;
+
+  *typep = type;
+  if (depthattrp)
+    *depthattrp = depthattr;
+  if (typeattrp) {
+    if (type == HWLOC_OBJ_CACHE && sizeof(hwloc_obj_cache_type_t) <= typeattrsize)
+      memcpy(typeattrp, &cachetypeattr, sizeof(hwloc_obj_cache_type_t));
+  }
+
+  return 0;
+}
+
 static const char *
 hwloc_pci_class_string(unsigned short class_id)
 {
index 0d91a27a0c2fb489304d6f1afc8e1712af44f550..bcd4b9b9ae2b6d4b4b6925159c85678836632070 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright © 2009 CNRS
- * Copyright © 2009-2013 Inria.  All rights reserved.
+ * Copyright © 2009-2014 Inria.  All rights reserved.
  * Copyright © 2009-2011 Université Bordeaux 1
  * Copyright © 2009-2010 Cisco Systems, Inc.  All rights reserved.
  * See COPYING in top-level directory.
@@ -161,9 +161,9 @@ hwloc_calc_output(hwloc_topology_t topology, const char *sep, hwloc_bitmap_t set
 
 static int hwloc_calc_type_depth(const char *string, hwloc_obj_type_t *typep, int *depthp)
 {
-  hwloc_obj_type_t type = hwloc_obj_type_of_string(string);
+  hwloc_obj_type_t type = (hwloc_obj_type_t) -1; /* in case we match a depth */
   int depth = -1;
-  if (type == (hwloc_obj_type_t) -1) {
+  if (hwloc_obj_type_sscanf(string, &type, NULL, NULL, 0) < 0) {
     char *endptr;
     depth = strtoul(string, &endptr, 0);
     if (*endptr)
index 5a1dfc540b397b5c8bfc7c63e15fa2ac8e755333..a1e7d36e13caf328d9f0a40434161a32f64b14e6 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright © 2009 CNRS
- * Copyright © 2009-2013 Inria.  All rights reserved.
+ * Copyright © 2009-2014 Inria.  All rights reserved.
  * Copyright © 2009-2012 Université Bordeaux 1
  * Copyright © 2011 Cisco Systems, Inc.  All rights reserved.
  * See COPYING in top-level directory.
@@ -85,79 +85,6 @@ hwloc_calc_get_obj_inside_cpuset_by_depth(hwloc_topology_t topology, hwloc_const
   }
 }
 
-/* extended version of hwloc_obj_type_of_string()
- *
- * matches L2, L3Cache and Group4, and return the corresponding depth attribute if depthattrp isn't NULL.
- * only looks at the beginning of the string to allow truncated type names.
- */
-static __hwloc_inline int
-hwloc_obj_type_sscanf(const char *string, hwloc_obj_type_t *typep, int *depthattrp, hwloc_obj_cache_type_t *cachetypeattrp)
-{
-  hwloc_obj_type_t type = (hwloc_obj_type_t) -1;
-  int depthattr = -1;
-  hwloc_obj_cache_type_t cachetypeattr = (hwloc_obj_cache_type_t) -1; /* unspecified */
-  char *end;
-
-  /* types without depthattr */
-  if (!hwloc_strncasecmp(string, "system", 2)) {
-    type = HWLOC_OBJ_SYSTEM;
-  } else if (!hwloc_strncasecmp(string, "machine", 2)) {
-    type = HWLOC_OBJ_MACHINE;
-  } else if (!hwloc_strncasecmp(string, "node", 1)) {
-    type = HWLOC_OBJ_NODE;
-  } else if (!hwloc_strncasecmp(string, "socket", 2)) {
-    type = HWLOC_OBJ_SOCKET;
-  } else if (!hwloc_strncasecmp(string, "core", 2)) {
-    type = HWLOC_OBJ_CORE;
-  } else if (!hwloc_strncasecmp(string, "pu", 2)) {
-    type = HWLOC_OBJ_PU;
-  } else if (!hwloc_strncasecmp(string, "misc", 2)) {
-    type = HWLOC_OBJ_MISC;
-  } else if (!hwloc_strncasecmp(string, "pci", 2)) {
-    type = HWLOC_OBJ_PCI_DEVICE;
-  } else if (!hwloc_strncasecmp(string, "os", 2)) {
-    type = HWLOC_OBJ_OS_DEVICE;
-
-  /* types with depthattr */
-  } else if (!hwloc_strncasecmp(string, "cache", 2)) {
-    type = HWLOC_OBJ_CACHE;
-  } else if ((string[0] == 'l' || string[0] == 'L') && string[1] >= '0' && string[1] <= '9') {
-    type = HWLOC_OBJ_CACHE;
-    depthattr = strtol(string+1, &end, 10);
-    if (*end == 'd') {
-      cachetypeattr = HWLOC_OBJ_CACHE_DATA;
-      end++;
-    } else if (*end == 'i') {
-      cachetypeattr = HWLOC_OBJ_CACHE_INSTRUCTION;
-      end++;
-    } else if (*end == 'u') {
-      cachetypeattr = HWLOC_OBJ_CACHE_UNIFIED;
-      end++;
-    }
-    if (*end && hwloc_strncasecmp(end, "cache", 2))
-      return -1;
-
-  } else if (!hwloc_strncasecmp(string, "group", 1)) {
-    int length;
-    type = HWLOC_OBJ_GROUP;
-    length = strcspn(string, "0123456789");
-    if (string[length] != '\0') {
-      depthattr = strtol(string+length, &end, 10);
-      if (*end)
-       return -1;
-    }
-  } else
-    return -1;
-
-  *typep = type;
-  if (depthattrp)
-    *depthattrp = depthattr;
-  if (cachetypeattrp)
-    *cachetypeattrp = cachetypeattr;
-
-  return 0;
-}
-
 static __hwloc_inline int
 hwloc_calc_depth_of_type(hwloc_topology_t topology, hwloc_obj_type_t type,
                         int depthattr, hwloc_obj_cache_type_t cachetype /* -1 if not specified */,
@@ -242,7 +169,7 @@ hwloc_calc_parse_depth_prefix(hwloc_topology_t topology, unsigned topodepth,
   typestring[typelen] = '\0';
 
   /* try to match a type name */
-  err = hwloc_obj_type_sscanf(typestring, &type, &depthattr, &cachetypeattr);
+  err = hwloc_obj_type_sscanf(typestring, &type, &depthattr, &cachetypeattr, sizeof(cachetypeattr));
   if (!err) {
     *typep = type;
     return hwloc_calc_depth_of_type(topology, type, depthattr, cachetypeattr, verbose);
index b04c15beb5d26b64f9995c3c2b56089d3fd40468..a1145a15097cb5690f1ccd26d86d5169fa7f080d 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright © 2009 CNRS
- * Copyright © 2009-2013 Inria.  All rights reserved.
+ * Copyright © 2009-2014 Inria.  All rights reserved.
  * Copyright © 2009-2010 Université Bordeaux 1
  * Copyright © 2009-2011 Cisco Systems, Inc.  All rights reserved.
  * See COPYING in top-level directory.
@@ -103,11 +103,10 @@ int main(int argc, char *argv[])
          usage(callname, stdout);
          exit(EXIT_FAILURE);
        }
-       type = hwloc_obj_type_of_string(argv[1]);
-       if (type != (hwloc_obj_type_t) -1)
-         hwloc_topology_ignore_type(topology, type);
-       else
+       if (hwloc_obj_type_sscanf(argv[1], &type, NULL, NULL, 0) < 0)
          fprintf(stderr, "Unsupported type `%s' passed to --ignore, ignoring.\n", argv[1]);
+       else
+         hwloc_topology_ignore_type(topology, type);
        argc--;
        argv++;
        goto next;
@@ -117,8 +116,7 @@ int main(int argc, char *argv[])
          usage(callname, stdout);
          exit(EXIT_FAILURE);
        }
-       from_type = hwloc_obj_type_of_string(argv[1]);
-       if (from_type == (hwloc_obj_type_t) -1)
+       if (hwloc_obj_type_sscanf(argv[1], &from_type, NULL, NULL, 0) < 0)
          fprintf(stderr, "Unsupported type `%s' passed to --from, ignoring.\n", argv[1]);
        argc--;
        argv++;
@@ -129,8 +127,7 @@ int main(int argc, char *argv[])
          usage(callname, stdout);
          exit(EXIT_FAILURE);
        }
-       to_type = hwloc_obj_type_of_string(argv[1]);
-       if (to_type == (hwloc_obj_type_t) -1)
+       if (hwloc_obj_type_sscanf(argv[1], &to_type, NULL, NULL, 0) < 0)
          fprintf(stderr, "Unsupported type `%s' passed to --to, ignoring.\n", argv[1]);
        argc--;
        argv++;
@@ -141,7 +138,9 @@ int main(int argc, char *argv[])
          usage(callname, stdout);
          exit(EXIT_FAILURE);
        }
-       from_type = to_type = hwloc_obj_type_of_string(argv[1]);
+       if (hwloc_obj_type_sscanf(argv[1], &to_type, NULL, NULL, 0) < 0)
+         fprintf(stderr, "Unsupported type `%s' passed to --at, ignoring.\n", argv[1]);
+       from_type = to_type;
        argc--;
        argv++;
        goto next;
index 96e225a7ac2551bb679a4688deb4684dc1d34114..1d422395c85635c66bb0a8b82fd1784a77fd8165 100644 (file)
@@ -303,7 +303,7 @@ main (int argc, char *argv[])
          usage (callname, stderr);
          exit(EXIT_FAILURE);
        }
-       err = hwloc_obj_type_sscanf(argv[1], &show_ancestor_type, &show_ancestor_attrdepth, &show_ancestor_attrcachetype);
+       err = hwloc_obj_type_sscanf(argv[1], &show_ancestor_type, &show_ancestor_attrdepth, &show_ancestor_attrcachetype, sizeof(show_ancestor_attrcachetype));
         if (err < 0) {
           fprintf(stderr, "unrecognized --ancestor type %s\n", argv[1]);
           usage(callname, stderr);
index 7956289db7b0102e24f7566d8666c26c9de65ec5..d9d146d8cc78d5419b4decf3e43d058f6e2b43a7 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright © 2009 CNRS
- * Copyright © 2009-2013 Inria.  All rights reserved.
+ * Copyright © 2009-2014 Inria.  All rights reserved.
  * Copyright © 2009-2012 Université Bordeaux 1
  * Copyright © 2009-2011 Cisco Systems, Inc.  All rights reserved.
  * See COPYING in top-level directory.
@@ -405,8 +405,7 @@ main (int argc, char *argv[])
          usage (callname, stderr);
          exit(EXIT_FAILURE);
        }
-        lstopo_show_only = hwloc_obj_type_of_string(argv[1]);
-       if (lstopo_show_only == (hwloc_obj_type_t) -1)
+        if (hwloc_obj_type_sscanf(argv[1], &lstopo_show_only, NULL, NULL, 0) < 0)
          fprintf(stderr, "Unsupported type `%s' passed to --only, ignoring.\n", argv[1]);
        opt = 1;
       }
@@ -416,8 +415,7 @@ main (int argc, char *argv[])
          usage (callname, stderr);
          exit(EXIT_FAILURE);
        }
-       type = hwloc_obj_type_of_string(argv[1]);
-       if (type == (hwloc_obj_type_t) -1)
+       if (hwloc_obj_type_sscanf(argv[1], &type, NULL, NULL, 0) < 0)
          fprintf(stderr, "Unsupported type `%s' passed to --ignore, ignoring.\n", argv[1]);
        else if (type == HWLOC_OBJ_PU)
          lstopo_ignore_pus = 1;
@@ -467,11 +465,10 @@ main (int argc, char *argv[])
          hwloc_obj_type_t type;
          if (end)
            *end = '\0';
-         type = hwloc_obj_type_of_string(tmp);
-         if (type != (hwloc_obj_type_t) -1)
-           force_orient[type] = orient;
-         else
+         if (hwloc_obj_type_sscanf(tmp, &type, NULL, NULL, 0) < 0)
            fprintf(stderr, "Unsupported type `%s' passed to %s, ignoring.\n", tmp, argv[0]);
+         else
+           force_orient[type] = orient;
          if (!end)
            break;
          tmp = end+1;