====== kconfig / printconf ====== The point of origin was the zconf_dump() routine. As it turned out this was nothing like a "lint" or "dump" tool. It reports errors just because it's not supporting the kconfig syntax completely . It's obviously not the thing to mess with. Next try was to implement the ''printconf'' stuff. /* * V 5c * Released under the terms of the GNU GPL v2.0. */ #include #include #include "lkc.h" void printconf(FILE *); void printsym(FILE *, struct menu *); int main(int ac, char **av) { const char *name; if (ac != 2) exit(1); name = av[1]; conf_parse(name); printconf(stdout); /*zconfdump(stdout);*/ return 0; } void decodeflags (FILE *out, int flags); void decodeflags (FILE *out, int flags) { /* taken from expr.h */ int flaglist[] = { SYMBOL_CONST , /* 0x0001 symbol is const */ SYMBOL_CHECK , /* 0x0008 used during dependency checking */ SYMBOL_CHOICE , /* 0x0010 start of a choice block (null name) */ SYMBOL_CHOICEVAL, /* 0x0020 used as a value in a choice block */ SYMBOL_VALID , /* 0x0080 set when symbol.curr is calculated */ SYMBOL_OPTIONAL , /* 0x0100 choice is optional - values can be 'n' */ SYMBOL_WRITE , /* 0x0200 ? */ SYMBOL_CHANGED , /* 0x0400 ? */ SYMBOL_AUTO , /* 0x1000 value from environment variable */ SYMBOL_CHECKED , /* 0x2000 used during dependency checking */ SYMBOL_WARNED , /* 0x8000 warning has been issued */ 0x0 }; char *flagnames[] = { "CONST" , /* 0x0001 symbol is const */ "CHECK" , /* 0x0008 used during dependency checking */ "CHOICE" , /* 0x0010 start of a choice block (null name) */ "CHOICEVAL", /* 0x0020 used as a value in a choice block */ "VALID" , /* 0x0080 set when symbol.curr is calculated */ "OPTIONAL" , /* 0x0100 choice is optional - values can be 'n' */ "WRITE" , /* 0x0200 ? */ "CHANGED" , /* 0x0400 ? */ "AUTO" , /* 0x1000 value from environment variable */ "CHECKED" , /* 0x2000 used during dependency checking */ "WARNED" /* 0x8000 warning has been issued */ }; fprintf(out,"\t"); int i; for(i=0; flaglist[i]; i++) { if (flags & flaglist[i]) { fprintf(out,"%s",flagnames[i]); } } fprintf(out,"\n"); } void decodeexpr_type(FILE *out, char* tagname,int val); void decodeexpr_type(FILE *out, char* tagname,int val) { char *value; switch (val) { case E_NONE: value = "NONE"; break; case E_OR: value = "OR"; break; case E_AND: value = "AND"; break; case E_NOT: value = "NOT"; break; case E_EQUAL: value = "EQUAL"; break; case E_UNEQUAL: value = "UNEQUAL"; break; case E_LIST: value = "LIST"; break; case E_SYMBOL: value = "SYMBOL"; break; case E_RANGE: value = "RANGE"; break; default: fprintf(stderr, "ERROR: decodeexpr_type() '%d': should never happen\n",val); exit(1); } fprintf(out, "\t<%s>%s\n", tagname, value, tagname); } void decodesym(FILE *out, char* tagname,struct symbol_value symval); void decodesym(FILE *out, char* tagname,struct symbol_value symval) { fprintf(out, "\t<%s>%s\n", tagname, (char *)symval.val, tagname); } void printsym(FILE *out, struct menu *menu) { struct property *prop; // int have_properties = 0; int open_menu = 0; fprintf(out, "\n"); if (open_menu) // fprintf(out, "\n", menu->sym->name); fprintf(out, "\n", menu->sym->name,menu->sym->prop->file->name,menu->sym->prop->lineno); } void tag (FILE *out, char *tagname, char *value); void tag (FILE *out, char *tagname, char *value) { fprintf(out, "\t<%s>%s\n", tagname, value, tagname); } void printconf(FILE *out) { /* struct property *prop; */ struct menu *menu; fprintf(out, "\n"); fprintf(out, "\n"); fprintf(out, "\n"); menu = rootmenu.list; while (menu) { if ( menu->prompt ) { switch (menu->prompt->type) { case P_UNKNOWN: fprintf(out, "\t%s\n", "unknown"); break; case P_PROMPT: /* prompt "foo prompt" or "BAZ Value" */ // fprintf(out, "\t%s\n", "prompt"); break; case P_COMMENT: /* text associated with a comment */ // fprintf(out, "\t%s\n", "comment"); break; case P_MENU: /* prompt associated with a menuconfig option */ // fprintf(out, "\t%s\n", "menu"); break; case P_DEFAULT: /* default y */ fprintf(out, "\t%s\n", "default"); break; case P_CHOICE: /* choice value */ fprintf(out, "\t%s\n", "choice"); break; case P_SELECT: /* select BAR */ fprintf(out, "\t%s\n", "select"); break; case P_RANGE: /* range 7..100 (for a symbol) */ fprintf(out, "\t%s\n", "range"); break; case P_ENV: /* value from environment variable */ fprintf(out, "\t%s\n", "env"); break; case P_SYMBOL: /* where a symbol is defined */ fprintf(out, "\t%s\n", "symbol"); break; default: fprintf(stderr, "ERROR: menu->prompt->type '%d': should never happen\n",menu->prompt->type); exit(1); } } if (menu->sym) { printsym(out, menu); } else if (menu->prompt) { switch (menu->prompt->type) { case P_COMMENT: fprintf(out, "%s\n", menu->prompt->text); break; case P_MENU: if ( menu->sym ) { fprintf(out, "\n\t%s\n", menu->sym->name, menu->sym->prop->file->name, menu->sym->prop->lineno, menu->prompt->text); } else { fprintf(out, "\n\t%s\n", menu->prompt->text, menu->prompt->file->name, menu->prompt->file->lineno, menu->prompt->text); } // fprintf(out, "\n", menu->sym->name,menu->sym->prop->file->name,menu->sym->prop->lineno); break; case P_PROMPT: fprintf(out, "\n", menu->prompt->text); break; default: fprintf(stderr, "ERROR: menu->prompt->type '%d': should never happen\n",menu->prompt->type); exit(1); } if (menu->visibility) { decodeexpr_type(out,"visibility",menu->visibility->type); } } if (menu->list) menu = menu->list; else if (menu->next) menu = menu->next; else while ((menu = menu->parent)) { if (menu->prompt && menu->prompt->type == P_MENU) fprintf(out, "\n", menu->sym?menu->sym->name:menu->prompt->text); if (menu->next) { menu = menu->next; break; } } } fprintf(out, "\n"); fprintf(out, "\n"); } Then there is an assertion to be thrown on empty values, even if they are perfectly legal. The following patch helps: --- lkc.h.orig 2014-05-21 11:35:33.210489800 +0200 +++ lkc.h 2014-05-21 11:35:33.210489800 +0200 @@ -90,7 +90,10 @@ struct conf_printer { /* confdata.c and expr.c */ static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out) { - assert(len != 0); + /*assert(len != 0);*/ + if (len==0) { + return; + } if (fwrite(str, len, count, out) != count) fprintf(stderr, "Error in writing or end of file.\n"); To do things more easily, there is a script. You may want to change the settings of BASEDIR and DIR. #! /bin/sh if [ -z "$1" ]; then echo "usage: $0 " exit 1 fi KVER=$1 BASEDIR=/home/chris/prog/C/kconfig DIR=/home/chris/work/scratch/ssd01/kernels/linux-$KVER/scripts/kconfig if [ ! -e "$DIR" ]; then echo "$DIR does not exist" exit 1 fi if [ -e "$DIR" -a ! -d "$DIR" ]; then echo "$DIR exists but is not a directory" exit 1 fi if [ ! -e "$BASEDIR" ]; then echo "basedir '$BASEDIR' does not exist" exit 1 fi if [ -e "$BASEDIR" -a ! -d "$DIR" ]; then echo "basedir '$BASEDIR' exists but is not a directory" exit 1 fi cd $BASEDIR # ln -s jo/printconf.c-5a ./printconf.c cp printconf.c $DIR cp patches/lkc.h.diff $DIR #cp data/Kconfig* $DIR cd $DIR #flex --outfile zconf.lex.c zconf.l #gperf zconf.gperf --output-file zconf.hash.c #bison zconf.y cp zconf.hash.c_shipped zconf.hash.c cp zconf.lex.c_shipped zconf.lex.c cp zconf.tab.c_shipped zconf.tab.c patch < lkc.h.diff make () { gcc -Wp,-MD,.conf.o.d -Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer -I/usr/include/ncursesw -DCURSES_LOC="" -DLOCALE -c -o printconf.o printconf.c gcc -Wp,-MD,.zconf.tab.o.d -Wall -Wmissing-prototypes -Wstrict-prototypes -O2 -fomit-frame-pointer -I/usr/include/ncursesw -DCURSES_LOC="" -DLOCALE -I. -c -o zconf.tab.o zconf.tab.c gcc -o printconf printconf.o zconf.tab.o } make cd ../.. SRCARCH=x86 ARCH=x86 KERNELVERSION=$KVER scripts/kconfig/printconf Kconfig > Kconfig.xml cp -ax Kconfig.xml ../kconfig-$KVER.xml ===== current problems ===== * if running on kernel 3.10 some 37 '''' tags are missing. 3.4's just fine. * there are "entities" which are reflected as ''