clean::
rm -rf toybox toybox_unstripped generated/config.h generated/Config.in \
- generated/newtoys.h generated/globals.h testdir \
+ generated/newtoys.h generated/globals.htestdir \
generated/Config.probed generated/oldtoys.h generated/flags.h \
generated/portability.h .singleconfig .singleconfig.old \
- generated/instlist generated/mkflags
+ generated/instlist generated/mkflags generated/config2help \
+ generated/help.h
distclean: clean
- rm -f toybox_old .config* generated/help.h
+ rm -f toybox_old .config*
test: tests
--- /dev/null
+#include "toys.h"
+
+// Humor toys.h
+struct toy_context toys;
+char libbuf[4096], toybuf[4096];
+void show_help(void) {;}
+void toy_exec(char *argv[]) {;}
+
+// Parse config files into data structures.
+
+struct symbol {
+ struct symbol *next;
+ int enabled;
+ char *name, *depends;
+ struct double_list *help;
+} *sym;
+
+char *keyword(char *name, char *line)
+{
+ int len = strlen(name);
+
+ while (isspace(*line)) line++;
+ if (strncmp(name, line, len)) return 0;
+ line += len;
+ if (*line && !isspace(*line)) return 0;
+ while (isspace(*line)) line++;
+
+ return line;
+}
+
+void parse(char *filename)
+{
+ FILE *fp = xfopen(filename, "r");
+ struct symbol *new = 0;
+ int help = 0;
+
+ for (;;) {
+ char *s, *line = NULL;
+ size_t len;
+
+ // Read line, trim whitespace at right edge.
+ if (getline(&line, &len, fp) < 1) break;
+ s = line+strlen(line);
+ while (--s >= line) {
+ if (!isspace(*s)) break;
+ *s = 0;
+ }
+
+ // source or config keyword at left edge?
+ if (*line && !isspace(*line)) {
+ help = 0;
+ if ((s = keyword("config", line))) {
+ new = xzalloc(sizeof(struct symbol));
+ new->next = sym;
+ new->name = s;
+ sym = new;
+ } else if ((s = keyword("source", line))) parse(s);
+
+ continue;
+ }
+ if (!new) continue;
+
+ if (help) dlist_add(&(new->help), line);
+ else if ((s = keyword("depends", line)) && (s = keyword("on", s)))
+ new->depends = s;
+ else if (keyword("help", line)) help++;
+ }
+
+ fclose(fp);
+}
+
+int main(int argc, char *argv[])
+{
+ FILE *fp;
+ struct symbol *try;
+ char *s, *file;
+
+ if (argc != 3) {
+ fprintf(stderr, "usage: config2help Config.in .config\n");
+ exit(1);
+ }
+
+ // Read Config.in
+ parse(argv[1]);
+
+ // read .config
+ fp = xfopen(argv[2], "r");
+ for (;;) {
+ char *line = NULL;
+ size_t len;
+
+ if (getline(&line, &len, fp) < 1) break;
+ if (!strncmp("CONFIG_", line, 7)) {
+ s = line+7;
+ for (try=sym; try; try=try->next) {
+ len = strlen(try->name);
+ if (!strncmp(try->name, s, len) && s[len]=='=' && s[len+1]=='y') {
+ try->enabled++;
+ break;
+ }
+ }
+ }
+ }
+
+ // Print out help #defines
+ while (sym) {
+ struct double_list *dd;
+
+ if (sym->help) {
+ int i, padlen = 0;
+
+ s = xstrdup(sym->name);
+ for (i = 0; s[i]; i++) s[i] = tolower(s[i]);
+ printf("#define help_%s \"", s);
+ free(s);
+
+ // Measure leading whitespace of first line
+ dd = sym->help;
+ while (isspace(dd->data[padlen])) padlen++;
+
+ for (;;) {
+ i = padlen;
+
+ // Trim leading whitespace
+ s = dd->data;
+ while (isspace(*s) && i) {
+ s++;
+ i--;
+ }
+ for (i=0; s[i]; i++) {
+ if (s[i] == '"' || s[i] == '\\') putchar('\\');
+ putchar(s[i]);
+ }
+ dd = dd->next;
+ if (dd == sym->help) break;
+ }
+ printf("\"\n");
+ }
+ sym = sym->next;
+ }
+}
+++ /dev/null
-#!/usr/bin/python
-
-import os,sys
-
-def zapquotes(str):
- if str[0]=='"': str = str[1:str.rfind('"')]
- return str
-
-def escapequotes(str):
- return str.strip().replace("\\","\\\\").replace('"','\\"')
-
-helplen = morelines = 0
-out = sys.stdout
-
-def readfile(filename):
- global helplen, morelines
- #sys.stderr.write("Reading %s\n" % filename)
- try:
- lines = open(filename).read().split("\n")
- except IOError:
- sys.stderr.write("File %s missing\n" % filename)
- return
- config = None
- description = None
- for i in lines:
- if helplen:
- i = i.expandtabs()
- if not len(i) or i[:helplen].isspace():
- if morelines: out.write('\\n')
- morelines = 1
- out.write(escapequotes(i))
- continue
- else:
- helplen = morelines = 0
- out.write('"\n')
-
- words = i.strip().split(None,1)
- if not len(words): continue
-
- if words[0] in ("config", "menuconfig"):
- config = words[1]
- description = ""
- elif words[0] in ("bool", "boolean", "tristate", "string", "hex", "int"):
- if len(words)>1: description = zapquotes(words[1])
- elif words[0]=="prompt":
- description = htmlescape(zapquotes(words[1]))
- elif words[0] in ("help", "---help---"):
- out.write('#define help_%s "' % config.lower())
- helplen = len(i[:i.find(words[0])].expandtabs())
- elif words[0] == "source": readfile(zapquotes(words[1]))
- elif words[0] in ("default","depends", "select", "if", "endif", "#", "comment", "menu", "endmenu"): pass
-
-readfile(sys.argv[1])
-if helplen: out.write('"\n')
+++ /dev/null
-#!/bin/bash -e
-
-function firstmajor() {
- declare -i n j=$1
- test $j -gt 0 || return -1
- for j in $@; do
- if [ $j -gt $1 ]; then
- echo $j
- return 0
- fi
- done
- return 1
-}; export -f firstmajor
-
-function print_h() {
- declare -i i c=$2 s=$3 e=$4
- local str="$(echo "$1" | head -n$c | tail -n1 | sed -e "s,config[\t ]*,,")"
- echo -n "#define help_"$str" \"" | tr [A-Z] [a-z]
- echo -n "$1\\n" | head -n$e | tail -n$[e-s+1] | sed -e "s,\$,\r," | tr \\n\\r n\\
- echo \"
-}; export -f print_h
-
-file="$1"
-if test "$0" != "bash"; then
- if test -r "$file"; then
-# echo "$file..." >&2
- filetxt="$(sed -e "s,^[\t ]*,," -e "s,\([\"\\\\]\),\\\\\\1,g" "$file")"
- helps=$(echo "$filetxt" | egrep -ne "^help *" -e "^---help--- *" | cut -d\: -f1)
- configs=$(echo "$filetxt" | egrep -ne "^config *" | cut -d\: -f1)
- endmenus=$(echo "$filetxt" | egrep -ne "^endmenu *" | cut -d\: -f1)
- let last=$(echo "$filetxt" | wc -l)+2
-
- declare -i i c s e
- for i in $configs; do
-# echo -n "c:$i" >&2
- s=$(firstmajor $i $helps)
- test $s -gt 0
- e=$(firstmajor $s $configs || firstmajor $s $endmenus $last)
- let s++ e-=2
- test $e -ge $s
-# echo " s:$s e:$e" >&2
- print_h "$filetxt" $i $s $e
- done
- for fle in $(cat "$file" | egrep -e "^[ \t]*source " | sed -e "s,^[ \t]*source *\(.*\),\\1,"); do
- $0 $fle
- done
- else
- echo
- echo "USAGE EXAMPLE: $(basename $0) Config.in > generated/help.h"
- echo
- false
- fi | sed -e "s,\\\\n\\\\n\"$,\\\\n\","
-fi
-
exit 1
fi
+# Respond to V= by echoing command lines as well as running them
+do_loudly()
+{
+ [ ! -z "$V" ] && echo "$@"
+ "$@"
+}
+
echo "Make generated/config.h from $KCONFIG_CONFIG."
# This long and roundabout sed invocation is to make old versions of sed happy.
sed -n -e 's/.*(NEWTOY(\([^,]*\), *\(\("[^"]*"[^,]*\)*\),.*/#define OPTSTR_\1\t\2/p' \
generated/newtoys.h > generated/oldtoys.h
-if [ ! -e generated/mkflags ]
-then
- $HOSTCC scripts/mkflags.c -o generated/mkflags || exit 1
-fi
+do_loudly $HOSTCC scripts/mkflags.c -o generated/mkflags || exit 1
echo -n "generated/flags.h "
) > generated/globals.h
echo "generated/help.h"
-# Only recreate generated/help.h if python2 is installed. Does not work with 3.
-[ -z "$(python --version 2>&1 | grep 'Python 2')" ] &&
- PYTHON="$(which python2 || which python2.6 || which python2.7)" ||
- PYTHON=python
-if [ ! -z "$(grep 'CONFIG_TOYBOX_HELP=y' $KCONFIG_CONFIG)" ];
-then
- if [ -z "$PYTHON" ];
- then
- echo "Python 2.x required to rebuild generated/help.h"
- # exit 1
- else
- echo "Extract help text from Config.in."
- "$PYTHON" scripts/config2help.py Config.in > generated/help.h || exit 1
- fi
-fi
+do_loudly $HOSTCC scripts/config2help.c -I . lib/xwrap.c lib/llist.c lib/lib.c \
+ -o generated/config2help && \
+generated/config2help Config.in .config > generated/help.h || exit 1
# Extract a list of toys/*/*.c files to compile from the data in $KCONFIG_CONFIG