+static cmd_tbl_t *get_cmd_tbl_parent(cmd_tbl_t *child)
+{
+ if ((child->flags & CTBL_SUBCMDAUTO) == 0) {
+
+ cmd_tbl_t *tbl_start = get_cmd_tbl_base(child);
+ if (tbl_start != cmd_tbl) {
+ cmd_tbl_t *top = cmd_tbl;
+ while (top->subcmd != tbl_start)
+ ++top;
+ return top;
+ }
+ }
+ return NULL;
+}
+
+static int print_nameprefix(cmd_tbl_t *p)
+{
+ cmd_tbl_t *top = get_cmd_tbl_parent(p);
+
+ int width = 0;
+ if (top) {
+ width = printf_P(PSTR("%S "), top->name);
+ }
+
+ return width;
+}
+
+static int print_prefixed_name(cmd_tbl_t *p)
+{
+ int len;
+
+ len = print_nameprefix(p);
+ len += strlen_P(p->name);
+ my_puts_P(p->name);
+
+ return len;
+}
+
+static void print_usage_line(cmd_tbl_t *p, int width)
+{
+ width -= print_prefixed_name(p);
+ if (width < 0)
+ width = 0;
+ print_blanks(width);
+ my_puts_P(PSTR(" - "));
+ puts_P(p->usage);
+}
+
+#if 0
+static int strcmp_PP(const FLASH char *s1, const FLASH char *s2)
+{
+ unsigned char c1, c2;
+
+ while ((c1 = *(const FLASH unsigned char *)s1++)
+ == (c2 = *(const FLASH unsigned char *)s2++))
+ if (c1 == 0)
+ return 0;
+
+ return c1 - c2;
+}
+#endif
+
+#if 1
+static int cmpstring_PP(const void *p1, const void *p2)
+{
+ char s1[21] = {'\0'};
+ char s2[21] = {'\0'};
+ cmd_tbl_t *cp1 = *(cmd_tbl_t **) p1;
+ cmd_tbl_t *cp2 = *(cmd_tbl_t **) p2;
+ cmd_tbl_t *top1 = get_cmd_tbl_parent(*(cmd_tbl_t **) p1);
+ cmd_tbl_t *top2 = get_cmd_tbl_parent(*(cmd_tbl_t **) p2);
+
+ if (top1)
+ strlcpy_P(s1, top1->name, 21);
+ if (top2)
+ strlcpy_P(s2, top2->name, 21);
+
+ strlcat_P(s1, cp1->name, 21);
+ strlcat_P(s2, cp2->name, 21);
+
+ return strcmp(s1, s2);
+}
+#else
+static int cmpstring_PP(const void *p1, const void *p2)
+{
+ cmd_tbl_t *cp1 = *(cmd_tbl_t **) p1;
+ cmd_tbl_t *cp2 = *(cmd_tbl_t **) p2;
+ cmd_tbl_t *top1 = get_cmd_tbl_parent(*(cmd_tbl_t **) p1);
+ cmd_tbl_t *top2 = get_cmd_tbl_parent(*(cmd_tbl_t **) p2);
+ int res;
+
+ if (top1 && top2) {
+ res = strcmp_PP(top1->name, top2->name);
+ if (res == 0)
+ res = strcmp_PP(cp1->name, cp2->name);
+ return res;
+ }
+ if (top1) {
+ res = strcmp_PP(top1->name, cp2->name);
+ if (res == 0)
+ res = strcmp_PP(cp1->name, cp2->name);
+ return res;
+ }
+ if (top2) {
+ res = strcmp_PP(cp1->name, top2->name);
+ if (res == 0)
+ res = strcmp_PP(cp1->name, cp2->name);
+ return res;
+ }
+ return strcmp_PP(cp1->name, cp2->name);
+}
+#endif
+
+/****************************************************************************/
+