diff options
| author | Rob Landley <rob@landley.net> | 2014-01-29 23:47:53 -0600 | 
|---|---|---|
| committer | Rob Landley <rob@landley.net> | 2014-01-29 23:47:53 -0600 | 
| commit | 0432050a75f615a6e68d6bc60bba2fb939fbb586 (patch) | |
| tree | 04a316b4c6eaed943894015cbaa53622d4637e17 /scripts | |
| parent | c8cce3f302ce47db42e65ab2078f7ca9027af968 (diff) | |
| download | toybox-0432050a75f615a6e68d6bc60bba2fb939fbb586.tar.gz | |
More elaborate help text collating logic.
Diffstat (limited to 'scripts')
| -rw-r--r-- | scripts/config2help.c | 179 | 
1 files changed, 150 insertions, 29 deletions
diff --git a/scripts/config2help.c b/scripts/config2help.c index 30e7bbab..4b6c9dec 100644 --- a/scripts/config2help.c +++ b/scripts/config2help.c @@ -41,17 +41,84 @@ char *dlist_zap(struct double_list **help)    char *s = dd->data;    free(dd); +      return s;  } -void zap_blank_lines(struct double_list **help) +int zap_blank_lines(struct double_list **help)  { -  for(;;) { -    char *s = trim((*help)->data);; +  int got = 0; + +  while (*help) { +    char *s; + +    s = trim((*help)->data);      if (*s) break; +    got++;      free(dlist_zap(help));    } + +  return got; +} + +// Collect "-a blah" description lines following a blank line (or start). +// Returns array of removed lines with *len entries (0 for none). + +// Moves *help to new start of text (in case dash lines were at beginning). +// Sets *from to where dash lines removed from (in case they weren't). +// Discards blank lines before and after dashlines. + +// If no prefix, *help NULL. If no postfix, *from == *help +// if no dashlines returned *from == *help. + +char **grab_dashlines(struct double_list **help, struct double_list **from, +                      int *len) +{ +  struct double_list *dd; +  char *s, **list; +  int count = 0; + +  *len = 0; +  zap_blank_lines(help); +  *from = *help; + +  // Find start of dash block. Must be at start or after blank line. +  for (;;) { +    s = trim((*from)->data); +    if (*s == '-' && s[1] != '-' && !count) break; + +    if (!*s) count = 0; +    else count++; + +    *from = (*from)->next; +    if (*from == *help) return 0; +  } + +  // If there was whitespace before this, zap it. This can't take out *help +  // because zap_blank_lines skipped blank lines, and we had to have at least +  // one non-blank line (a dash line) to get this far. +  while (!*trim((*from)->prev->data)) { +    *from = (*from)->prev; +    free(dlist_zap(from)); +  } + +  // Count number of dashlines, copy out to array, zap trailing whitespace +  // If *help was at start of dashblock, move it with *from +  count = 0; +  dd = *from; +  if (*help == *from) *help = 0; +  for (;;) { +   if (*trim(dd->data) != '-') break; +   count++; +   if (*from == (dd = dd->next)) break; +  } + +  list = xmalloc(sizeof(char *)*count); +  *len = count; +  while (count) list[--count] = dlist_zap(from); + +  return list;  }  void parse(char *filename) @@ -108,15 +175,20 @@ int charsort(void *a, void *b)    return 0;  } -int dashsort(void *a, void *b) +int dashsort(char **a, char **b)  { -  char *aa = *(char **)a, *bb = *(char **)b; +  char *aa = *a, *bb = *b;    if (aa[1] < bb[1]) return -1;    if (aa[1] > bb[1]) return 1;    return 0;  } +int dashlinesort(char **a, char **b) +{ +  return strcmp(*a, *b); +} +  int main(int argc, char *argv[])  {    FILE *fp; @@ -154,7 +226,8 @@ int main(int argc, char *argv[])    // Collate help according to usage, depends, and .config    // Loop through each entry, finding duplicate enabled "usage:" names - +  // This is in reverse order, so last entry gets collated with previous +  // entry until we run out of matching pairs.    for (;;) {      struct symbol *throw = 0, *catch;      char *this, *that, *cusage, *tusage, *name; @@ -164,11 +237,12 @@ int main(int argc, char *argv[])      for (catch = sym; catch; catch = catch->next) {        if (catch->enabled != 1) continue;        if (catch->help && (that = keyword("usage:", catch->help->data))) { -        struct double_list *bang; -        char *try; - -        // Suck help text out of throw into catch, copying from this to that +        struct double_list *cfrom, *tfrom, *anchor; +        char *try, **cdashlines, **tdashlines; +        int clen, tlen; +        // Align usage: lines, finding a matching pair so we can suck help +        // text out of throw into catch, copying from this to that          if (!throw) name = that;          else if (strncmp(name, that, len) || !isspace(that[len])) continue;          catch->enabled++; @@ -182,14 +256,67 @@ int main(int argc, char *argv[])            continue;          } -        // Grab usage: lines to collate -        cusage = dlist_zap(&catch->help); -        zap_blank_lines(&catch->help); +        // Grab option description lines to collate from catch and throw          tusage = dlist_zap(&throw->help); -        zap_blank_lines(&throw->help); +        tdashlines = grab_dashlines(&throw->help, &tfrom, &tlen); +        cusage = dlist_zap(&catch->help); +        cdashlines = grab_dashlines(&catch->help, &cfrom, &clen); +        anchor = catch->help; + +        // If we've got both, collate and alphebetize +        if (cdashlines && tdashlines) { +          char **new = xmalloc(sizeof(char *)*(clen+tlen)); + +          memcpy(new, cdashlines, sizeof(char *)*clen); +          memcpy(new+clen, tdashlines, sizeof(char *)*tlen); +          free(cdashlines); +          free(tdashlines); +          qsort(new, clen+tlen, sizeof(char *), (void *)dashlinesort); +          cdashlines = new; + +        // If just one, make sure it's in catch. +        } else if (tdashlines) cdashlines = tdashlines; + +        // If throw had a prefix, insert it before dashlines, with a +        // blank line if catch had a prefix. +        if (tfrom && tfrom != throw->help) { +          if (throw->help || catch->help) dlist_add(&cfrom, strdup("")); +          else { +            dlist_add(&cfrom, 0); +            anchor = cfrom->prev; +          } +          while (throw->help && throw->help != tfrom) +            dlist_add(&cfrom, dlist_zap(&throw->help)); +          if (cfrom && cfrom->prev->data && *trim(cfrom->prev->data)) +            dlist_add(&cfrom, strdup("")); +        } +        if (!anchor) { +          dlist_add(&cfrom, 0); +          anchor = cfrom->prev; +        } + +        // Splice sorted lines back in place +        if (cdashlines) { +          tlen += clen; + +          for (clen = 0; clen < tlen; clen++)  +            dlist_add(&cfrom, cdashlines[clen]); +        } + +        // If there were no dashlines, text would be considered prefix, so +        // the list is definitely no longer empty, so discard placeholder. +        if (!anchor->data) dlist_zap(&anchor); + +        // zap whitespace at end of catch help text +        while (!*trim(anchor->prev->data)) { +          anchor = anchor->prev; +          free(dlist_zap(&anchor)); +        } -        // Collate first [-abc] option block +        // Append trailing lines. +        while (tfrom) dlist_add(&anchor, dlist_zap(&tfrom)); +        // Collate first [-abc] option block in usage: lines          try = 0;          if (*this == '[' && this[1] == '-' && this[2] != '-' &&              *that == '[' && that[1] == '-' && that[2] != '-') @@ -205,27 +332,21 @@ int main(int argc, char *argv[])            }          } +        // The list is definitely no longer empty, so discard placeholder. +        if (!anchor->data) dlist_zap(&anchor); +          // Add new collated line (and whitespace). -        dlist_add(&catch->help, xmprintf("%*cusage: %.*s %s%s%s%s", +        dlist_add(&anchor, xmprintf("%*cusage: %.*s %s%s%s%s",                    catch->help_indent, ' ', len, name, try ? try : "",                    this, *this ? " " : "", that)); -        dlist_add(&catch->help, strdup("")); -        catch->help = catch->help->prev->prev; - +        free(try); +        dlist_add(&anchor, strdup(""));          free(cusage);          free(tusage); -        free(try); -          throw->enabled = 0; +        throw = catch; +        throw->help = anchor->prev->prev; -        // splice together circularly linked lists -        bang = throw->help->prev; -        throw->help->prev->next = catch->help; -        throw->help->prev = catch->help->prev; -        catch->help->prev->next = throw->help; -        catch->help->prev = bang; - -        throw->help = 0;          throw = catch;          this = throw->help->data + throw->help_indent + 8 + len;        }  | 
