aboutsummaryrefslogtreecommitdiff
path: root/scripts/config2help.c
diff options
context:
space:
mode:
authorRob Landley <rob@landley.net>2014-01-29 23:47:53 -0600
committerRob Landley <rob@landley.net>2014-01-29 23:47:53 -0600
commit0432050a75f615a6e68d6bc60bba2fb939fbb586 (patch)
tree04a316b4c6eaed943894015cbaa53622d4637e17 /scripts/config2help.c
parentc8cce3f302ce47db42e65ab2078f7ca9027af968 (diff)
downloadtoybox-0432050a75f615a6e68d6bc60bba2fb939fbb586.tar.gz
More elaborate help text collating logic.
Diffstat (limited to 'scripts/config2help.c')
-rw-r--r--scripts/config2help.c179
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;
}