From 86cafe1fde7c40625b50433a731bb167934bd8ab Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Fri, 3 Jan 2014 18:23:09 -0600 Subject: Replace python help converter with C implementation. --- Makefile | 7 +-- scripts/config2help.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++++ scripts/config2help.py | 54 ------------------- scripts/config2help.sh | 54 ------------------- scripts/make.sh | 30 ++++------- 5 files changed, 156 insertions(+), 130 deletions(-) create mode 100644 scripts/config2help.c delete mode 100755 scripts/config2help.py delete mode 100755 scripts/config2help.sh diff --git a/Makefile b/Makefile index 6494a012..13c8ec42 100644 --- a/Makefile +++ b/Makefile @@ -42,13 +42,14 @@ uninstall: 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 diff --git a/scripts/config2help.c b/scripts/config2help.c new file mode 100644 index 00000000..337db9aa --- /dev/null +++ b/scripts/config2help.c @@ -0,0 +1,141 @@ +#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; + } +} diff --git a/scripts/config2help.py b/scripts/config2help.py deleted file mode 100755 index 2573d08a..00000000 --- a/scripts/config2help.py +++ /dev/null @@ -1,54 +0,0 @@ -#!/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') diff --git a/scripts/config2help.sh b/scripts/config2help.sh deleted file mode 100755 index 8f96e39e..00000000 --- a/scripts/config2help.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/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 - diff --git a/scripts/make.sh b/scripts/make.sh index e4f0b35e..9fdadc47 100755 --- a/scripts/make.sh +++ b/scripts/make.sh @@ -13,6 +13,13 @@ then 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. @@ -59,10 +66,7 @@ sed -n -e 's/^USE_[A-Z0-9_]*(/&/p' toys/*/*.c \ 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 " @@ -125,21 +129,9 @@ GLOBSTRUCT="$(getglobals)" ) > 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 -- cgit v1.2.3