All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC v5 0/5] mac80211: elide code for static hw flags
@ 2015-11-12 22:00 Johannes Berg
  2015-11-12 22:00 ` [RFC v5 1/5] kconfig: introduce "count" Johannes Berg
                   ` (4 more replies)
  0 siblings, 5 replies; 16+ messages in thread
From: Johannes Berg @ 2015-11-12 22:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Michal Marek

In v5, I've radically simplified the whole concept and dropped the
support for static keys. Instead, I'm now simply entirely removing 
the if statements - replacing them by "if (true)" or "if (false)" 
if that's at all possible.

For many (distro) kernels, this will - as before - mean no change,
but for those of us who are building special purpose systems with
perhaps just a single driver or two this might result in the code
size (and perhaps speed?) improvements I mention in the patch.

johannes


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [RFC v5 1/5] kconfig: introduce "count"
  2015-11-12 22:00 [RFC v5 0/5] mac80211: elide code for static hw flags Johannes Berg
@ 2015-11-12 22:00 ` Johannes Berg
  2015-11-12 22:00 ` [RFC v5 2/5] kconfig: regenerate the shipped files Johannes Berg
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 16+ messages in thread
From: Johannes Berg @ 2015-11-12 22:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Michal Marek, Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

"count" works similar to "select"; take, for example, this snippet:

    config MY_COUNTER
            int

    config MY_DRIVER_1
            bool "my driver 1"
            count MY_COUNTER

    config MY_DRIVER_2
            bool "my driver 2"
            count MY_COUNTER

This will get MY_COUNTER to have a value of 0, 1 or 2, depending
on whether or not MY_DRIVER_1/MY_DRIVER_2 are not at all, one or
both selected respectively.

This can be useful for certain optimization purposes but I'm sure
people will come up with other creative usage.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 Documentation/kbuild/kconfig-language.txt |  7 +++++++
 scripts/kconfig/expr.h                    |  1 +
 scripts/kconfig/menu.c                    | 28 +++++++++++++++++++++++++++-
 scripts/kconfig/symbol.c                  | 30 +++++++++++++++++++++++++++++-
 scripts/kconfig/zconf.gperf               |  1 +
 scripts/kconfig/zconf.y                   | 16 ++++++++++++++--
 6 files changed, 79 insertions(+), 4 deletions(-)

diff --git a/Documentation/kbuild/kconfig-language.txt b/Documentation/kbuild/kconfig-language.txt
index 350f733bf2c7..cee587254d3b 100644
--- a/Documentation/kbuild/kconfig-language.txt
+++ b/Documentation/kbuild/kconfig-language.txt
@@ -113,6 +113,13 @@ applicable everywhere (see syntax).
 	That will limit the usefulness but on the other hand avoid
 	the illegal configurations all over.
 
+- counting: "count" <symbol> ["if" <expr>]
+  If, for some reason, it is desired to understand the number of times a
+  given symbol is selected, that can be achieved by using "count" instead
+  of select. The <symbol> must be an int, and the default value is added
+  to the count.
+  A lot of the caveats for "select" apply here since it's very similar.
+
 - limiting menu display: "visible if" <expr>
   This attribute is only applicable to menu blocks, if the condition is
   false, the menu block is not displayed to the user (the symbols
diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h
index 973b6f733368..c77c8c30dd52 100644
--- a/scripts/kconfig/expr.h
+++ b/scripts/kconfig/expr.h
@@ -139,6 +139,7 @@ enum prop_type {
 	P_RANGE,    /* range 7..100 (for a symbol) */
 	P_ENV,      /* value from environment variable */
 	P_SYMBOL,   /* where a symbol is defined */
+	P_COUNT,    /* count BAR - increments BAR counter */
 };
 
 struct property {
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index b05cc3d4a9be..0f7ef400741a 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -265,6 +265,18 @@ static void sym_check_prop(struct symbol *sym)
 				    "accept arguments of boolean and "
 				    "tristate type", sym2->name);
 			break;
+		case P_COUNT:
+			sym2 = prop_get_symbol(prop);
+			if (sym->type != S_BOOLEAN && sym->type != S_TRISTATE)
+				prop_warn(prop,
+				    "config symbol '%s' uses select, but is "
+				    "not boolean or tristate", sym->name);
+			else if (sym2->type != S_INT)
+				prop_warn(prop,
+				    "'%s' has wrong type. 'count' only "
+				    "accept arguments of int type",
+				    sym2->name);
+			break;
 		case P_RANGE:
 			if (sym->type != S_INT && sym->type != S_HEX)
 				prop_warn(prop, "range is only allowed "
@@ -333,6 +345,9 @@ void menu_finalize(struct menu *parent)
 					struct symbol *es = prop_get_symbol(prop);
 					es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr,
 							expr_alloc_and(expr_alloc_symbol(menu->sym), expr_copy(dep)));
+				} else if (prop->type == P_COUNT) {
+					struct symbol *es = prop_get_symbol(prop);
+					es->rev_dep.expr = expr_alloc_or(es->rev_dep.expr, expr_alloc_symbol(menu->sym));
 				}
 			}
 		}
@@ -657,10 +672,21 @@ static void get_symbol_str(struct gstr *r, struct symbol *sym,
 			str_printf(r, " && ");
 		expr_gstr_print(prop->expr, r);
 	}
+	for_all_properties(sym, prop, P_COUNT) {
+		if (!hit) {
+			str_append(r, "  Counts: ");
+			hit = true;
+		} else
+			str_printf(r, " && ");
+		expr_gstr_print(prop->expr, r);
+	}
 	if (hit)
 		str_append(r, "\n");
 	if (sym->rev_dep.expr) {
-		str_append(r, _("  Selected by: "));
+		if (sym->type != S_INT)
+			str_append(r, _("  Selected by: "));
+		else
+			str_append(r, _("  Counted by: "));
 		expr_gstr_print(sym->rev_dep.expr, r);
 		str_append(r, "\n");
 	}
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
index 50878dc025a5..c50835f28243 100644
--- a/scripts/kconfig/symbol.c
+++ b/scripts/kconfig/symbol.c
@@ -310,6 +310,21 @@ static struct symbol *sym_calc_choice(struct symbol *sym)
 	return def_sym;
 }
 
+static unsigned long long count_or_symbols(struct expr *e)
+{
+	switch (e->type) {
+	case E_SYMBOL:
+		sym_calc_value(e->left.sym);
+		return e->left.sym->curr.tri != no;
+	case E_OR:
+		return count_or_symbols(e->left.expr) +
+		       count_or_symbols(e->right.expr);
+	default:
+		fprintf(stderr, "warning: unexpected expression in count");
+		return 0;
+	}
+}
+
 void sym_calc_value(struct symbol *sym)
 {
 	struct symbol_value newval, oldval;
@@ -421,6 +436,15 @@ void sym_calc_value(struct symbol *sym)
 				newval.val = ds->curr.val;
 			}
 		}
+		if (sym->rev_dep.expr) {
+			long long val = strtoll(newval.val, NULL, 0);
+			char *buf = xmalloc(22);
+
+			val += count_or_symbols(sym->rev_dep.expr);
+			sprintf(buf, "%lld", val);
+			newval.val = buf;
+			sym->flags |= SYMBOL_WRITE;
+		}
 		break;
 	default:
 		;
@@ -1197,7 +1221,9 @@ static struct symbol *sym_check_sym_deps(struct symbol *sym)
 		goto out;
 
 	for (prop = sym->prop; prop; prop = prop->next) {
-		if (prop->type == P_CHOICE || prop->type == P_SELECT)
+		if (prop->type == P_CHOICE ||
+		    prop->type == P_SELECT ||
+		    prop->type == P_COUNT)
 			continue;
 		stack.prop = prop;
 		sym2 = sym_check_expr_deps(prop->visible.expr);
@@ -1336,6 +1362,8 @@ const char *prop_get_type_name(enum prop_type type)
 		return "choice";
 	case P_SELECT:
 		return "select";
+	case P_COUNT:
+		return "count";
 	case P_RANGE:
 		return "range";
 	case P_SYMBOL:
diff --git a/scripts/kconfig/zconf.gperf b/scripts/kconfig/zconf.gperf
index ac498f01b449..46ce5833887e 100644
--- a/scripts/kconfig/zconf.gperf
+++ b/scripts/kconfig/zconf.gperf
@@ -46,4 +46,5 @@ modules,	T_OPT_MODULES,	TF_OPTION
 defconfig_list,	T_OPT_DEFCONFIG_LIST,TF_OPTION
 env,		T_OPT_ENV,	TF_OPTION
 allnoconfig_y,	T_OPT_ALLNOCONFIG_Y,TF_OPTION
+count,		T_COUNT,	TF_COMMAND
 %%
diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y
index 71bf8bff696a..18c43561860b 100644
--- a/scripts/kconfig/zconf.y
+++ b/scripts/kconfig/zconf.y
@@ -31,7 +31,7 @@ struct symbol *symbol_hash[SYMBOL_HASHSIZE];
 static struct menu *current_menu, *current_entry;
 
 %}
-%expect 30
+%expect 32
 
 %union
 {
@@ -76,6 +76,7 @@ static struct menu *current_menu, *current_entry;
 %token T_CLOSE_PAREN
 %token T_OPEN_PAREN
 %token T_EOL
+%token <id>T_COUNT
 
 %left T_OR
 %left T_AND
@@ -124,7 +125,7 @@ stmt_list:
 ;
 
 option_name:
-	T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_OPTIONAL | T_RANGE | T_DEFAULT | T_VISIBLE
+	T_DEPENDS | T_PROMPT | T_TYPE | T_SELECT | T_COUNT | T_OPTIONAL | T_RANGE | T_DEFAULT | T_VISIBLE
 ;
 
 common_stmt:
@@ -216,6 +217,12 @@ config_option: T_SELECT T_WORD if_expr T_EOL
 	printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno());
 };
 
+config_option: T_COUNT T_WORD if_expr T_EOL
+{
+	menu_add_symbol(P_COUNT, sym_lookup($2, 0), $3);
+	printd(DEBUG_PARSE, "%s:%d:count\n", zconf_curname(), zconf_lineno());
+};
+
 config_option: T_RANGE symbol symbol if_expr T_EOL
 {
 	menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,$2, $3), $4);
@@ -664,6 +671,11 @@ static void print_symbol(FILE *out, struct menu *menu)
 			expr_fprint(prop->expr, out);
 			fputc('\n', out);
 			break;
+		case P_COUNT:
+			fputs( "  count ", out);
+			expr_fprint(prop->expr, out);
+			fputc('\n', out);
+			break;
 		case P_RANGE:
 			fputs( "  range ", out);
 			expr_fprint(prop->expr, out);
-- 
2.6.2


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC v5 2/5] kconfig: regenerate the shipped files
  2015-11-12 22:00 [RFC v5 0/5] mac80211: elide code for static hw flags Johannes Berg
  2015-11-12 22:00 ` [RFC v5 1/5] kconfig: introduce "count" Johannes Berg
@ 2015-11-12 22:00 ` Johannes Berg
  2015-11-12 22:00 ` [RFC v5 3/5] mac80211: generate hw flags from include file Johannes Berg
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 16+ messages in thread
From: Johannes Berg @ 2015-11-12 22:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Michal Marek, Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

Unfortunately, I again used a different version of the tools,
so the changes are rather large.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 scripts/kconfig/zconf.hash.c_shipped |   10 +-
 scripts/kconfig/zconf.lex.c_shipped  |   62 +-
 scripts/kconfig/zconf.tab.c_shipped  | 1600 ++++++++++++++++------------------
 3 files changed, 789 insertions(+), 883 deletions(-)

diff --git a/scripts/kconfig/zconf.hash.c_shipped b/scripts/kconfig/zconf.hash.c_shipped
index 360a62df2b5e..759bfe9400e2 100644
--- a/scripts/kconfig/zconf.hash.c_shipped
+++ b/scripts/kconfig/zconf.hash.c_shipped
@@ -118,6 +118,7 @@ struct kconf_id_strings_t
     char kconf_id_strings_str41[sizeof("source")];
     char kconf_id_strings_str42[sizeof("visible")];
     char kconf_id_strings_str43[sizeof("hex")];
+    char kconf_id_strings_str45[sizeof("count")];
     char kconf_id_strings_str46[sizeof("config")];
     char kconf_id_strings_str47[sizeof("boolean")];
     char kconf_id_strings_str51[sizeof("string")];
@@ -155,6 +156,7 @@ static const struct kconf_id_strings_t kconf_id_strings_contents =
     "source",
     "visible",
     "hex",
+    "count",
     "config",
     "boolean",
     "string",
@@ -174,7 +176,7 @@ kconf_id_lookup (register const char *str, register unsigned int len)
 {
   enum
     {
-      TOTAL_KEYWORDS = 34,
+      TOTAL_KEYWORDS = 35,
       MIN_WORD_LENGTH = 2,
       MAX_WORD_LENGTH = 14,
       MIN_HASH_VALUE = 2,
@@ -251,7 +253,9 @@ kconf_id_lookup (register const char *str, register unsigned int len)
       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str42,	T_VISIBLE,	TF_COMMAND},
 #line 38 "scripts/kconfig/zconf.gperf"
       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str43,		T_TYPE,		TF_COMMAND, S_HEX},
-      {-1}, {-1},
+      {-1},
+#line 49 "scripts/kconfig/zconf.gperf"
+      {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str45,		T_COUNT,	TF_COMMAND},
 #line 22 "scripts/kconfig/zconf.gperf"
       {(int)(long)&((struct kconf_id_strings_t *)0)->kconf_id_strings_str46,		T_CONFIG,	TF_COMMAND},
 #line 35 "scripts/kconfig/zconf.gperf"
@@ -289,5 +293,5 @@ kconf_id_lookup (register const char *str, register unsigned int len)
     }
   return 0;
 }
-#line 49 "scripts/kconfig/zconf.gperf"
+#line 50 "scripts/kconfig/zconf.gperf"
 
diff --git a/scripts/kconfig/zconf.lex.c_shipped b/scripts/kconfig/zconf.lex.c_shipped
index 37fdf6123505..204d2d265201 100644
--- a/scripts/kconfig/zconf.lex.c_shipped
+++ b/scripts/kconfig/zconf.lex.c_shipped
@@ -27,7 +27,7 @@
 #define FLEX_SCANNER
 #define YY_FLEX_MAJOR_VERSION 2
 #define YY_FLEX_MINOR_VERSION 5
-#define YY_FLEX_SUBMINOR_VERSION 35
+#define YY_FLEX_SUBMINOR_VERSION 39
 #if YY_FLEX_SUBMINOR_VERSION > 0
 #define FLEX_BETA
 #endif
@@ -180,7 +180,12 @@ typedef unsigned int flex_uint32_t;
 typedef struct yy_buffer_state *YY_BUFFER_STATE;
 #endif
 
-extern int zconfleng;
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef size_t yy_size_t;
+#endif
+
+extern yy_size_t zconfleng;
 
 extern FILE *zconfin, *zconfout;
 
@@ -189,6 +194,7 @@ extern FILE *zconfin, *zconfout;
 #define EOB_ACT_LAST_MATCH 2
 
     #define YY_LESS_LINENO(n)
+    #define YY_LINENO_REWIND_TO(ptr)
     
 /* Return all but the first "n" matched characters back to the input stream. */
 #define yyless(n) \
@@ -206,11 +212,6 @@ extern FILE *zconfin, *zconfout;
 
 #define unput(c) yyunput( c, (yytext_ptr)  )
 
-#ifndef YY_TYPEDEF_YY_SIZE_T
-#define YY_TYPEDEF_YY_SIZE_T
-typedef size_t yy_size_t;
-#endif
-
 #ifndef YY_STRUCT_YY_BUFFER_STATE
 #define YY_STRUCT_YY_BUFFER_STATE
 struct yy_buffer_state
@@ -228,7 +229,7 @@ struct yy_buffer_state
 	/* Number of characters read into yy_ch_buf, not including EOB
 	 * characters.
 	 */
-	int yy_n_chars;
+	yy_size_t yy_n_chars;
 
 	/* Whether we "own" the buffer - i.e., we know we created it,
 	 * and can realloc() it to grow it, and should free() it to
@@ -298,8 +299,8 @@ static YY_BUFFER_STATE * yy_buffer_stack = 0; /**< Stack as an array. */
 
 /* yy_hold_char holds the character lost when zconftext is formed. */
 static char yy_hold_char;
-static int yy_n_chars;		/* number of characters read into yy_ch_buf */
-int zconfleng;
+static yy_size_t yy_n_chars;		/* number of characters read into yy_ch_buf */
+yy_size_t zconfleng;
 
 /* Points to current character in buffer. */
 static char *yy_c_buf_p = (char *) 0;
@@ -327,7 +328,7 @@ static void zconf_init_buffer (YY_BUFFER_STATE b,FILE *file  );
 
 YY_BUFFER_STATE zconf_scan_buffer (char *base,yy_size_t size  );
 YY_BUFFER_STATE zconf_scan_string (yyconst char *yy_str  );
-YY_BUFFER_STATE zconf_scan_bytes (yyconst char *bytes,int len  );
+YY_BUFFER_STATE zconf_scan_bytes (yyconst char *bytes,yy_size_t len  );
 
 void *zconfalloc (yy_size_t  );
 void *zconfrealloc (void *,yy_size_t  );
@@ -359,7 +360,7 @@ void zconffree (void *  );
 
 /* Begin user sect3 */
 
-#define zconfwrap(n) 1
+#define zconfwrap() 1
 #define YY_SKIP_YYWRAP
 
 typedef unsigned char YY_CHAR;
@@ -374,6 +375,7 @@ int zconflineno = 1;
 
 extern char *zconftext;
 #define yytext_ptr zconftext
+
 static yyconst flex_int16_t yy_nxt[][18] =
     {
     {
@@ -902,7 +904,7 @@ FILE *zconfget_out (void );
 
 void zconfset_out  (FILE * out_str  );
 
-int zconfget_leng (void );
+yy_size_t zconfget_leng (void );
 
 char *zconfget_text (void );
 
@@ -1034,9 +1036,6 @@ YY_DECL
 	register char *yy_cp, *yy_bp;
 	register int yy_act;
     
-	int str = 0;
-	int ts, i;
-
 	if ( !(yy_init) )
 		{
 		(yy_init) = 1;
@@ -1063,6 +1062,11 @@ YY_DECL
 		zconf_load_buffer_state( );
 		}
 
+	{
+
+	int str = 0;
+	int ts, i;
+
 	while ( 1 )		/* loops until end-of-file is reached */
 		{
 		yy_cp = (yy_c_buf_p);
@@ -1245,6 +1249,7 @@ case YY_STATE_EOF(PARAM):
 case 27:
 /* rule 27 can match eol */
 *yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */
+YY_LINENO_REWIND_TO(yy_cp - 1);
 (yy_c_buf_p) = yy_cp -= 1;
 YY_DO_BEFORE_ACTION; /* set up zconftext again */
 YY_RULE_SETUP
@@ -1263,6 +1268,7 @@ YY_RULE_SETUP
 case 29:
 /* rule 29 can match eol */
 *yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */
+YY_LINENO_REWIND_TO(yy_cp - 1);
 (yy_c_buf_p) = yy_cp -= 1;
 YY_DO_BEFORE_ACTION; /* set up zconftext again */
 YY_RULE_SETUP
@@ -1333,6 +1339,7 @@ YY_RULE_SETUP
 case 34:
 /* rule 34 can match eol */
 *yy_cp = (yy_hold_char); /* undo effects of setting up zconftext */
+YY_LINENO_REWIND_TO(yy_cp - 1);
 (yy_c_buf_p) = yy_cp -= 1;
 YY_DO_BEFORE_ACTION; /* set up zconftext again */
 YY_RULE_SETUP
@@ -1513,6 +1520,7 @@ YY_FATAL_ERROR( "flex scanner jammed" );
 			"fatal flex scanner internal error--no action found" );
 	} /* end of action switch */
 		} /* end of scanning one token */
+	} /* end of user's declarations */
 } /* end of zconflex */
 
 /* yy_get_next_buffer - try to read in a new buffer
@@ -1568,21 +1576,21 @@ static int yy_get_next_buffer (void)
 
 	else
 		{
-			int num_to_read =
+			yy_size_t num_to_read =
 			YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
 
 		while ( num_to_read <= 0 )
 			{ /* Not enough room in the buffer - grow it. */
 
 			/* just a shorter name for the current buffer */
-			YY_BUFFER_STATE b = YY_CURRENT_BUFFER;
+			YY_BUFFER_STATE b = YY_CURRENT_BUFFER_LVALUE;
 
 			int yy_c_buf_p_offset =
 				(int) ((yy_c_buf_p) - b->yy_ch_buf);
 
 			if ( b->yy_is_our_buffer )
 				{
-				int new_size = b->yy_buf_size * 2;
+				yy_size_t new_size = b->yy_buf_size * 2;
 
 				if ( new_size <= 0 )
 					b->yy_buf_size += b->yy_buf_size / 8;
@@ -1613,7 +1621,7 @@ static int yy_get_next_buffer (void)
 
 		/* Read in more data. */
 		YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
-			(yy_n_chars), (size_t) num_to_read );
+			(yy_n_chars), num_to_read );
 
 		YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars);
 		}
@@ -1683,7 +1691,7 @@ static int yy_get_next_buffer (void)
 	yy_current_state = yy_nxt[yy_current_state][1];
 	yy_is_jam = (yy_current_state <= 0);
 
-	return yy_is_jam ? 0 : yy_current_state;
+		return yy_is_jam ? 0 : yy_current_state;
 }
 
     static void yyunput (int c, register char * yy_bp )
@@ -1698,7 +1706,7 @@ static int yy_get_next_buffer (void)
 	if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
 		{ /* need to shift things up to make room */
 		/* +2 for EOB chars. */
-		register int number_to_move = (yy_n_chars) + 2;
+		register yy_size_t number_to_move = (yy_n_chars) + 2;
 		register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
 					YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
 		register char *source =
@@ -1747,7 +1755,7 @@ static int yy_get_next_buffer (void)
 
 		else
 			{ /* need more input */
-			int offset = (yy_c_buf_p) - (yytext_ptr);
+			yy_size_t offset = (yy_c_buf_p) - (yytext_ptr);
 			++(yy_c_buf_p);
 
 			switch ( yy_get_next_buffer(  ) )
@@ -2019,7 +2027,7 @@ void zconfpop_buffer_state (void)
  */
 static void zconfensure_buffer_stack (void)
 {
-	int num_to_alloc;
+	yy_size_t num_to_alloc;
     
 	if (!(yy_buffer_stack)) {
 
@@ -2116,12 +2124,12 @@ YY_BUFFER_STATE zconf_scan_string (yyconst char * yystr )
  * 
  * @return the newly allocated buffer state object.
  */
-YY_BUFFER_STATE zconf_scan_bytes  (yyconst char * yybytes, int  _yybytes_len )
+YY_BUFFER_STATE zconf_scan_bytes  (yyconst char * yybytes, yy_size_t  _yybytes_len )
 {
 	YY_BUFFER_STATE b;
 	char *buf;
 	yy_size_t n;
-	int i;
+	yy_size_t i;
     
 	/* Get memory for full buffer, including space for trailing EOB's. */
 	n = _yybytes_len + 2;
@@ -2203,7 +2211,7 @@ FILE *zconfget_out  (void)
 /** Get the length of the current token.
  * 
  */
-int zconfget_leng  (void)
+yy_size_t zconfget_leng  (void)
 {
         return zconfleng;
 }
diff --git a/scripts/kconfig/zconf.tab.c_shipped b/scripts/kconfig/zconf.tab.c_shipped
index 7a4d658c2066..2d34ce63fd0e 100644
--- a/scripts/kconfig/zconf.tab.c_shipped
+++ b/scripts/kconfig/zconf.tab.c_shipped
@@ -1,19 +1,19 @@
-/* A Bison parser, made by GNU Bison 2.5.1.  */
+/* A Bison parser, made by GNU Bison 3.0.4.  */
 
 /* Bison implementation for Yacc-like parsers in C
-   
-      Copyright (C) 1984, 1989-1990, 2000-2012 Free Software Foundation, Inc.
-   
+
+   Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc.
+
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
-   
+
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
-   
+
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
@@ -26,7 +26,7 @@
    special exception, which will cause the skeleton and the resulting
    Bison output files to be licensed under the GNU General Public
    License without this special exception.
-   
+
    This special exception was added by the Free Software Foundation in
    version 2.2 of Bison.  */
 
@@ -44,7 +44,7 @@
 #define YYBISON 1
 
 /* Bison version.  */
-#define YYBISON_VERSION "2.5.1"
+#define YYBISON_VERSION "3.0.4"
 
 /* Skeleton name.  */
 #define YYSKELETON_NAME "yacc.c"
@@ -58,18 +58,16 @@
 /* Pull parsers.  */
 #define YYPULL 1
 
-/* Using locations.  */
-#define YYLSP_NEEDED 0
 
 /* Substitute the variable and function names.  */
 #define yyparse         zconfparse
 #define yylex           zconflex
 #define yyerror         zconferror
-#define yylval          zconflval
-#define yychar          zconfchar
 #define yydebug         zconfdebug
 #define yynerrs         zconfnerrs
 
+#define yylval          zconflval
+#define yychar          zconfchar
 
 /* Copy the first part of user declarations.  */
 
@@ -108,19 +106,14 @@ static struct menu *current_menu, *current_entry;
 
 
 
-# ifndef YY_NULL
+# ifndef YY_NULLPTR
 #  if defined __cplusplus && 201103L <= __cplusplus
-#   define YY_NULL nullptr
+#   define YY_NULLPTR nullptr
 #  else
-#   define YY_NULL 0
+#   define YY_NULLPTR 0
 #  endif
 # endif
 
-/* Enabling traces.  */
-#ifndef YYDEBUG
-# define YYDEBUG 1
-#endif
-
 /* Enabling verbose error messages.  */
 #ifdef YYERROR_VERBOSE
 # undef YYERROR_VERBOSE
@@ -129,62 +122,65 @@ static struct menu *current_menu, *current_entry;
 # define YYERROR_VERBOSE 0
 #endif
 
-/* Enabling the token table.  */
-#ifndef YYTOKEN_TABLE
-# define YYTOKEN_TABLE 0
-#endif
 
+/* Debug traces.  */
+#ifndef YYDEBUG
+# define YYDEBUG 1
+#endif
+#if YYDEBUG
+extern int zconfdebug;
+#endif
 
-/* Tokens.  */
+/* Token type.  */
 #ifndef YYTOKENTYPE
 # define YYTOKENTYPE
-   /* Put the tokens into the symbol table, so that GDB and other debuggers
-      know about them.  */
-   enum yytokentype {
-     T_MAINMENU = 258,
-     T_MENU = 259,
-     T_ENDMENU = 260,
-     T_SOURCE = 261,
-     T_CHOICE = 262,
-     T_ENDCHOICE = 263,
-     T_COMMENT = 264,
-     T_CONFIG = 265,
-     T_MENUCONFIG = 266,
-     T_HELP = 267,
-     T_HELPTEXT = 268,
-     T_IF = 269,
-     T_ENDIF = 270,
-     T_DEPENDS = 271,
-     T_OPTIONAL = 272,
-     T_PROMPT = 273,
-     T_TYPE = 274,
-     T_DEFAULT = 275,
-     T_SELECT = 276,
-     T_RANGE = 277,
-     T_VISIBLE = 278,
-     T_OPTION = 279,
-     T_ON = 280,
-     T_WORD = 281,
-     T_WORD_QUOTE = 282,
-     T_UNEQUAL = 283,
-     T_LESS = 284,
-     T_LESS_EQUAL = 285,
-     T_GREATER = 286,
-     T_GREATER_EQUAL = 287,
-     T_CLOSE_PAREN = 288,
-     T_OPEN_PAREN = 289,
-     T_EOL = 290,
-     T_OR = 291,
-     T_AND = 292,
-     T_EQUAL = 293,
-     T_NOT = 294
-   };
+  enum yytokentype
+  {
+    T_MAINMENU = 258,
+    T_MENU = 259,
+    T_ENDMENU = 260,
+    T_SOURCE = 261,
+    T_CHOICE = 262,
+    T_ENDCHOICE = 263,
+    T_COMMENT = 264,
+    T_CONFIG = 265,
+    T_MENUCONFIG = 266,
+    T_HELP = 267,
+    T_HELPTEXT = 268,
+    T_IF = 269,
+    T_ENDIF = 270,
+    T_DEPENDS = 271,
+    T_OPTIONAL = 272,
+    T_PROMPT = 273,
+    T_TYPE = 274,
+    T_DEFAULT = 275,
+    T_SELECT = 276,
+    T_RANGE = 277,
+    T_VISIBLE = 278,
+    T_OPTION = 279,
+    T_ON = 280,
+    T_WORD = 281,
+    T_WORD_QUOTE = 282,
+    T_UNEQUAL = 283,
+    T_LESS = 284,
+    T_LESS_EQUAL = 285,
+    T_GREATER = 286,
+    T_GREATER_EQUAL = 287,
+    T_CLOSE_PAREN = 288,
+    T_OPEN_PAREN = 289,
+    T_EOL = 290,
+    T_COUNT = 291,
+    T_OR = 292,
+    T_AND = 293,
+    T_EQUAL = 294,
+    T_NOT = 295
+  };
 #endif
 
-
-
+/* Value type.  */
 #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
-typedef union YYSTYPE
+
+union YYSTYPE
 {
 
 
@@ -196,14 +192,20 @@ typedef union YYSTYPE
 	const struct kconf_id *id;
 
 
+};
 
-} YYSTYPE;
+typedef union YYSTYPE YYSTYPE;
 # define YYSTYPE_IS_TRIVIAL 1
-# define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
 #endif
 
 
+extern YYSTYPE zconflval;
+
+int zconfparse (void);
+
+
+
 /* Copy the second part of user declarations.  */
 
 
@@ -224,11 +226,8 @@ typedef unsigned char yytype_uint8;
 
 #ifdef YYTYPE_INT8
 typedef YYTYPE_INT8 yytype_int8;
-#elif (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-typedef signed char yytype_int8;
 #else
-typedef short int yytype_int8;
+typedef signed char yytype_int8;
 #endif
 
 #ifdef YYTYPE_UINT16
@@ -248,8 +247,7 @@ typedef short int yytype_int16;
 #  define YYSIZE_T __SIZE_TYPE__
 # elif defined size_t
 #  define YYSIZE_T size_t
-# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
+# elif ! defined YYSIZE_T
 #  include <stddef.h> /* INFRINGES ON USER NAME SPACE */
 #  define YYSIZE_T size_t
 # else
@@ -263,38 +261,67 @@ typedef short int yytype_int16;
 # if defined YYENABLE_NLS && YYENABLE_NLS
 #  if ENABLE_NLS
 #   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
-#   define YY_(msgid) dgettext ("bison-runtime", msgid)
+#   define YY_(Msgid) dgettext ("bison-runtime", Msgid)
 #  endif
 # endif
 # ifndef YY_
-#  define YY_(msgid) msgid
+#  define YY_(Msgid) Msgid
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE
+# if (defined __GNUC__                                               \
+      && (2 < __GNUC__ || (__GNUC__ == 2 && 96 <= __GNUC_MINOR__)))  \
+     || defined __SUNPRO_C && 0x5110 <= __SUNPRO_C
+#  define YY_ATTRIBUTE(Spec) __attribute__(Spec)
+# else
+#  define YY_ATTRIBUTE(Spec) /* empty */
+# endif
+#endif
+
+#ifndef YY_ATTRIBUTE_PURE
+# define YY_ATTRIBUTE_PURE   YY_ATTRIBUTE ((__pure__))
+#endif
+
+#ifndef YY_ATTRIBUTE_UNUSED
+# define YY_ATTRIBUTE_UNUSED YY_ATTRIBUTE ((__unused__))
+#endif
+
+#if !defined _Noreturn \
+     && (!defined __STDC_VERSION__ || __STDC_VERSION__ < 201112)
+# if defined _MSC_VER && 1200 <= _MSC_VER
+#  define _Noreturn __declspec (noreturn)
+# else
+#  define _Noreturn YY_ATTRIBUTE ((__noreturn__))
 # endif
 #endif
 
 /* Suppress unused-variable warnings by "using" E.  */
 #if ! defined lint || defined __GNUC__
-# define YYUSE(e) ((void) (e))
+# define YYUSE(E) ((void) (E))
 #else
-# define YYUSE(e) /* empty */
+# define YYUSE(E) /* empty */
 #endif
 
-/* Identity function, used to suppress warnings about constant conditions.  */
-#ifndef lint
-# define YYID(n) (n)
-#else
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-static int
-YYID (int yyi)
+#if defined __GNUC__ && 407 <= __GNUC__ * 100 + __GNUC_MINOR__
+/* Suppress an incorrect diagnostic about yylval being uninitialized.  */
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN \
+    _Pragma ("GCC diagnostic push") \
+    _Pragma ("GCC diagnostic ignored \"-Wuninitialized\"")\
+    _Pragma ("GCC diagnostic ignored \"-Wmaybe-uninitialized\"")
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END \
+    _Pragma ("GCC diagnostic pop")
 #else
-static int
-YYID (yyi)
-    int yyi;
+# define YY_INITIAL_VALUE(Value) Value
 #endif
-{
-  return yyi;
-}
+#ifndef YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
+# define YY_IGNORE_MAYBE_UNINITIALIZED_END
 #endif
+#ifndef YY_INITIAL_VALUE
+# define YY_INITIAL_VALUE(Value) /* Nothing. */
+#endif
+
 
 #if ! defined yyoverflow || YYERROR_VERBOSE
 
@@ -313,8 +340,7 @@ YYID (yyi)
 #    define alloca _alloca
 #   else
 #    define YYSTACK_ALLOC alloca
-#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
+#    if ! defined _ALLOCA_H && ! defined EXIT_SUCCESS
 #     include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
       /* Use EXIT_SUCCESS as a witness for stdlib.h.  */
 #     ifndef EXIT_SUCCESS
@@ -326,8 +352,8 @@ YYID (yyi)
 # endif
 
 # ifdef YYSTACK_ALLOC
-   /* Pacify GCC's `empty if-body' warning.  */
-#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+   /* Pacify GCC's 'empty if-body' warning.  */
+#  define YYSTACK_FREE(Ptr) do { /* empty */; } while (0)
 #  ifndef YYSTACK_ALLOC_MAXIMUM
     /* The OS might guarantee only one guard page at the bottom of the stack,
        and a page size can be as small as 4096 bytes.  So we cannot safely
@@ -343,7 +369,7 @@ YYID (yyi)
 #  endif
 #  if (defined __cplusplus && ! defined EXIT_SUCCESS \
        && ! ((defined YYMALLOC || defined malloc) \
-	     && (defined YYFREE || defined free)))
+             && (defined YYFREE || defined free)))
 #   include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
 #   ifndef EXIT_SUCCESS
 #    define EXIT_SUCCESS 0
@@ -351,15 +377,13 @@ YYID (yyi)
 #  endif
 #  ifndef YYMALLOC
 #   define YYMALLOC malloc
-#   if ! defined malloc && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
+#   if ! defined malloc && ! defined EXIT_SUCCESS
 void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
 #   endif
 #  endif
 #  ifndef YYFREE
 #   define YYFREE free
-#   if ! defined free && ! defined EXIT_SUCCESS && (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
+#   if ! defined free && ! defined EXIT_SUCCESS
 void free (void *); /* INFRINGES ON USER NAME SPACE */
 #   endif
 #  endif
@@ -369,7 +393,7 @@ void free (void *); /* INFRINGES ON USER NAME SPACE */
 
 #if (! defined yyoverflow \
      && (! defined __cplusplus \
-	 || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+         || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
 
 /* A type that is properly aligned for any stack member.  */
 union yyalloc
@@ -394,16 +418,16 @@ union yyalloc
    elements in the stack, and YYPTR gives the new location of the
    stack.  Advance YYPTR to a properly aligned location for the next
    stack.  */
-# define YYSTACK_RELOCATE(Stack_alloc, Stack)				\
-    do									\
-      {									\
-	YYSIZE_T yynewbytes;						\
-	YYCOPY (&yyptr->Stack_alloc, Stack, yysize);			\
-	Stack = &yyptr->Stack_alloc;					\
-	yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
-	yyptr += yynewbytes / sizeof (*yyptr);				\
-      }									\
-    while (YYID (0))
+# define YYSTACK_RELOCATE(Stack_alloc, Stack)                           \
+    do                                                                  \
+      {                                                                 \
+        YYSIZE_T yynewbytes;                                            \
+        YYCOPY (&yyptr->Stack_alloc, Stack, yysize);                    \
+        Stack = &yyptr->Stack_alloc;                                    \
+        yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+        yyptr += yynewbytes / sizeof (*yyptr);                          \
+      }                                                                 \
+    while (0)
 
 #endif
 
@@ -422,7 +446,7 @@ union yyalloc
           for (yyi = 0; yyi < (Count); yyi++)   \
             (Dst)[yyi] = (Src)[yyi];            \
         }                                       \
-      while (YYID (0))
+      while (0)
 #  endif
 # endif
 #endif /* !YYCOPY_NEEDED */
@@ -430,25 +454,27 @@ union yyalloc
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  11
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   298
+#define YYLAST   313
 
 /* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  40
+#define YYNTOKENS  41
 /* YYNNTS -- Number of nonterminals.  */
 #define YYNNTS  50
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  122
-/* YYNRULES -- Number of states.  */
-#define YYNSTATES  199
+#define YYNRULES  124
+/* YYNSTATES -- Number of states.  */
+#define YYNSTATES  204
 
-/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
+/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
+   by yylex, with out-of-bounds checking.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   294
+#define YYMAXUTOK   295
 
-#define YYTRANSLATE(YYX)						\
+#define YYTRANSLATE(YYX)                                                \
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
 
-/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX.  */
+/* YYTRANSLATE[TOKEN-NUM] -- Symbol number corresponding to TOKEN-NUM
+   as returned by yylex, without out-of-bounds checking.  */
 static const yytype_uint8 yytranslate[] =
 {
        0,     2,     2,     2,     2,     2,     2,     2,     2,     2,
@@ -480,90 +506,30 @@ static const yytype_uint8 yytranslate[] =
        5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
       15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
       25,    26,    27,    28,    29,    30,    31,    32,    33,    34,
-      35,    36,    37,    38,    39
+      35,    36,    37,    38,    39,    40
 };
 
 #if YYDEBUG
-/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
-   YYRHS.  */
-static const yytype_uint16 yyprhs[] =
-{
-       0,     0,     3,     6,     8,    11,    13,    14,    17,    20,
-      23,    26,    31,    36,    40,    42,    44,    46,    48,    50,
-      52,    54,    56,    58,    60,    62,    64,    66,    68,    72,
-      75,    79,    82,    86,    89,    90,    93,    96,    99,   102,
-     105,   108,   112,   117,   122,   127,   133,   137,   138,   142,
-     143,   146,   150,   153,   155,   159,   160,   163,   166,   169,
-     172,   175,   180,   184,   187,   192,   193,   196,   200,   202,
-     206,   207,   210,   213,   216,   220,   224,   228,   230,   234,
-     235,   238,   241,   244,   248,   252,   255,   258,   261,   262,
-     265,   268,   271,   276,   277,   280,   283,   286,   287,   290,
-     292,   294,   297,   300,   303,   305,   308,   309,   312,   314,
-     318,   322,   326,   330,   334,   338,   342,   345,   349,   353,
-     355,   357,   358
-};
-
-/* YYRHS -- A `-1'-separated list of the rules' RHS.  */
-static const yytype_int8 yyrhs[] =
-{
-      41,     0,    -1,    85,    42,    -1,    42,    -1,    67,    43,
-      -1,    43,    -1,    -1,    43,    45,    -1,    43,    59,    -1,
-      43,    71,    -1,    43,    84,    -1,    43,    26,     1,    35,
-      -1,    43,    44,     1,    35,    -1,    43,     1,    35,    -1,
-      16,    -1,    18,    -1,    19,    -1,    21,    -1,    17,    -1,
-      22,    -1,    20,    -1,    23,    -1,    35,    -1,    65,    -1,
-      75,    -1,    48,    -1,    50,    -1,    73,    -1,    26,     1,
-      35,    -1,     1,    35,    -1,    10,    26,    35,    -1,    47,
-      51,    -1,    11,    26,    35,    -1,    49,    51,    -1,    -1,
-      51,    52,    -1,    51,    53,    -1,    51,    79,    -1,    51,
-      77,    -1,    51,    46,    -1,    51,    35,    -1,    19,    82,
-      35,    -1,    18,    83,    86,    35,    -1,    20,    87,    86,
-      35,    -1,    21,    26,    86,    35,    -1,    22,    88,    88,
-      86,    35,    -1,    24,    54,    35,    -1,    -1,    54,    26,
-      55,    -1,    -1,    38,    83,    -1,     7,    89,    35,    -1,
-      56,    60,    -1,    84,    -1,    57,    62,    58,    -1,    -1,
-      60,    61,    -1,    60,    79,    -1,    60,    77,    -1,    60,
-      35,    -1,    60,    46,    -1,    18,    83,    86,    35,    -1,
-      19,    82,    35,    -1,    17,    35,    -1,    20,    26,    86,
-      35,    -1,    -1,    62,    45,    -1,    14,    87,    85,    -1,
-      84,    -1,    63,    66,    64,    -1,    -1,    66,    45,    -1,
-      66,    71,    -1,    66,    59,    -1,     3,    83,    85,    -1,
-       4,    83,    35,    -1,    68,    80,    78,    -1,    84,    -1,
-      69,    72,    70,    -1,    -1,    72,    45,    -1,    72,    71,
-      -1,    72,    59,    -1,     6,    83,    35,    -1,     9,    83,
-      35,    -1,    74,    78,    -1,    12,    35,    -1,    76,    13,
-      -1,    -1,    78,    79,    -1,    78,    35,    -1,    78,    46,
-      -1,    16,    25,    87,    35,    -1,    -1,    80,    81,    -1,
-      80,    35,    -1,    23,    86,    -1,    -1,    83,    86,    -1,
-      26,    -1,    27,    -1,     5,    35,    -1,     8,    35,    -1,
-      15,    35,    -1,    35,    -1,    85,    35,    -1,    -1,    14,
-      87,    -1,    88,    -1,    88,    29,    88,    -1,    88,    30,
-      88,    -1,    88,    31,    88,    -1,    88,    32,    88,    -1,
-      88,    38,    88,    -1,    88,    28,    88,    -1,    34,    87,
-      33,    -1,    39,    87,    -1,    87,    36,    87,    -1,    87,
-      37,    87,    -1,    26,    -1,    27,    -1,    -1,    26,    -1
-};
-
-/* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
+  /* YYRLINE[YYN] -- Source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   108,   108,   108,   110,   110,   112,   114,   115,   116,
-     117,   118,   119,   123,   127,   127,   127,   127,   127,   127,
-     127,   127,   131,   132,   133,   134,   135,   136,   140,   141,
-     147,   155,   161,   169,   179,   181,   182,   183,   184,   185,
-     186,   189,   197,   203,   213,   219,   225,   228,   230,   241,
-     242,   247,   256,   261,   269,   272,   274,   275,   276,   277,
-     278,   281,   287,   298,   304,   314,   316,   321,   329,   337,
-     340,   342,   343,   344,   349,   356,   363,   368,   376,   379,
-     381,   382,   383,   386,   394,   401,   408,   414,   421,   423,
-     424,   425,   428,   436,   438,   439,   442,   449,   451,   456,
-     457,   460,   461,   462,   466,   467,   470,   471,   474,   475,
-     476,   477,   478,   479,   480,   481,   482,   483,   484,   487,
-     488,   491,   492
+       0,   109,   109,   109,   111,   111,   113,   115,   116,   117,
+     118,   119,   120,   124,   128,   128,   128,   128,   128,   128,
+     128,   128,   128,   132,   133,   134,   135,   136,   137,   141,
+     142,   148,   156,   162,   170,   180,   182,   183,   184,   185,
+     186,   187,   190,   198,   204,   214,   220,   226,   232,   235,
+     237,   248,   249,   254,   263,   268,   276,   279,   281,   282,
+     283,   284,   285,   288,   294,   305,   311,   321,   323,   328,
+     336,   344,   347,   349,   350,   351,   356,   363,   370,   375,
+     383,   386,   388,   389,   390,   393,   401,   408,   415,   421,
+     428,   430,   431,   432,   435,   443,   445,   446,   449,   456,
+     458,   463,   464,   467,   468,   469,   473,   474,   477,   478,
+     481,   482,   483,   484,   485,   486,   487,   488,   489,   490,
+     491,   494,   495,   498,   499
 };
 #endif
 
-#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+#if YYDEBUG || YYERROR_VERBOSE || 0
 /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
    First, the terminals, then, starting at YYNTOKENS, nonterminals.  */
 static const char *const yytname[] =
@@ -574,271 +540,268 @@ static const char *const yytname[] =
   "T_OPTIONAL", "T_PROMPT", "T_TYPE", "T_DEFAULT", "T_SELECT", "T_RANGE",
   "T_VISIBLE", "T_OPTION", "T_ON", "T_WORD", "T_WORD_QUOTE", "T_UNEQUAL",
   "T_LESS", "T_LESS_EQUAL", "T_GREATER", "T_GREATER_EQUAL",
-  "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_EOL", "T_OR", "T_AND", "T_EQUAL",
-  "T_NOT", "$accept", "input", "start", "stmt_list", "option_name",
-  "common_stmt", "option_error", "config_entry_start", "config_stmt",
-  "menuconfig_entry_start", "menuconfig_stmt", "config_option_list",
-  "config_option", "symbol_option", "symbol_option_list",
-  "symbol_option_arg", "choice", "choice_entry", "choice_end",
-  "choice_stmt", "choice_option_list", "choice_option", "choice_block",
-  "if_entry", "if_end", "if_stmt", "if_block", "mainmenu_stmt", "menu",
-  "menu_entry", "menu_end", "menu_stmt", "menu_block", "source_stmt",
-  "comment", "comment_stmt", "help_start", "help", "depends_list",
-  "depends", "visibility_list", "visible", "prompt_stmt_opt", "prompt",
-  "end", "nl", "if_expr", "expr", "symbol", "word_opt", YY_NULL
+  "T_CLOSE_PAREN", "T_OPEN_PAREN", "T_EOL", "T_COUNT", "T_OR", "T_AND",
+  "T_EQUAL", "T_NOT", "$accept", "input", "start", "stmt_list",
+  "option_name", "common_stmt", "option_error", "config_entry_start",
+  "config_stmt", "menuconfig_entry_start", "menuconfig_stmt",
+  "config_option_list", "config_option", "symbol_option",
+  "symbol_option_list", "symbol_option_arg", "choice", "choice_entry",
+  "choice_end", "choice_stmt", "choice_option_list", "choice_option",
+  "choice_block", "if_entry", "if_end", "if_stmt", "if_block",
+  "mainmenu_stmt", "menu", "menu_entry", "menu_end", "menu_stmt",
+  "menu_block", "source_stmt", "comment", "comment_stmt", "help_start",
+  "help", "depends_list", "depends", "visibility_list", "visible",
+  "prompt_stmt_opt", "prompt", "end", "nl", "if_expr", "expr", "symbol",
+  "word_opt", YY_NULLPTR
 };
 #endif
 
 # ifdef YYPRINT
-/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
-   token YYLEX-NUM.  */
+/* YYTOKNUM[NUM] -- (External) token number corresponding to the
+   (internal) symbol number NUM (which must be that of a token).  */
 static const yytype_uint16 yytoknum[] =
 {
        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
      265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
      275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
-     285,   286,   287,   288,   289,   290,   291,   292,   293,   294
+     285,   286,   287,   288,   289,   290,   291,   292,   293,   294,
+     295
 };
 # endif
 
-/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
-static const yytype_uint8 yyr1[] =
-{
-       0,    40,    41,    41,    42,    42,    43,    43,    43,    43,
-      43,    43,    43,    43,    44,    44,    44,    44,    44,    44,
-      44,    44,    45,    45,    45,    45,    45,    45,    46,    46,
-      47,    48,    49,    50,    51,    51,    51,    51,    51,    51,
-      51,    52,    52,    52,    52,    52,    53,    54,    54,    55,
-      55,    56,    57,    58,    59,    60,    60,    60,    60,    60,
-      60,    61,    61,    61,    61,    62,    62,    63,    64,    65,
-      66,    66,    66,    66,    67,    68,    69,    70,    71,    72,
-      72,    72,    72,    73,    74,    75,    76,    77,    78,    78,
-      78,    78,    79,    80,    80,    80,    81,    82,    82,    83,
-      83,    84,    84,    84,    85,    85,    86,    86,    87,    87,
-      87,    87,    87,    87,    87,    87,    87,    87,    87,    88,
-      88,    89,    89
-};
+#define YYPACT_NINF -92
 
-/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
-static const yytype_uint8 yyr2[] =
-{
-       0,     2,     2,     1,     2,     1,     0,     2,     2,     2,
-       2,     4,     4,     3,     1,     1,     1,     1,     1,     1,
-       1,     1,     1,     1,     1,     1,     1,     1,     3,     2,
-       3,     2,     3,     2,     0,     2,     2,     2,     2,     2,
-       2,     3,     4,     4,     4,     5,     3,     0,     3,     0,
-       2,     3,     2,     1,     3,     0,     2,     2,     2,     2,
-       2,     4,     3,     2,     4,     0,     2,     3,     1,     3,
-       0,     2,     2,     2,     3,     3,     3,     1,     3,     0,
-       2,     2,     2,     3,     3,     2,     2,     2,     0,     2,
-       2,     2,     4,     0,     2,     2,     2,     0,     2,     1,
-       1,     2,     2,     2,     1,     2,     0,     2,     1,     3,
-       3,     3,     3,     3,     3,     3,     2,     3,     3,     1,
-       1,     0,     1
-};
+#define yypact_value_is_default(Yystate) \
+  (!!((Yystate) == (-92)))
 
-/* YYDEFACT[STATE-NAME] -- Default reduction number in state STATE-NUM.
-   Performed when YYTABLE doesn't specify something else to do.  Zero
-   means the default is an error.  */
-static const yytype_uint8 yydefact[] =
+#define YYTABLE_NINF -88
+
+#define yytable_value_is_error(Yytable_value) \
+  0
+
+  /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+     STATE-NUM.  */
+static const yytype_int16 yypact[] =
 {
-       6,     0,   104,     0,     3,     0,     6,     6,    99,   100,
-       0,     1,     0,     0,     0,     0,   121,     0,     0,     0,
-       0,     0,     0,    14,    18,    15,    16,    20,    17,    19,
-      21,     0,    22,     0,     7,    34,    25,    34,    26,    55,
-      65,     8,    70,    23,    93,    79,     9,    27,    88,    24,
-      10,     0,   105,     2,    74,    13,     0,   101,     0,   122,
-       0,   102,     0,     0,     0,   119,   120,     0,     0,     0,
-     108,   103,     0,     0,     0,     0,     0,     0,     0,    88,
-       0,     0,    75,    83,    51,    84,    30,    32,     0,   116,
-       0,     0,    67,     0,     0,     0,     0,     0,     0,    11,
-      12,     0,     0,     0,     0,    97,     0,     0,     0,    47,
-       0,    40,    39,    35,    36,     0,    38,    37,     0,     0,
-      97,     0,    59,    60,    56,    58,    57,    66,    54,    53,
-      71,    73,    69,    72,    68,   106,    95,     0,    94,    80,
-      82,    78,    81,    77,    90,    91,    89,   115,   117,   118,
-     114,   109,   110,   111,   112,   113,    29,    86,     0,   106,
-       0,   106,   106,   106,     0,     0,     0,    87,    63,   106,
-       0,   106,     0,    96,     0,     0,    41,    98,     0,     0,
-     106,    49,    46,    28,     0,    62,     0,   107,    92,    42,
-      43,    44,     0,     0,    48,    61,    64,    45,    50
+      19,     3,   -92,    13,   -92,    80,   -92,    20,   -92,   -92,
+     -16,   -92,    -9,     3,    21,     3,    34,    37,     3,    50,
+      79,    31,    57,   -92,   -92,   -92,   -92,   -92,   -92,   -92,
+     -92,   112,   -92,   -92,   118,   -92,   -92,   -92,   -92,   -92,
+     -92,   -92,   -92,   -92,   -92,   -92,   -92,   -92,   -92,   -92,
+     -92,   -92,   150,   -92,   -92,    95,   -92,   107,   -92,   114,
+     -92,   139,   -92,   143,   144,   145,   -92,   -92,    31,    31,
+      29,   274,   -92,   146,   147,    27,   117,   215,   266,   251,
+     -14,   251,   183,   -92,   -92,   -92,   -92,   -92,   -92,    41,
+     -92,    31,    31,    95,    42,    42,    42,    42,    42,    42,
+     -92,   -92,   160,   172,   185,     3,     3,    31,   182,    42,
+     -92,   210,   -92,   186,   -92,   -92,   -92,   200,   -92,   -92,
+     179,     3,     3,   189,   -92,   -92,   -92,   -92,   -92,   -92,
+     -92,   -92,   -92,   -92,   -92,   -92,   -92,   203,   -92,   238,
+     -92,   -92,   -92,   -92,   -92,   -92,   -92,   -92,   -92,   -92,
+     184,   -92,   -92,   -92,   -92,   -92,   -92,   -92,   -92,   -92,
+      31,   203,   193,   203,    45,   203,    42,    26,   201,   203,
+     -92,   -92,   203,   202,   203,    31,   -92,    72,   205,   -92,
+     -92,   216,   228,   203,   199,   -92,   -92,   232,   233,   -92,
+     234,   125,   -92,   -92,   -92,   -92,   235,     3,   -92,   -92,
+     -92,   -92,   -92,   -92
 };
 
-/* YYDEFGOTO[NTERM-NUM].  */
-static const yytype_int16 yydefgoto[] =
+  /* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
+     Performed when YYTABLE does not specify something else to do.  Zero
+     means the default is an error.  */
+static const yytype_uint8 yydefact[] =
 {
-      -1,     3,     4,     5,    33,    34,   112,    35,    36,    37,
-      38,    74,   113,   114,   165,   194,    39,    40,   128,    41,
-      76,   124,    77,    42,   132,    43,    78,     6,    44,    45,
-     141,    46,    80,    47,    48,    49,   115,   116,    81,   117,
-      79,   138,   160,   161,    50,     7,   173,    69,    70,    60
+       6,     0,   106,     0,     3,     0,     6,     6,   101,   102,
+       0,     1,     0,     0,     0,     0,   123,     0,     0,     0,
+       0,     0,     0,    14,    19,    15,    16,    21,    17,    20,
+      22,     0,    23,    18,     0,     7,    35,    26,    35,    27,
+      57,    67,     8,    72,    24,    95,    81,     9,    28,    90,
+      25,    10,     0,   107,     2,    76,    13,     0,   103,     0,
+     124,     0,   104,     0,     0,     0,   121,   122,     0,     0,
+       0,   110,   105,     0,     0,     0,     0,     0,     0,     0,
+      90,     0,     0,    77,    85,    53,    86,    31,    33,     0,
+     118,     0,     0,    69,     0,     0,     0,     0,     0,     0,
+      11,    12,     0,     0,     0,     0,    99,     0,     0,     0,
+      49,     0,    41,     0,    40,    36,    37,     0,    39,    38,
+       0,     0,    99,     0,    61,    62,    58,    60,    59,    68,
+      56,    55,    73,    75,    71,    74,    70,   108,    97,     0,
+      96,    82,    84,    80,    83,    79,    92,    93,    91,   117,
+     119,   120,   116,   111,   112,   113,   114,   115,    30,    88,
+       0,   108,     0,   108,   108,   108,     0,     0,     0,   108,
+      89,    65,   108,     0,   108,     0,    98,     0,     0,    42,
+     100,     0,     0,   108,    51,    48,    29,     0,     0,    64,
+       0,   109,    94,    43,    44,    45,     0,     0,    50,    46,
+      63,    66,    47,    52
 };
 
-/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
-   STATE-NUM.  */
-#define YYPACT_NINF -91
-static const yytype_int16 yypact[] =
+  /* YYPGOTO[NTERM-NUM].  */
+static const yytype_int16 yypgoto[] =
 {
-      19,    37,   -91,    13,   -91,    79,   -91,    20,   -91,   -91,
-     -16,   -91,    21,    37,    25,    37,    41,    36,    37,    78,
-      83,    31,    56,   -91,   -91,   -91,   -91,   -91,   -91,   -91,
-     -91,   116,   -91,   127,   -91,   -91,   -91,   -91,   -91,   -91,
-     -91,   -91,   -91,   -91,   -91,   -91,   -91,   -91,   -91,   -91,
-     -91,   147,   -91,   -91,   105,   -91,   109,   -91,   111,   -91,
-     114,   -91,   136,   137,   142,   -91,   -91,    31,    31,    76,
-     254,   -91,   143,   146,    27,   115,   207,   258,   243,   -14,
-     243,   179,   -91,   -91,   -91,   -91,   -91,   -91,    -7,   -91,
-      31,    31,   105,    51,    51,    51,    51,    51,    51,   -91,
-     -91,   156,   168,   181,    37,    37,    31,   178,    51,   -91,
-     206,   -91,   -91,   -91,   -91,   196,   -91,   -91,   175,    37,
-      37,   185,   -91,   -91,   -91,   -91,   -91,   -91,   -91,   -91,
-     -91,   -91,   -91,   -91,   -91,   214,   -91,   230,   -91,   -91,
-     -91,   -91,   -91,   -91,   -91,   -91,   -91,   -91,   183,   -91,
-     -91,   -91,   -91,   -91,   -91,   -91,   -91,   -91,    31,   214,
-     194,   214,    45,   214,    51,    26,   195,   -91,   -91,   214,
-     197,   214,    31,   -91,   139,   208,   -91,   -91,   220,   224,
-     214,   222,   -91,   -91,   226,   -91,   227,   123,   -91,   -91,
-     -91,   -91,   235,    37,   -91,   -91,   -91,   -91,   -91
+     -92,   -92,   271,   273,   -92,    33,   -66,   -92,   -92,   -92,
+     -92,   244,   -92,   -92,   -92,   -92,   -92,   -92,   -92,    67,
+     -92,   -92,   -92,   -92,   -92,   -92,   -92,   -92,   -92,   -92,
+     -92,    96,   -92,   -92,   -92,   -92,   -92,   206,   204,   -62,
+     -92,   -92,   168,    -1,    66,     0,   124,   -67,   -91,   -92
 };
 
-/* YYPGOTO[NTERM-NUM].  */
-static const yytype_int16 yypgoto[] =
+  /* YYDEFGOTO[NTERM-NUM].  */
+static const yytype_int16 yydefgoto[] =
 {
-     -91,   -91,   264,   268,   -91,    30,   -65,   -91,   -91,   -91,
-     -91,   238,   -91,   -91,   -91,   -91,   -91,   -91,   -91,   -12,
-     -91,   -91,   -91,   -91,   -91,   -91,   -91,   -91,   -91,   -91,
-     -91,    -5,   -91,   -91,   -91,   -91,   -91,   200,   209,   -61,
-     -91,   -91,   170,    -1,    65,     0,   118,   -66,   -90,   -91
+      -1,     3,     4,     5,    34,    35,   114,    36,    37,    38,
+      39,    75,   115,   116,   167,   198,    40,    41,   130,    42,
+      77,   126,    78,    43,   134,    44,    79,     6,    45,    46,
+     143,    47,    81,    48,    49,    50,   117,   118,    82,   119,
+      80,   140,   162,   163,    51,     7,   176,    70,    71,    61
 };
 
-/* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
-   positive, shift that token.  If negative, reduce the rule which
-   number is the opposite.  If YYTABLE_NINF, syntax error.  */
-#define YYTABLE_NINF -86
+  /* YYTABLE[YYPACT[STATE-NUM]] -- What to do in state STATE-NUM.  If
+     positive, shift that token.  If negative, reduce the rule whose
+     number is the opposite.  If YYTABLE_NINF, syntax error.  */
 static const yytype_int16 yytable[] =
 {
-      10,    88,    89,   150,   151,   152,   153,   154,   155,   135,
-      54,   123,    56,    11,    58,   126,   145,    62,   164,     2,
-     146,   136,     1,     1,   148,   149,   147,   -31,   101,    90,
-      91,   -31,   -31,   -31,   -31,   -31,   -31,   -31,   -31,   102,
-     162,   -31,   -31,   103,   -31,   104,   105,   106,   107,   108,
-     -31,   109,   181,   110,     2,    52,    55,    65,    66,   172,
-      57,   182,   111,     8,     9,    67,   131,    59,   140,    92,
-      68,    61,   145,   133,   180,   142,   146,    65,    66,    -5,
-      12,    90,    91,    13,    14,    15,    16,    17,    18,    19,
-      20,    71,   174,    21,    22,    23,    24,    25,    26,    27,
-      28,    29,    30,   159,    63,    31,   187,   127,   130,    64,
-     139,     2,    90,    91,    32,   -33,   101,    72,   169,   -33,
-     -33,   -33,   -33,   -33,   -33,   -33,   -33,   102,    73,   -33,
-     -33,   103,   -33,   104,   105,   106,   107,   108,   -33,   109,
-      52,   110,   129,   134,    82,   143,    83,    -4,    12,    84,
-     111,    13,    14,    15,    16,    17,    18,    19,    20,    90,
-      91,    21,    22,    23,    24,    25,    26,    27,    28,    29,
-      30,    85,    86,    31,   188,    90,    91,    87,    99,   -85,
-     101,   100,    32,   -85,   -85,   -85,   -85,   -85,   -85,   -85,
-     -85,   156,   198,   -85,   -85,   103,   -85,   -85,   -85,   -85,
-     -85,   -85,   -85,   157,   163,   110,   158,   166,   101,   167,
-     168,   171,   -52,   -52,   144,   -52,   -52,   -52,   -52,   102,
-      91,   -52,   -52,   103,   118,   119,   120,   121,   172,   176,
-     183,   101,   185,   110,   -76,   -76,   -76,   -76,   -76,   -76,
-     -76,   -76,   122,   189,   -76,   -76,   103,    13,    14,    15,
-      16,    17,    18,    19,    20,   190,   110,    21,    22,   191,
-     193,   195,   196,    14,    15,   144,    17,    18,    19,    20,
-     197,    53,    21,    22,    51,    75,   125,   175,    32,   177,
-     178,   179,    93,    94,    95,    96,    97,   184,   137,   186,
-     170,     0,    98,    32,     0,     0,     0,     0,   192
+      10,    89,    90,   152,   153,   154,   155,   156,   157,   137,
+      55,   125,    57,    11,    59,   128,   147,    63,   166,     2,
+     148,   138,     1,     1,   150,   151,    56,   -32,   102,     8,
+       9,   -32,   -32,   -32,   -32,   -32,   -32,   -32,   -32,   103,
+     164,   -32,   -32,   104,   -32,   105,   106,   107,   108,   109,
+     -32,   110,   184,   111,     2,    53,    58,    66,    67,   175,
+      60,   185,   112,   113,     2,    68,    91,    92,    66,    67,
+      93,    69,    62,   147,   149,   183,    64,   148,    91,    92,
+      -5,    12,    91,    92,    13,    14,    15,    16,    17,    18,
+      19,    20,    72,   177,    21,    22,    23,    24,    25,    26,
+      27,    28,    29,    30,   161,    65,    31,   192,   191,    91,
+      92,   129,   132,    73,   141,    32,    33,   -34,   102,    74,
+     172,   -34,   -34,   -34,   -34,   -34,   -34,   -34,   -34,   103,
+      53,   -34,   -34,   104,   -34,   105,   106,   107,   108,   109,
+     -34,   110,    83,   111,   131,   136,   133,   145,   142,    84,
+      -4,    12,   112,   113,    13,    14,    15,    16,    17,    18,
+      19,    20,    91,    92,    21,    22,    23,    24,    25,    26,
+      27,    28,    29,    30,    85,   135,    31,   144,    86,    87,
+      88,   100,   101,   -87,   102,    32,    33,   -87,   -87,   -87,
+     -87,   -87,   -87,   -87,   -87,   158,   203,   -87,   -87,   104,
+     -87,   -87,   -87,   -87,   -87,   -87,   -87,   159,   165,   111,
+     160,   168,   169,   170,   171,   174,   102,   175,   146,   -87,
+     -54,   -54,    92,   -54,   -54,   -54,   -54,   103,   179,   -54,
+     -54,   104,   120,   121,   122,   123,   186,   189,   197,   102,
+     193,   111,   -78,   -78,   -78,   -78,   -78,   -78,   -78,   -78,
+     124,   194,   -78,   -78,   104,    13,    14,    15,    16,    17,
+      18,    19,    20,   195,   111,    21,    22,   199,   200,   201,
+     202,    14,    15,   146,    17,    18,    19,    20,    54,    52,
+      21,    22,    76,   127,   139,   178,    32,   180,   181,   182,
+     173,     0,     0,   187,     0,     0,   188,     0,   190,     0,
+       0,    32,    94,    95,    96,    97,    98,   196,     0,     0,
+       0,     0,     0,    99
 };
 
-#define yypact_value_is_default(yystate) \
-  ((yystate) == (-91))
-
-#define yytable_value_is_error(yytable_value) \
-  YYID (0)
-
 static const yytype_int16 yycheck[] =
 {
-       1,    67,    68,    93,    94,    95,    96,    97,    98,    23,
-      10,    76,    13,     0,    15,    76,    81,    18,   108,    35,
-      81,    35,     3,     3,    90,    91,    33,     0,     1,    36,
-      37,     4,     5,     6,     7,     8,     9,    10,    11,    12,
-     106,    14,    15,    16,    17,    18,    19,    20,    21,    22,
+       1,    68,    69,    94,    95,    96,    97,    98,    99,    23,
+      10,    77,    13,     0,    15,    77,    82,    18,   109,    35,
+      82,    35,     3,     3,    91,    92,    35,     0,     1,    26,
+      27,     4,     5,     6,     7,     8,     9,    10,    11,    12,
+     107,    14,    15,    16,    17,    18,    19,    20,    21,    22,
       23,    24,    26,    26,    35,    35,    35,    26,    27,    14,
-      35,    35,    35,    26,    27,    34,    78,    26,    80,    69,
-      39,    35,   137,    78,   164,    80,   137,    26,    27,     0,
-       1,    36,    37,     4,     5,     6,     7,     8,     9,    10,
-      11,    35,   158,    14,    15,    16,    17,    18,    19,    20,
-      21,    22,    23,   104,    26,    26,   172,    77,    78,    26,
-      80,    35,    36,    37,    35,     0,     1,     1,   119,     4,
-       5,     6,     7,     8,     9,    10,    11,    12,     1,    14,
-      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-      35,    26,    77,    78,    35,    80,    35,     0,     1,    35,
-      35,     4,     5,     6,     7,     8,     9,    10,    11,    36,
-      37,    14,    15,    16,    17,    18,    19,    20,    21,    22,
-      23,    35,    35,    26,    35,    36,    37,    35,    35,     0,
-       1,    35,    35,     4,     5,     6,     7,     8,     9,    10,
-      11,    35,   193,    14,    15,    16,    17,    18,    19,    20,
-      21,    22,    23,    35,    26,    26,    25,     1,     1,    13,
-      35,    26,     5,     6,    35,     8,     9,    10,    11,    12,
-      37,    14,    15,    16,    17,    18,    19,    20,    14,    35,
-      35,     1,    35,    26,     4,     5,     6,     7,     8,     9,
-      10,    11,    35,    35,    14,    15,    16,     4,     5,     6,
-       7,     8,     9,    10,    11,    35,    26,    14,    15,    35,
-      38,    35,    35,     5,     6,    35,     8,     9,    10,    11,
-      35,     7,    14,    15,     6,    37,    76,   159,    35,   161,
-     162,   163,    28,    29,    30,    31,    32,   169,    79,   171,
-     120,    -1,    38,    35,    -1,    -1,    -1,    -1,   180
+      26,    35,    35,    36,    35,    34,    37,    38,    26,    27,
+      70,    40,    35,   139,    33,   166,    26,   139,    37,    38,
+       0,     1,    37,    38,     4,     5,     6,     7,     8,     9,
+      10,    11,    35,   160,    14,    15,    16,    17,    18,    19,
+      20,    21,    22,    23,   105,    26,    26,    35,   175,    37,
+      38,    78,    79,     1,    81,    35,    36,     0,     1,     1,
+     121,     4,     5,     6,     7,     8,     9,    10,    11,    12,
+      35,    14,    15,    16,    17,    18,    19,    20,    21,    22,
+      23,    24,    35,    26,    78,    79,    79,    81,    81,    35,
+       0,     1,    35,    36,     4,     5,     6,     7,     8,     9,
+      10,    11,    37,    38,    14,    15,    16,    17,    18,    19,
+      20,    21,    22,    23,    35,    79,    26,    81,    35,    35,
+      35,    35,    35,     0,     1,    35,    36,     4,     5,     6,
+       7,     8,     9,    10,    11,    35,   197,    14,    15,    16,
+      17,    18,    19,    20,    21,    22,    23,    35,    26,    26,
+      25,     1,    26,    13,    35,    26,     1,    14,    35,    36,
+       5,     6,    38,     8,     9,    10,    11,    12,    35,    14,
+      15,    16,    17,    18,    19,    20,    35,    35,    39,     1,
+      35,    26,     4,     5,     6,     7,     8,     9,    10,    11,
+      35,    35,    14,    15,    16,     4,     5,     6,     7,     8,
+       9,    10,    11,    35,    26,    14,    15,    35,    35,    35,
+      35,     5,     6,    35,     8,     9,    10,    11,     7,     6,
+      14,    15,    38,    77,    80,   161,    35,   163,   164,   165,
+     122,    -1,    -1,   169,    -1,    -1,   172,    -1,   174,    -1,
+      -1,    35,    28,    29,    30,    31,    32,   183,    -1,    -1,
+      -1,    -1,    -1,    39
 };
 
-/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
-   symbol of state STATE-NUM.  */
+  /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+     symbol of state STATE-NUM.  */
 static const yytype_uint8 yystos[] =
 {
-       0,     3,    35,    41,    42,    43,    67,    85,    26,    27,
-      83,     0,     1,     4,     5,     6,     7,     8,     9,    10,
+       0,     3,    35,    42,    43,    44,    68,    86,    26,    27,
+      84,     0,     1,     4,     5,     6,     7,     8,     9,    10,
       11,    14,    15,    16,    17,    18,    19,    20,    21,    22,
-      23,    26,    35,    44,    45,    47,    48,    49,    50,    56,
-      57,    59,    63,    65,    68,    69,    71,    73,    74,    75,
-      84,    43,    35,    42,    85,    35,    83,    35,    83,    26,
-      89,    35,    83,    26,    26,    26,    27,    34,    39,    87,
-      88,    35,     1,     1,    51,    51,    60,    62,    66,    80,
-      72,    78,    35,    35,    35,    35,    35,    35,    87,    87,
-      36,    37,    85,    28,    29,    30,    31,    32,    38,    35,
-      35,     1,    12,    16,    18,    19,    20,    21,    22,    24,
-      26,    35,    46,    52,    53,    76,    77,    79,    17,    18,
-      19,    20,    35,    46,    61,    77,    79,    45,    58,    84,
-      45,    59,    64,    71,    84,    23,    35,    78,    81,    45,
-      59,    70,    71,    84,    35,    46,    79,    33,    87,    87,
-      88,    88,    88,    88,    88,    88,    35,    35,    25,    83,
-      82,    83,    87,    26,    88,    54,     1,    13,    35,    83,
-      82,    26,    14,    86,    87,    86,    35,    86,    86,    86,
-      88,    26,    35,    35,    86,    35,    86,    87,    35,    35,
-      35,    35,    86,    38,    55,    35,    35,    35,    83
+      23,    26,    35,    36,    45,    46,    48,    49,    50,    51,
+      57,    58,    60,    64,    66,    69,    70,    72,    74,    75,
+      76,    85,    44,    35,    43,    86,    35,    84,    35,    84,
+      26,    90,    35,    84,    26,    26,    26,    27,    34,    40,
+      88,    89,    35,     1,     1,    52,    52,    61,    63,    67,
+      81,    73,    79,    35,    35,    35,    35,    35,    35,    88,
+      88,    37,    38,    86,    28,    29,    30,    31,    32,    39,
+      35,    35,     1,    12,    16,    18,    19,    20,    21,    22,
+      24,    26,    35,    36,    47,    53,    54,    77,    78,    80,
+      17,    18,    19,    20,    35,    47,    62,    78,    80,    46,
+      59,    85,    46,    60,    65,    72,    85,    23,    35,    79,
+      82,    46,    60,    71,    72,    85,    35,    47,    80,    33,
+      88,    88,    89,    89,    89,    89,    89,    89,    35,    35,
+      25,    84,    83,    84,    88,    26,    89,    55,     1,    26,
+      13,    35,    84,    83,    26,    14,    87,    88,    87,    35,
+      87,    87,    87,    89,    26,    35,    35,    87,    87,    35,
+      87,    88,    35,    35,    35,    35,    87,    39,    56,    35,
+      35,    35,    35,    84
 };
 
-#define yyerrok		(yyerrstatus = 0)
-#define yyclearin	(yychar = YYEMPTY)
-#define YYEMPTY		(-2)
-#define YYEOF		0
-
-#define YYACCEPT	goto yyacceptlab
-#define YYABORT		goto yyabortlab
-#define YYERROR		goto yyerrorlab
-
-
-/* Like YYERROR except do call yyerror.  This remains here temporarily
-   to ease the transition to the new meaning of YYERROR, for GCC.
-   Once GCC version 2 has supplanted version 1, this can go.  However,
-   YYFAIL appears to be in use.  Nevertheless, it is formally deprecated
-   in Bison 2.4.2's NEWS entry, where a plan to phase it out is
-   discussed.  */
-
-#define YYFAIL		goto yyerrlab
-#if defined YYFAIL
-  /* This is here to suppress warnings from the GCC cpp's
-     -Wunused-macros.  Normally we don't worry about that warning, but
-     some users do, and we want to make it easy for users to remove
-     YYFAIL uses, which will produce warnings from Bison 2.5.  */
-#endif
+  /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
+static const yytype_uint8 yyr1[] =
+{
+       0,    41,    42,    42,    43,    43,    44,    44,    44,    44,
+      44,    44,    44,    44,    45,    45,    45,    45,    45,    45,
+      45,    45,    45,    46,    46,    46,    46,    46,    46,    47,
+      47,    48,    49,    50,    51,    52,    52,    52,    52,    52,
+      52,    52,    53,    53,    53,    53,    53,    53,    54,    55,
+      55,    56,    56,    57,    58,    59,    60,    61,    61,    61,
+      61,    61,    61,    62,    62,    62,    62,    63,    63,    64,
+      65,    66,    67,    67,    67,    67,    68,    69,    70,    71,
+      72,    73,    73,    73,    73,    74,    75,    76,    77,    78,
+      79,    79,    79,    79,    80,    81,    81,    81,    82,    83,
+      83,    84,    84,    85,    85,    85,    86,    86,    87,    87,
+      88,    88,    88,    88,    88,    88,    88,    88,    88,    88,
+      88,    89,    89,    90,    90
+};
+
+  /* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN.  */
+static const yytype_uint8 yyr2[] =
+{
+       0,     2,     2,     1,     2,     1,     0,     2,     2,     2,
+       2,     4,     4,     3,     1,     1,     1,     1,     1,     1,
+       1,     1,     1,     1,     1,     1,     1,     1,     1,     3,
+       2,     3,     2,     3,     2,     0,     2,     2,     2,     2,
+       2,     2,     3,     4,     4,     4,     4,     5,     3,     0,
+       3,     0,     2,     3,     2,     1,     3,     0,     2,     2,
+       2,     2,     2,     4,     3,     2,     4,     0,     2,     3,
+       1,     3,     0,     2,     2,     2,     3,     3,     3,     1,
+       3,     0,     2,     2,     2,     3,     3,     2,     2,     2,
+       0,     2,     2,     2,     4,     0,     2,     2,     2,     0,
+       2,     1,     1,     2,     2,     2,     1,     2,     0,     2,
+       1,     3,     3,     3,     3,     3,     3,     3,     2,     3,
+       3,     1,     1,     0,     1
+};
+
+
+#define yyerrok         (yyerrstatus = 0)
+#define yyclearin       (yychar = YYEMPTY)
+#define YYEMPTY         (-2)
+#define YYEOF           0
+
+#define YYACCEPT        goto yyacceptlab
+#define YYABORT         goto yyabortlab
+#define YYERROR         goto yyerrorlab
+
 
 #define YYRECOVERING()  (!!yyerrstatus)
 
@@ -855,55 +818,15 @@ do                                                              \
   else                                                          \
     {                                                           \
       yyerror (YY_("syntax error: cannot back up")); \
-      YYERROR;							\
-    }								\
-while (YYID (0))
-
-
-#define YYTERROR	1
-#define YYERRCODE	256
-
-
-/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
-   If N is 0, then set CURRENT to the empty location which ends
-   the previous symbol: RHS[0] (always defined).  */
-
-#define YYRHSLOC(Rhs, K) ((Rhs)[K])
-#ifndef YYLLOC_DEFAULT
-# define YYLLOC_DEFAULT(Current, Rhs, N)				\
-    do									\
-      if (YYID (N))                                                    \
-	{								\
-	  (Current).first_line   = YYRHSLOC (Rhs, 1).first_line;	\
-	  (Current).first_column = YYRHSLOC (Rhs, 1).first_column;	\
-	  (Current).last_line    = YYRHSLOC (Rhs, N).last_line;		\
-	  (Current).last_column  = YYRHSLOC (Rhs, N).last_column;	\
-	}								\
-      else								\
-	{								\
-	  (Current).first_line   = (Current).last_line   =		\
-	    YYRHSLOC (Rhs, 0).last_line;				\
-	  (Current).first_column = (Current).last_column =		\
-	    YYRHSLOC (Rhs, 0).last_column;				\
-	}								\
-    while (YYID (0))
-#endif
-
-
-/* This macro is provided for backward compatibility. */
-
-#ifndef YY_LOCATION_PRINT
-# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
-#endif
+      YYERROR;                                                  \
+    }                                                           \
+while (0)
 
+/* Error token number */
+#define YYTERROR        1
+#define YYERRCODE       256
 
-/* YYLEX -- calling `yylex' with the right arguments.  */
 
-#ifdef YYLEX_PARAM
-# define YYLEX yylex (YYLEX_PARAM)
-#else
-# define YYLEX yylex ()
-#endif
 
 /* Enable debugging if requested.  */
 #if YYDEBUG
@@ -913,40 +836,36 @@ while (YYID (0))
 #  define YYFPRINTF fprintf
 # endif
 
-# define YYDPRINTF(Args)			\
-do {						\
-  if (yydebug)					\
-    YYFPRINTF Args;				\
-} while (YYID (0))
+# define YYDPRINTF(Args)                        \
+do {                                            \
+  if (yydebug)                                  \
+    YYFPRINTF Args;                             \
+} while (0)
 
-# define YY_SYMBOL_PRINT(Title, Type, Value, Location)			  \
-do {									  \
-  if (yydebug)								  \
-    {									  \
-      YYFPRINTF (stderr, "%s ", Title);					  \
-      yy_symbol_print (stderr,						  \
-		  Type, Value); \
-      YYFPRINTF (stderr, "\n");						  \
-    }									  \
-} while (YYID (0))
+/* This macro is provided for backward compatibility. */
+#ifndef YY_LOCATION_PRINT
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+#endif
 
 
-/*--------------------------------.
-| Print this symbol on YYOUTPUT.  |
-`--------------------------------*/
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)                    \
+do {                                                                      \
+  if (yydebug)                                                            \
+    {                                                                     \
+      YYFPRINTF (stderr, "%s ", Title);                                   \
+      yy_symbol_print (stderr,                                            \
+                  Type, Value); \
+      YYFPRINTF (stderr, "\n");                                           \
+    }                                                                     \
+} while (0)
+
+
+/*----------------------------------------.
+| Print this symbol's value on YYOUTPUT.  |
+`----------------------------------------*/
 
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static void
 yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
-#else
-static void
-yy_symbol_value_print (yyoutput, yytype, yyvaluep)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE const * const yyvaluep;
-#endif
 {
   FILE *yyo = yyoutput;
   YYUSE (yyo);
@@ -955,14 +874,8 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep)
 # ifdef YYPRINT
   if (yytype < YYNTOKENS)
     YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
-# else
-  YYUSE (yyoutput);
 # endif
-  switch (yytype)
-    {
-      default:
-	break;
-    }
+  YYUSE (yytype);
 }
 
 
@@ -970,22 +883,11 @@ yy_symbol_value_print (yyoutput, yytype, yyvaluep)
 | Print this symbol on YYOUTPUT.  |
 `--------------------------------*/
 
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static void
 yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep)
-#else
-static void
-yy_symbol_print (yyoutput, yytype, yyvaluep)
-    FILE *yyoutput;
-    int yytype;
-    YYSTYPE const * const yyvaluep;
-#endif
 {
-  if (yytype < YYNTOKENS)
-    YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
-  else
-    YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+  YYFPRINTF (yyoutput, "%s %s (",
+             yytype < YYNTOKENS ? "token" : "nterm", yytname[yytype]);
 
   yy_symbol_value_print (yyoutput, yytype, yyvaluep);
   YYFPRINTF (yyoutput, ")");
@@ -996,16 +898,8 @@ yy_symbol_print (yyoutput, yytype, yyvaluep)
 | TOP (included).                                                   |
 `------------------------------------------------------------------*/
 
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static void
 yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop)
-#else
-static void
-yy_stack_print (yybottom, yytop)
-    yytype_int16 *yybottom;
-    yytype_int16 *yytop;
-#endif
 {
   YYFPRINTF (stderr, "Stack now");
   for (; yybottom <= yytop; yybottom++)
@@ -1016,49 +910,42 @@ yy_stack_print (yybottom, yytop)
   YYFPRINTF (stderr, "\n");
 }
 
-# define YY_STACK_PRINT(Bottom, Top)				\
-do {								\
-  if (yydebug)							\
-    yy_stack_print ((Bottom), (Top));				\
-} while (YYID (0))
+# define YY_STACK_PRINT(Bottom, Top)                            \
+do {                                                            \
+  if (yydebug)                                                  \
+    yy_stack_print ((Bottom), (Top));                           \
+} while (0)
 
 
 /*------------------------------------------------.
 | Report that the YYRULE is going to be reduced.  |
 `------------------------------------------------*/
 
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static void
-yy_reduce_print (YYSTYPE *yyvsp, int yyrule)
-#else
-static void
-yy_reduce_print (yyvsp, yyrule)
-    YYSTYPE *yyvsp;
-    int yyrule;
-#endif
+yy_reduce_print (yytype_int16 *yyssp, YYSTYPE *yyvsp, int yyrule)
 {
+  unsigned long int yylno = yyrline[yyrule];
   int yynrhs = yyr2[yyrule];
   int yyi;
-  unsigned long int yylno = yyrline[yyrule];
   YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
-	     yyrule - 1, yylno);
+             yyrule - 1, yylno);
   /* The symbols being reduced.  */
   for (yyi = 0; yyi < yynrhs; yyi++)
     {
       YYFPRINTF (stderr, "   $%d = ", yyi + 1);
-      yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
-		       &(yyvsp[(yyi + 1) - (yynrhs)])
-		       		       );
+      yy_symbol_print (stderr,
+                       yystos[yyssp[yyi + 1 - yynrhs]],
+                       &(yyvsp[(yyi + 1) - (yynrhs)])
+                                              );
       YYFPRINTF (stderr, "\n");
     }
 }
 
-# define YY_REDUCE_PRINT(Rule)		\
-do {					\
-  if (yydebug)				\
-    yy_reduce_print (yyvsp, Rule); \
-} while (YYID (0))
+# define YY_REDUCE_PRINT(Rule)          \
+do {                                    \
+  if (yydebug)                          \
+    yy_reduce_print (yyssp, yyvsp, Rule); \
+} while (0)
 
 /* Nonzero means print parse trace.  It is left uninitialized so that
    multiple parsers can coexist.  */
@@ -1072,7 +959,7 @@ int yydebug;
 
 
 /* YYINITDEPTH -- initial size of the parser's stacks.  */
-#ifndef	YYINITDEPTH
+#ifndef YYINITDEPTH
 # define YYINITDEPTH 200
 #endif
 
@@ -1095,15 +982,8 @@ int yydebug;
 #   define yystrlen strlen
 #  else
 /* Return the length of YYSTR.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static YYSIZE_T
 yystrlen (const char *yystr)
-#else
-static YYSIZE_T
-yystrlen (yystr)
-    const char *yystr;
-#endif
 {
   YYSIZE_T yylen;
   for (yylen = 0; yystr[yylen]; yylen++)
@@ -1119,16 +999,8 @@ yystrlen (yystr)
 #  else
 /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
    YYDEST.  */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static char *
 yystpcpy (char *yydest, const char *yysrc)
-#else
-static char *
-yystpcpy (yydest, yysrc)
-    char *yydest;
-    const char *yysrc;
-#endif
 {
   char *yyd = yydest;
   const char *yys = yysrc;
@@ -1158,27 +1030,27 @@ yytnamerr (char *yyres, const char *yystr)
       char const *yyp = yystr;
 
       for (;;)
-	switch (*++yyp)
-	  {
-	  case '\'':
-	  case ',':
-	    goto do_not_strip_quotes;
-
-	  case '\\':
-	    if (*++yyp != '\\')
-	      goto do_not_strip_quotes;
-	    /* Fall through.  */
-	  default:
-	    if (yyres)
-	      yyres[yyn] = *yyp;
-	    yyn++;
-	    break;
-
-	  case '"':
-	    if (yyres)
-	      yyres[yyn] = '\0';
-	    return yyn;
-	  }
+        switch (*++yyp)
+          {
+          case '\'':
+          case ',':
+            goto do_not_strip_quotes;
+
+          case '\\':
+            if (*++yyp != '\\')
+              goto do_not_strip_quotes;
+            /* Fall through.  */
+          default:
+            if (yyres)
+              yyres[yyn] = *yyp;
+            yyn++;
+            break;
+
+          case '"':
+            if (yyres)
+              yyres[yyn] = '\0';
+            return yyn;
+          }
     do_not_strip_quotes: ;
     }
 
@@ -1201,12 +1073,11 @@ static int
 yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
                 yytype_int16 *yyssp, int yytoken)
 {
-  YYSIZE_T yysize0 = yytnamerr (YY_NULL, yytname[yytoken]);
+  YYSIZE_T yysize0 = yytnamerr (YY_NULLPTR, yytname[yytoken]);
   YYSIZE_T yysize = yysize0;
-  YYSIZE_T yysize1;
   enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
   /* Internationalized format string. */
-  const char *yyformat = YY_NULL;
+  const char *yyformat = YY_NULLPTR;
   /* Arguments of yyformat. */
   char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
   /* Number of reported tokens (one for the "unexpected", one per
@@ -1214,10 +1085,6 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
   int yycount = 0;
 
   /* There are many possibilities here to consider:
-     - Assume YYFAIL is not used.  It's too flawed to consider.  See
-       <http://lists.gnu.org/archive/html/bison-patches/2009-12/msg00024.html>
-       for details.  YYERROR is fine as it does not invoke this
-       function.
      - If this state is a consistent state with a default action, then
        the only way this function was invoked is if the default action
        is an error action.  In that case, don't check for expected
@@ -1266,11 +1133,13 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
                     break;
                   }
                 yyarg[yycount++] = yytname[yyx];
-                yysize1 = yysize + yytnamerr (YY_NULL, yytname[yyx]);
-                if (! (yysize <= yysize1
-                       && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
-                  return 2;
-                yysize = yysize1;
+                {
+                  YYSIZE_T yysize1 = yysize + yytnamerr (YY_NULLPTR, yytname[yyx]);
+                  if (! (yysize <= yysize1
+                         && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+                    return 2;
+                  yysize = yysize1;
+                }
               }
         }
     }
@@ -1290,10 +1159,12 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
 # undef YYCASE_
     }
 
-  yysize1 = yysize + yystrlen (yyformat);
-  if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
-    return 2;
-  yysize = yysize1;
+  {
+    YYSIZE_T yysize1 = yysize + yystrlen (yyformat);
+    if (! (yysize <= yysize1 && yysize1 <= YYSTACK_ALLOC_MAXIMUM))
+      return 2;
+    yysize = yysize1;
+  }
 
   if (*yymsg_alloc < yysize)
     {
@@ -1330,78 +1201,58 @@ yysyntax_error (YYSIZE_T *yymsg_alloc, char **yymsg,
 | Release the memory associated to this symbol.  |
 `-----------------------------------------------*/
 
-/*ARGSUSED*/
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 static void
 yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep)
-#else
-static void
-yydestruct (yymsg, yytype, yyvaluep)
-    const char *yymsg;
-    int yytype;
-    YYSTYPE *yyvaluep;
-#endif
 {
   YYUSE (yyvaluep);
-
   if (!yymsg)
     yymsg = "Deleting";
   YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
 
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
   switch (yytype)
     {
-      case 57: /* "choice_entry" */
+          case 58: /* choice_entry  */
 
-	{
+      {
 	fprintf(stderr, "%s:%d: missing end statement for this entry\n",
-		(yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno);
-	if (current_menu == (yyvaluep->menu))
+		((*yyvaluep).menu)->file->name, ((*yyvaluep).menu)->lineno);
+	if (current_menu == ((*yyvaluep).menu))
 		menu_end_menu();
-};
+}
 
-	break;
-      case 63: /* "if_entry" */
+        break;
 
-	{
+    case 64: /* if_entry  */
+
+      {
 	fprintf(stderr, "%s:%d: missing end statement for this entry\n",
-		(yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno);
-	if (current_menu == (yyvaluep->menu))
+		((*yyvaluep).menu)->file->name, ((*yyvaluep).menu)->lineno);
+	if (current_menu == ((*yyvaluep).menu))
 		menu_end_menu();
-};
+}
 
-	break;
-      case 69: /* "menu_entry" */
+        break;
 
-	{
+    case 70: /* menu_entry  */
+
+      {
 	fprintf(stderr, "%s:%d: missing end statement for this entry\n",
-		(yyvaluep->menu)->file->name, (yyvaluep->menu)->lineno);
-	if (current_menu == (yyvaluep->menu))
+		((*yyvaluep).menu)->file->name, ((*yyvaluep).menu)->lineno);
+	if (current_menu == ((*yyvaluep).menu))
 		menu_end_menu();
-};
+}
+
+        break;
 
-	break;
 
       default:
-	break;
+        break;
     }
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
 }
 
 
-/* Prevent warnings from -Wmissing-prototypes.  */
-#ifdef YYPARSE_PARAM
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void *YYPARSE_PARAM);
-#else
-int yyparse ();
-#endif
-#else /* ! YYPARSE_PARAM */
-#if defined __STDC__ || defined __cplusplus
-int yyparse (void);
-#else
-int yyparse ();
-#endif
-#endif /* ! YYPARSE_PARAM */
 
 
 /* The lookahead symbol.  */
@@ -1409,7 +1260,6 @@ int yychar;
 
 /* The semantic value of the lookahead symbol.  */
 YYSTYPE yylval;
-
 /* Number of syntax errors so far.  */
 int yynerrs;
 
@@ -1418,35 +1268,16 @@ int yynerrs;
 | yyparse.  |
 `----------*/
 
-#ifdef YYPARSE_PARAM
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
-int
-yyparse (void *YYPARSE_PARAM)
-#else
-int
-yyparse (YYPARSE_PARAM)
-    void *YYPARSE_PARAM;
-#endif
-#else /* ! YYPARSE_PARAM */
-#if (defined __STDC__ || defined __C99__FUNC__ \
-     || defined __cplusplus || defined _MSC_VER)
 int
 yyparse (void)
-#else
-int
-yyparse ()
-
-#endif
-#endif
 {
     int yystate;
     /* Number of tokens to shift before error messages enabled.  */
     int yyerrstatus;
 
     /* The stacks and their tools:
-       `yyss': related to states.
-       `yyvs': related to semantic values.
+       'yyss': related to states.
+       'yyvs': related to semantic values.
 
        Refer to the stacks through separate pointers, to allow yyoverflow
        to reallocate them elsewhere.  */
@@ -1466,7 +1297,7 @@ yyparse ()
   int yyn;
   int yyresult;
   /* Lookahead token as an internal (translated) token number.  */
-  int yytoken;
+  int yytoken = 0;
   /* The variables used to return semantic value and location from the
      action routines.  */
   YYSTYPE yyval;
@@ -1484,9 +1315,8 @@ yyparse ()
      Keep to zero when no symbol should be popped.  */
   int yylen = 0;
 
-  yytoken = 0;
-  yyss = yyssa;
-  yyvs = yyvsa;
+  yyssp = yyss = yyssa;
+  yyvsp = yyvs = yyvsa;
   yystacksize = YYINITDEPTH;
 
   YYDPRINTF ((stderr, "Starting parse\n"));
@@ -1495,14 +1325,6 @@ yyparse ()
   yyerrstatus = 0;
   yynerrs = 0;
   yychar = YYEMPTY; /* Cause a token to be read.  */
-
-  /* Initialize stack pointers.
-     Waste one element of value and location stack
-     so that they stay on the same level as the state stack.
-     The wasted elements are never initialized.  */
-  yyssp = yyss;
-  yyvsp = yyvs;
-
   goto yysetstate;
 
 /*------------------------------------------------------------.
@@ -1523,23 +1345,23 @@ yyparse ()
 
 #ifdef yyoverflow
       {
-	/* Give user a chance to reallocate the stack.  Use copies of
-	   these so that the &'s don't force the real ones into
-	   memory.  */
-	YYSTYPE *yyvs1 = yyvs;
-	yytype_int16 *yyss1 = yyss;
-
-	/* Each stack pointer address is followed by the size of the
-	   data in use in that stack, in bytes.  This used to be a
-	   conditional around just the two extra args, but that might
-	   be undefined if yyoverflow is a macro.  */
-	yyoverflow (YY_("memory exhausted"),
-		    &yyss1, yysize * sizeof (*yyssp),
-		    &yyvs1, yysize * sizeof (*yyvsp),
-		    &yystacksize);
-
-	yyss = yyss1;
-	yyvs = yyvs1;
+        /* Give user a chance to reallocate the stack.  Use copies of
+           these so that the &'s don't force the real ones into
+           memory.  */
+        YYSTYPE *yyvs1 = yyvs;
+        yytype_int16 *yyss1 = yyss;
+
+        /* Each stack pointer address is followed by the size of the
+           data in use in that stack, in bytes.  This used to be a
+           conditional around just the two extra args, but that might
+           be undefined if yyoverflow is a macro.  */
+        yyoverflow (YY_("memory exhausted"),
+                    &yyss1, yysize * sizeof (*yyssp),
+                    &yyvs1, yysize * sizeof (*yyvsp),
+                    &yystacksize);
+
+        yyss = yyss1;
+        yyvs = yyvs1;
       }
 #else /* no yyoverflow */
 # ifndef YYSTACK_RELOCATE
@@ -1547,22 +1369,22 @@ yyparse ()
 # else
       /* Extend the stack our own way.  */
       if (YYMAXDEPTH <= yystacksize)
-	goto yyexhaustedlab;
+        goto yyexhaustedlab;
       yystacksize *= 2;
       if (YYMAXDEPTH < yystacksize)
-	yystacksize = YYMAXDEPTH;
+        yystacksize = YYMAXDEPTH;
 
       {
-	yytype_int16 *yyss1 = yyss;
-	union yyalloc *yyptr =
-	  (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
-	if (! yyptr)
-	  goto yyexhaustedlab;
-	YYSTACK_RELOCATE (yyss_alloc, yyss);
-	YYSTACK_RELOCATE (yyvs_alloc, yyvs);
+        yytype_int16 *yyss1 = yyss;
+        union yyalloc *yyptr =
+          (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+        if (! yyptr)
+          goto yyexhaustedlab;
+        YYSTACK_RELOCATE (yyss_alloc, yyss);
+        YYSTACK_RELOCATE (yyvs_alloc, yyvs);
 #  undef YYSTACK_RELOCATE
-	if (yyss1 != yyssa)
-	  YYSTACK_FREE (yyss1);
+        if (yyss1 != yyssa)
+          YYSTACK_FREE (yyss1);
       }
 # endif
 #endif /* no yyoverflow */
@@ -1571,10 +1393,10 @@ yyparse ()
       yyvsp = yyvs + yysize - 1;
 
       YYDPRINTF ((stderr, "Stack size increased to %lu\n",
-		  (unsigned long int) yystacksize));
+                  (unsigned long int) yystacksize));
 
       if (yyss + yystacksize - 1 <= yyssp)
-	YYABORT;
+        YYABORT;
     }
 
   YYDPRINTF ((stderr, "Entering state %d\n", yystate));
@@ -1603,7 +1425,7 @@ yybackup:
   if (yychar == YYEMPTY)
     {
       YYDPRINTF ((stderr, "Reading a token: "));
-      yychar = YYLEX;
+      yychar = yylex ();
     }
 
   if (yychar <= YYEOF)
@@ -1643,7 +1465,9 @@ yybackup:
   yychar = YYEMPTY;
 
   yystate = yyn;
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
   *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
 
   goto yynewstate;
 
@@ -1666,7 +1490,7 @@ yyreduce:
   yylen = yyr2[yyn];
 
   /* If YYLEN is nonzero, implement the default value of the action:
-     `$$ = $1'.
+     '$$ = $1'.
 
      Otherwise, the following line sets YYVAL to garbage.
      This behavior is undocumented and Bison
@@ -1682,64 +1506,73 @@ yyreduce:
         case 10:
 
     { zconf_error("unexpected end statement"); }
+
     break;
 
   case 11:
 
-    { zconf_error("unknown statement \"%s\"", (yyvsp[(2) - (4)].string)); }
+    { zconf_error("unknown statement \"%s\"", (yyvsp[-2].string)); }
+
     break;
 
   case 12:
 
     {
-	zconf_error("unexpected option \"%s\"", kconf_id_strings + (yyvsp[(2) - (4)].id)->name);
+	zconf_error("unexpected option \"%s\"", kconf_id_strings + (yyvsp[-2].id)->name);
 }
+
     break;
 
   case 13:
 
     { zconf_error("invalid statement"); }
+
     break;
 
-  case 28:
+  case 29:
+
+    { zconf_error("unknown option \"%s\"", (yyvsp[-2].string)); }
 
-    { zconf_error("unknown option \"%s\"", (yyvsp[(1) - (3)].string)); }
     break;
 
-  case 29:
+  case 30:
 
     { zconf_error("invalid option"); }
+
     break;
 
-  case 30:
+  case 31:
 
     {
-	struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0);
+	struct symbol *sym = sym_lookup((yyvsp[-1].string), 0);
 	sym->flags |= SYMBOL_OPTIONAL;
 	menu_add_entry(sym);
-	printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string));
+	printd(DEBUG_PARSE, "%s:%d:config %s\n", zconf_curname(), zconf_lineno(), (yyvsp[-1].string));
 }
+
     break;
 
-  case 31:
+  case 32:
 
     {
 	menu_end_entry();
 	printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
 }
+
     break;
 
-  case 32:
+  case 33:
 
     {
-	struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), 0);
+	struct symbol *sym = sym_lookup((yyvsp[-1].string), 0);
 	sym->flags |= SYMBOL_OPTIONAL;
 	menu_add_entry(sym);
-	printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string));
+	printd(DEBUG_PARSE, "%s:%d:menuconfig %s\n", zconf_curname(), zconf_lineno(), (yyvsp[-1].string));
 }
+
     break;
 
-  case 33:
+  case 34:
 
     {
 	if (current_entry->prompt)
@@ -1749,352 +1582,410 @@ yyreduce:
 	menu_end_entry();
 	printd(DEBUG_PARSE, "%s:%d:endconfig\n", zconf_curname(), zconf_lineno());
 }
+
     break;
 
-  case 41:
+  case 42:
 
     {
-	menu_set_type((yyvsp[(1) - (3)].id)->stype);
+	menu_set_type((yyvsp[-2].id)->stype);
 	printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
 		zconf_curname(), zconf_lineno(),
-		(yyvsp[(1) - (3)].id)->stype);
+		(yyvsp[-2].id)->stype);
 }
+
     break;
 
-  case 42:
+  case 43:
 
     {
-	menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr));
+	menu_add_prompt(P_PROMPT, (yyvsp[-2].string), (yyvsp[-1].expr));
 	printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
 }
+
     break;
 
-  case 43:
+  case 44:
 
     {
-	menu_add_expr(P_DEFAULT, (yyvsp[(2) - (4)].expr), (yyvsp[(3) - (4)].expr));
-	if ((yyvsp[(1) - (4)].id)->stype != S_UNKNOWN)
-		menu_set_type((yyvsp[(1) - (4)].id)->stype);
+	menu_add_expr(P_DEFAULT, (yyvsp[-2].expr), (yyvsp[-1].expr));
+	if ((yyvsp[-3].id)->stype != S_UNKNOWN)
+		menu_set_type((yyvsp[-3].id)->stype);
 	printd(DEBUG_PARSE, "%s:%d:default(%u)\n",
 		zconf_curname(), zconf_lineno(),
-		(yyvsp[(1) - (4)].id)->stype);
+		(yyvsp[-3].id)->stype);
 }
+
     break;
 
-  case 44:
+  case 45:
 
     {
-	menu_add_symbol(P_SELECT, sym_lookup((yyvsp[(2) - (4)].string), 0), (yyvsp[(3) - (4)].expr));
+	menu_add_symbol(P_SELECT, sym_lookup((yyvsp[-2].string), 0), (yyvsp[-1].expr));
 	printd(DEBUG_PARSE, "%s:%d:select\n", zconf_curname(), zconf_lineno());
 }
+
     break;
 
-  case 45:
+  case 46:
+
+    {
+	menu_add_symbol(P_COUNT, sym_lookup((yyvsp[-2].string), 0), (yyvsp[-1].expr));
+	printd(DEBUG_PARSE, "%s:%d:count\n", zconf_curname(), zconf_lineno());
+}
+
+    break;
+
+  case 47:
 
     {
-	menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,(yyvsp[(2) - (5)].symbol), (yyvsp[(3) - (5)].symbol)), (yyvsp[(4) - (5)].expr));
+	menu_add_expr(P_RANGE, expr_alloc_comp(E_RANGE,(yyvsp[-3].symbol), (yyvsp[-2].symbol)), (yyvsp[-1].expr));
 	printd(DEBUG_PARSE, "%s:%d:range\n", zconf_curname(), zconf_lineno());
 }
+
     break;
 
-  case 48:
+  case 50:
 
     {
-	const struct kconf_id *id = kconf_id_lookup((yyvsp[(2) - (3)].string), strlen((yyvsp[(2) - (3)].string)));
+	const struct kconf_id *id = kconf_id_lookup((yyvsp[-1].string), strlen((yyvsp[-1].string)));
 	if (id && id->flags & TF_OPTION)
-		menu_add_option(id->token, (yyvsp[(3) - (3)].string));
+		menu_add_option(id->token, (yyvsp[0].string));
 	else
-		zconfprint("warning: ignoring unknown option %s", (yyvsp[(2) - (3)].string));
-	free((yyvsp[(2) - (3)].string));
+		zconfprint("warning: ignoring unknown option %s", (yyvsp[-1].string));
+	free((yyvsp[-1].string));
 }
+
     break;
 
-  case 49:
+  case 51:
 
     { (yyval.string) = NULL; }
+
     break;
 
-  case 50:
+  case 52:
+
+    { (yyval.string) = (yyvsp[0].string); }
 
-    { (yyval.string) = (yyvsp[(2) - (2)].string); }
     break;
 
-  case 51:
+  case 53:
 
     {
-	struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), SYMBOL_CHOICE);
+	struct symbol *sym = sym_lookup((yyvsp[-1].string), SYMBOL_CHOICE);
 	sym->flags |= SYMBOL_AUTO;
 	menu_add_entry(sym);
 	menu_add_expr(P_CHOICE, NULL, NULL);
 	printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno());
 }
+
     break;
 
-  case 52:
+  case 54:
 
     {
 	(yyval.menu) = menu_add_menu();
 }
+
     break;
 
-  case 53:
+  case 55:
 
     {
-	if (zconf_endtoken((yyvsp[(1) - (1)].id), T_CHOICE, T_ENDCHOICE)) {
+	if (zconf_endtoken((yyvsp[0].id), T_CHOICE, T_ENDCHOICE)) {
 		menu_end_menu();
 		printd(DEBUG_PARSE, "%s:%d:endchoice\n", zconf_curname(), zconf_lineno());
 	}
 }
+
     break;
 
-  case 61:
+  case 63:
 
     {
-	menu_add_prompt(P_PROMPT, (yyvsp[(2) - (4)].string), (yyvsp[(3) - (4)].expr));
+	menu_add_prompt(P_PROMPT, (yyvsp[-2].string), (yyvsp[-1].expr));
 	printd(DEBUG_PARSE, "%s:%d:prompt\n", zconf_curname(), zconf_lineno());
 }
+
     break;
 
-  case 62:
+  case 64:
 
     {
-	if ((yyvsp[(1) - (3)].id)->stype == S_BOOLEAN || (yyvsp[(1) - (3)].id)->stype == S_TRISTATE) {
-		menu_set_type((yyvsp[(1) - (3)].id)->stype);
+	if ((yyvsp[-2].id)->stype == S_BOOLEAN || (yyvsp[-2].id)->stype == S_TRISTATE) {
+		menu_set_type((yyvsp[-2].id)->stype);
 		printd(DEBUG_PARSE, "%s:%d:type(%u)\n",
 			zconf_curname(), zconf_lineno(),
-			(yyvsp[(1) - (3)].id)->stype);
+			(yyvsp[-2].id)->stype);
 	} else
 		YYERROR;
 }
+
     break;
 
-  case 63:
+  case 65:
 
     {
 	current_entry->sym->flags |= SYMBOL_OPTIONAL;
 	printd(DEBUG_PARSE, "%s:%d:optional\n", zconf_curname(), zconf_lineno());
 }
+
     break;
 
-  case 64:
+  case 66:
 
     {
-	if ((yyvsp[(1) - (4)].id)->stype == S_UNKNOWN) {
-		menu_add_symbol(P_DEFAULT, sym_lookup((yyvsp[(2) - (4)].string), 0), (yyvsp[(3) - (4)].expr));
+	if ((yyvsp[-3].id)->stype == S_UNKNOWN) {
+		menu_add_symbol(P_DEFAULT, sym_lookup((yyvsp[-2].string), 0), (yyvsp[-1].expr));
 		printd(DEBUG_PARSE, "%s:%d:default\n",
 			zconf_curname(), zconf_lineno());
 	} else
 		YYERROR;
 }
+
     break;
 
-  case 67:
+  case 69:
 
     {
 	printd(DEBUG_PARSE, "%s:%d:if\n", zconf_curname(), zconf_lineno());
 	menu_add_entry(NULL);
-	menu_add_dep((yyvsp[(2) - (3)].expr));
+	menu_add_dep((yyvsp[-1].expr));
 	(yyval.menu) = menu_add_menu();
 }
+
     break;
 
-  case 68:
+  case 70:
 
     {
-	if (zconf_endtoken((yyvsp[(1) - (1)].id), T_IF, T_ENDIF)) {
+	if (zconf_endtoken((yyvsp[0].id), T_IF, T_ENDIF)) {
 		menu_end_menu();
 		printd(DEBUG_PARSE, "%s:%d:endif\n", zconf_curname(), zconf_lineno());
 	}
 }
+
     break;
 
-  case 74:
+  case 76:
 
     {
-	menu_add_prompt(P_MENU, (yyvsp[(2) - (3)].string), NULL);
+	menu_add_prompt(P_MENU, (yyvsp[-1].string), NULL);
 }
+
     break;
 
-  case 75:
+  case 77:
 
     {
 	menu_add_entry(NULL);
-	menu_add_prompt(P_MENU, (yyvsp[(2) - (3)].string), NULL);
+	menu_add_prompt(P_MENU, (yyvsp[-1].string), NULL);
 	printd(DEBUG_PARSE, "%s:%d:menu\n", zconf_curname(), zconf_lineno());
 }
+
     break;
 
-  case 76:
+  case 78:
 
     {
 	(yyval.menu) = menu_add_menu();
 }
+
     break;
 
-  case 77:
+  case 79:
 
     {
-	if (zconf_endtoken((yyvsp[(1) - (1)].id), T_MENU, T_ENDMENU)) {
+	if (zconf_endtoken((yyvsp[0].id), T_MENU, T_ENDMENU)) {
 		menu_end_menu();
 		printd(DEBUG_PARSE, "%s:%d:endmenu\n", zconf_curname(), zconf_lineno());
 	}
 }
+
     break;
 
-  case 83:
+  case 85:
 
     {
-	printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), (yyvsp[(2) - (3)].string));
-	zconf_nextfile((yyvsp[(2) - (3)].string));
+	printd(DEBUG_PARSE, "%s:%d:source %s\n", zconf_curname(), zconf_lineno(), (yyvsp[-1].string));
+	zconf_nextfile((yyvsp[-1].string));
 }
+
     break;
 
-  case 84:
+  case 86:
 
     {
 	menu_add_entry(NULL);
-	menu_add_prompt(P_COMMENT, (yyvsp[(2) - (3)].string), NULL);
+	menu_add_prompt(P_COMMENT, (yyvsp[-1].string), NULL);
 	printd(DEBUG_PARSE, "%s:%d:comment\n", zconf_curname(), zconf_lineno());
 }
+
     break;
 
-  case 85:
+  case 87:
 
     {
 	menu_end_entry();
 }
+
     break;
 
-  case 86:
+  case 88:
 
     {
 	printd(DEBUG_PARSE, "%s:%d:help\n", zconf_curname(), zconf_lineno());
 	zconf_starthelp();
 }
+
     break;
 
-  case 87:
+  case 89:
 
     {
-	current_entry->help = (yyvsp[(2) - (2)].string);
+	current_entry->help = (yyvsp[0].string);
 }
+
     break;
 
-  case 92:
+  case 94:
 
     {
-	menu_add_dep((yyvsp[(3) - (4)].expr));
+	menu_add_dep((yyvsp[-1].expr));
 	printd(DEBUG_PARSE, "%s:%d:depends on\n", zconf_curname(), zconf_lineno());
 }
-    break;
-
-  case 96:
 
-    {
-	menu_add_visibility((yyvsp[(2) - (2)].expr));
-}
     break;
 
   case 98:
 
     {
-	menu_add_prompt(P_PROMPT, (yyvsp[(1) - (2)].string), (yyvsp[(2) - (2)].expr));
+	menu_add_visibility((yyvsp[0].expr));
 }
-    break;
 
-  case 101:
-
-    { (yyval.id) = (yyvsp[(1) - (2)].id); }
     break;
 
-  case 102:
+  case 100:
+
+    {
+	menu_add_prompt(P_PROMPT, (yyvsp[-1].string), (yyvsp[0].expr));
+}
 
-    { (yyval.id) = (yyvsp[(1) - (2)].id); }
     break;
 
   case 103:
 
-    { (yyval.id) = (yyvsp[(1) - (2)].id); }
+    { (yyval.id) = (yyvsp[-1].id); }
+
     break;
 
-  case 106:
+  case 104:
+
+    { (yyval.id) = (yyvsp[-1].id); }
 
-    { (yyval.expr) = NULL; }
     break;
 
-  case 107:
+  case 105:
+
+    { (yyval.id) = (yyvsp[-1].id); }
 
-    { (yyval.expr) = (yyvsp[(2) - (2)].expr); }
     break;
 
   case 108:
 
-    { (yyval.expr) = expr_alloc_symbol((yyvsp[(1) - (1)].symbol)); }
+    { (yyval.expr) = NULL; }
+
     break;
 
   case 109:
 
-    { (yyval.expr) = expr_alloc_comp(E_LTH, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); }
+    { (yyval.expr) = (yyvsp[0].expr); }
+
     break;
 
   case 110:
 
-    { (yyval.expr) = expr_alloc_comp(E_LEQ, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); }
+    { (yyval.expr) = expr_alloc_symbol((yyvsp[0].symbol)); }
+
     break;
 
   case 111:
 
-    { (yyval.expr) = expr_alloc_comp(E_GTH, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); }
+    { (yyval.expr) = expr_alloc_comp(E_LTH, (yyvsp[-2].symbol), (yyvsp[0].symbol)); }
+
     break;
 
   case 112:
 
-    { (yyval.expr) = expr_alloc_comp(E_GEQ, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); }
+    { (yyval.expr) = expr_alloc_comp(E_LEQ, (yyvsp[-2].symbol), (yyvsp[0].symbol)); }
+
     break;
 
   case 113:
 
-    { (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); }
+    { (yyval.expr) = expr_alloc_comp(E_GTH, (yyvsp[-2].symbol), (yyvsp[0].symbol)); }
+
     break;
 
   case 114:
 
-    { (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[(1) - (3)].symbol), (yyvsp[(3) - (3)].symbol)); }
+    { (yyval.expr) = expr_alloc_comp(E_GEQ, (yyvsp[-2].symbol), (yyvsp[0].symbol)); }
+
     break;
 
   case 115:
 
-    { (yyval.expr) = (yyvsp[(2) - (3)].expr); }
+    { (yyval.expr) = expr_alloc_comp(E_EQUAL, (yyvsp[-2].symbol), (yyvsp[0].symbol)); }
+
     break;
 
   case 116:
 
-    { (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[(2) - (2)].expr)); }
+    { (yyval.expr) = expr_alloc_comp(E_UNEQUAL, (yyvsp[-2].symbol), (yyvsp[0].symbol)); }
+
     break;
 
   case 117:
 
-    { (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
+    { (yyval.expr) = (yyvsp[-1].expr); }
+
     break;
 
   case 118:
 
-    { (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[(1) - (3)].expr), (yyvsp[(3) - (3)].expr)); }
+    { (yyval.expr) = expr_alloc_one(E_NOT, (yyvsp[0].expr)); }
+
     break;
 
   case 119:
 
-    { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), 0); free((yyvsp[(1) - (1)].string)); }
+    { (yyval.expr) = expr_alloc_two(E_OR, (yyvsp[-2].expr), (yyvsp[0].expr)); }
+
     break;
 
   case 120:
 
-    { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), SYMBOL_CONST); free((yyvsp[(1) - (1)].string)); }
+    { (yyval.expr) = expr_alloc_two(E_AND, (yyvsp[-2].expr), (yyvsp[0].expr)); }
+
     break;
 
   case 121:
 
+    { (yyval.symbol) = sym_lookup((yyvsp[0].string), 0); free((yyvsp[0].string)); }
+
+    break;
+
+  case 122:
+
+    { (yyval.symbol) = sym_lookup((yyvsp[0].string), SYMBOL_CONST); free((yyvsp[0].string)); }
+
+    break;
+
+  case 123:
+
     { (yyval.string) = NULL; }
+
     break;
 
 
@@ -2120,7 +2011,7 @@ yyreduce:
 
   *++yyvsp = yyval;
 
-  /* Now `shift' the result of the reduction.  Determine what state
+  /* Now 'shift' the result of the reduction.  Determine what state
      that goes to, based on the state we popped back to and the rule
      number reduced by.  */
 
@@ -2135,9 +2026,9 @@ yyreduce:
   goto yynewstate;
 
 
-/*------------------------------------.
-| yyerrlab -- here on detecting error |
-`------------------------------------*/
+/*--------------------------------------.
+| yyerrlab -- here on detecting error.  |
+`--------------------------------------*/
 yyerrlab:
   /* Make sure we have latest lookahead translation.  See comments at
      user semantic actions for why this is necessary.  */
@@ -2188,20 +2079,20 @@ yyerrlab:
   if (yyerrstatus == 3)
     {
       /* If just tried and failed to reuse lookahead token after an
-	 error, discard it.  */
+         error, discard it.  */
 
       if (yychar <= YYEOF)
-	{
-	  /* Return failure if at end of input.  */
-	  if (yychar == YYEOF)
-	    YYABORT;
-	}
+        {
+          /* Return failure if at end of input.  */
+          if (yychar == YYEOF)
+            YYABORT;
+        }
       else
-	{
-	  yydestruct ("Error: discarding",
-		      yytoken, &yylval);
-	  yychar = YYEMPTY;
-	}
+        {
+          yydestruct ("Error: discarding",
+                      yytoken, &yylval);
+          yychar = YYEMPTY;
+        }
     }
 
   /* Else will try to reuse lookahead token after shifting the error
@@ -2220,7 +2111,7 @@ yyerrorlab:
   if (/*CONSTCOND*/ 0)
      goto yyerrorlab;
 
-  /* Do not reclaim the symbols of the rule which action triggered
+  /* Do not reclaim the symbols of the rule whose action triggered
      this YYERROR.  */
   YYPOPSTACK (yylen);
   yylen = 0;
@@ -2233,35 +2124,37 @@ yyerrorlab:
 | yyerrlab1 -- common code for both syntax error and YYERROR.  |
 `-------------------------------------------------------------*/
 yyerrlab1:
-  yyerrstatus = 3;	/* Each real token shifted decrements this.  */
+  yyerrstatus = 3;      /* Each real token shifted decrements this.  */
 
   for (;;)
     {
       yyn = yypact[yystate];
       if (!yypact_value_is_default (yyn))
-	{
-	  yyn += YYTERROR;
-	  if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
-	    {
-	      yyn = yytable[yyn];
-	      if (0 < yyn)
-		break;
-	    }
-	}
+        {
+          yyn += YYTERROR;
+          if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+            {
+              yyn = yytable[yyn];
+              if (0 < yyn)
+                break;
+            }
+        }
 
       /* Pop the current state because it cannot handle the error token.  */
       if (yyssp == yyss)
-	YYABORT;
+        YYABORT;
 
 
       yydestruct ("Error: popping",
-		  yystos[yystate], yyvsp);
+                  yystos[yystate], yyvsp);
       YYPOPSTACK (1);
       yystate = *yyssp;
       YY_STACK_PRINT (yyss, yyssp);
     }
 
+  YY_IGNORE_MAYBE_UNINITIALIZED_BEGIN
   *++yyvsp = yylval;
+  YY_IGNORE_MAYBE_UNINITIALIZED_END
 
 
   /* Shift the error token.  */
@@ -2304,14 +2197,14 @@ yyreturn:
       yydestruct ("Cleanup: discarding lookahead",
                   yytoken, &yylval);
     }
-  /* Do not reclaim the symbols of the rule which action triggered
+  /* Do not reclaim the symbols of the rule whose action triggered
      this YYABORT or YYACCEPT.  */
   YYPOPSTACK (yylen);
   YY_STACK_PRINT (yyss, yyssp);
   while (yyssp != yyss)
     {
       yydestruct ("Cleanup: popping",
-		  yystos[*yyssp], yyvsp);
+                  yystos[*yyssp], yyvsp);
       YYPOPSTACK (1);
     }
 #ifndef yyoverflow
@@ -2322,14 +2215,11 @@ yyreturn:
   if (yymsg != yymsgbuf)
     YYSTACK_FREE (yymsg);
 #endif
-  /* Make sure YYID is used.  */
-  return YYID (yyresult);
+  return yyresult;
 }
 
 
 
-
-
 void conf_parse(const char *name)
 {
 	struct symbol *sym;
@@ -2501,6 +2391,11 @@ static void print_symbol(FILE *out, struct menu *menu)
 			expr_fprint(prop->expr, out);
 			fputc('\n', out);
 			break;
+		case P_COUNT:
+			fputs( "  count ", out);
+			expr_fprint(prop->expr, out);
+			fputc('\n', out);
+			break;
 		case P_RANGE:
 			fputs( "  range ", out);
 			expr_fprint(prop->expr, out);
@@ -2577,4 +2472,3 @@ void zconfdump(FILE *out)
 #include "expr.c"
 #include "symbol.c"
 #include "menu.c"
-
-- 
2.6.2


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC v5 3/5] mac80211: generate hw flags from include file
  2015-11-12 22:00 [RFC v5 0/5] mac80211: elide code for static hw flags Johannes Berg
  2015-11-12 22:00 ` [RFC v5 1/5] kconfig: introduce "count" Johannes Berg
  2015-11-12 22:00 ` [RFC v5 2/5] kconfig: regenerate the shipped files Johannes Berg
@ 2015-11-12 22:00 ` Johannes Berg
  2015-11-12 22:00 ` [RFC v5 4/5] mac80211: use Kconfig counters to elide unnecessary code Johannes Berg
  2015-11-12 22:00 ` [RFC v5 5/5] iwlwifi: mvm: add Kconfig settings for hw flags Johannes Berg
  4 siblings, 0 replies; 16+ messages in thread
From: Johannes Berg @ 2015-11-12 22:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Michal Marek, Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

Instead of having to list all the hw flags in many places, just
list the macro to generate everything in a new include file and
include it in the proper places.

Unfortunately this breaks docbook processing since that doesn't
pre-process the file. It also doesn't generate the necessary
Kconfig items.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/net/mac80211-hwflags.h | 33 +++++++++++++++++++++++++++++
 include/net/mac80211.h         | 37 +++------------------------------
 net/mac80211/debugfs.c         | 47 ++++--------------------------------------
 3 files changed, 40 insertions(+), 77 deletions(-)
 create mode 100644 include/net/mac80211-hwflags.h

diff --git a/include/net/mac80211-hwflags.h b/include/net/mac80211-hwflags.h
new file mode 100644
index 000000000000..c0450391088c
--- /dev/null
+++ b/include/net/mac80211-hwflags.h
@@ -0,0 +1,33 @@
+/* this file intentionally has no include guard */
+DEFINE_HWFLAG(HAS_RATE_CONTROL)
+DEFINE_HWFLAG(RX_INCLUDES_FCS)
+DEFINE_HWFLAG(HOST_BROADCAST_PS_BUFFERING)
+DEFINE_HWFLAG(SIGNAL_UNSPEC)
+DEFINE_HWFLAG(SIGNAL_DBM)
+DEFINE_HWFLAG(NEED_DTIM_BEFORE_ASSOC)
+DEFINE_HWFLAG(SPECTRUM_MGMT)
+DEFINE_HWFLAG(AMPDU_AGGREGATION)
+DEFINE_HWFLAG(SUPPORTS_PS)
+DEFINE_HWFLAG(PS_NULLFUNC_STACK)
+DEFINE_HWFLAG(SUPPORTS_DYNAMIC_PS)
+DEFINE_HWFLAG(MFP_CAPABLE)
+DEFINE_HWFLAG(WANT_MONITOR_VIF)
+DEFINE_HWFLAG(NO_AUTO_VIF)
+DEFINE_HWFLAG(SW_CRYPTO_CONTROL)
+DEFINE_HWFLAG(SUPPORT_FAST_XMIT)
+DEFINE_HWFLAG(REPORTS_TX_ACK_STATUS)
+DEFINE_HWFLAG(CONNECTION_MONITOR)
+DEFINE_HWFLAG(QUEUE_CONTROL)
+DEFINE_HWFLAG(SUPPORTS_PER_STA_GTK)
+DEFINE_HWFLAG(AP_LINK_PS)
+DEFINE_HWFLAG(TX_AMPDU_SETUP_IN_HW)
+DEFINE_HWFLAG(SUPPORTS_RC_TABLE)
+DEFINE_HWFLAG(P2P_DEV_ADDR_FOR_INTF)
+DEFINE_HWFLAG(TIMING_BEACON_ONLY)
+DEFINE_HWFLAG(SUPPORTS_HT_CCK_RATES)
+DEFINE_HWFLAG(CHANCTX_STA_CSA)
+DEFINE_HWFLAG(SUPPORTS_CLONED_SKBS)
+DEFINE_HWFLAG(SINGLE_SCAN_ON_ALL_BANDS)
+DEFINE_HWFLAG(TDLS_WIDER_BW)
+DEFINE_HWFLAG(SUPPORTS_AMSDU_IN_AMPDU)
+DEFINE_HWFLAG(BEACON_TX_STATUS)
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 82045fca388b..2345d3d43300 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1904,40 +1904,9 @@ struct ieee80211_txq {
  * @NUM_IEEE80211_HW_FLAGS: number of hardware flags, used for sizing arrays
  */
 enum ieee80211_hw_flags {
-	IEEE80211_HW_HAS_RATE_CONTROL,
-	IEEE80211_HW_RX_INCLUDES_FCS,
-	IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING,
-	IEEE80211_HW_SIGNAL_UNSPEC,
-	IEEE80211_HW_SIGNAL_DBM,
-	IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC,
-	IEEE80211_HW_SPECTRUM_MGMT,
-	IEEE80211_HW_AMPDU_AGGREGATION,
-	IEEE80211_HW_SUPPORTS_PS,
-	IEEE80211_HW_PS_NULLFUNC_STACK,
-	IEEE80211_HW_SUPPORTS_DYNAMIC_PS,
-	IEEE80211_HW_MFP_CAPABLE,
-	IEEE80211_HW_WANT_MONITOR_VIF,
-	IEEE80211_HW_NO_AUTO_VIF,
-	IEEE80211_HW_SW_CRYPTO_CONTROL,
-	IEEE80211_HW_SUPPORT_FAST_XMIT,
-	IEEE80211_HW_REPORTS_TX_ACK_STATUS,
-	IEEE80211_HW_CONNECTION_MONITOR,
-	IEEE80211_HW_QUEUE_CONTROL,
-	IEEE80211_HW_SUPPORTS_PER_STA_GTK,
-	IEEE80211_HW_AP_LINK_PS,
-	IEEE80211_HW_TX_AMPDU_SETUP_IN_HW,
-	IEEE80211_HW_SUPPORTS_RC_TABLE,
-	IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF,
-	IEEE80211_HW_TIMING_BEACON_ONLY,
-	IEEE80211_HW_SUPPORTS_HT_CCK_RATES,
-	IEEE80211_HW_CHANCTX_STA_CSA,
-	IEEE80211_HW_SUPPORTS_CLONED_SKBS,
-	IEEE80211_HW_SINGLE_SCAN_ON_ALL_BANDS,
-	IEEE80211_HW_TDLS_WIDER_BW,
-	IEEE80211_HW_SUPPORTS_AMSDU_IN_AMPDU,
-	IEEE80211_HW_BEACON_TX_STATUS,
-
-	/* keep last, obviously */
+#define DEFINE_HWFLAG(_flg) IEEE80211_HW_##_flg,
+#include <net/mac80211-hwflags.h>
+#undef DEFINE_HWFLAG
 	NUM_IEEE80211_HW_FLAGS
 };
 
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index 4d2aaebd4f97..dc0eca604be1 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -91,44 +91,10 @@ static const struct file_operations reset_ops = {
 };
 #endif
 
-static const char *hw_flag_names[NUM_IEEE80211_HW_FLAGS + 1] = {
-#define FLAG(F)	[IEEE80211_HW_##F] = #F
-	FLAG(HAS_RATE_CONTROL),
-	FLAG(RX_INCLUDES_FCS),
-	FLAG(HOST_BROADCAST_PS_BUFFERING),
-	FLAG(SIGNAL_UNSPEC),
-	FLAG(SIGNAL_DBM),
-	FLAG(NEED_DTIM_BEFORE_ASSOC),
-	FLAG(SPECTRUM_MGMT),
-	FLAG(AMPDU_AGGREGATION),
-	FLAG(SUPPORTS_PS),
-	FLAG(PS_NULLFUNC_STACK),
-	FLAG(SUPPORTS_DYNAMIC_PS),
-	FLAG(MFP_CAPABLE),
-	FLAG(WANT_MONITOR_VIF),
-	FLAG(NO_AUTO_VIF),
-	FLAG(SW_CRYPTO_CONTROL),
-	FLAG(SUPPORT_FAST_XMIT),
-	FLAG(REPORTS_TX_ACK_STATUS),
-	FLAG(CONNECTION_MONITOR),
-	FLAG(QUEUE_CONTROL),
-	FLAG(SUPPORTS_PER_STA_GTK),
-	FLAG(AP_LINK_PS),
-	FLAG(TX_AMPDU_SETUP_IN_HW),
-	FLAG(SUPPORTS_RC_TABLE),
-	FLAG(P2P_DEV_ADDR_FOR_INTF),
-	FLAG(TIMING_BEACON_ONLY),
-	FLAG(SUPPORTS_HT_CCK_RATES),
-	FLAG(CHANCTX_STA_CSA),
-	FLAG(SUPPORTS_CLONED_SKBS),
-	FLAG(SINGLE_SCAN_ON_ALL_BANDS),
-	FLAG(TDLS_WIDER_BW),
-	FLAG(SUPPORTS_AMSDU_IN_AMPDU),
-	FLAG(BEACON_TX_STATUS),
-
-	/* keep last for the build bug below */
-	(void *)0x1
-#undef FLAG
+static const char *hw_flag_names[NUM_IEEE80211_HW_FLAGS] = {
+#define DEFINE_HWFLAG(_flg)	[IEEE80211_HW_##_flg] = #_flg,
+#include <net/mac80211-hwflags.h>
+#undef DEFINE_HWFLAG
 };
 
 static ssize_t hwflags_read(struct file *file, char __user *user_buf,
@@ -144,11 +110,6 @@ static ssize_t hwflags_read(struct file *file, char __user *user_buf,
 	if (!buf)
 		return -ENOMEM;
 
-	/* fail compilation if somebody adds or removes
-	 * a flag without updating the name array above
-	 */
-	BUILD_BUG_ON(hw_flag_names[NUM_IEEE80211_HW_FLAGS] != (void *)0x1);
-
 	for (i = 0; i < NUM_IEEE80211_HW_FLAGS; i++) {
 		if (test_bit(i, local->hw.flags))
 			pos += scnprintf(pos, end - pos, "%s\n",
-- 
2.6.2


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC v5 4/5] mac80211: use Kconfig counters to elide unnecessary code
  2015-11-12 22:00 [RFC v5 0/5] mac80211: elide code for static hw flags Johannes Berg
                   ` (2 preceding siblings ...)
  2015-11-12 22:00 ` [RFC v5 3/5] mac80211: generate hw flags from include file Johannes Berg
@ 2015-11-12 22:00 ` Johannes Berg
  2015-11-13  9:48   ` Julian Calaby
                     ` (2 more replies)
  2015-11-12 22:00 ` [RFC v5 5/5] iwlwifi: mvm: add Kconfig settings for hw flags Johannes Berg
  4 siblings, 3 replies; 16+ messages in thread
From: Johannes Berg @ 2015-11-12 22:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Michal Marek, Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

There are many drivers with different behaviour, but in a lot of
systems only a single driver will ever be built. In that case we
can get rid of code paths that this driver doesn't need and also
optimize the ones that it always takes to not have a check.

To make that possible, make use Kconfig counters to
 (a) the number of times each feature flag was desired
 (b) the number of mac80211 drivers built
and use Kconfig selects to select those flags that any drivers
need to be dynamic (e.g. if they can only determine this flag's
setting at runtime.)

If the dynamic request isn't set then

 if (a) > 0 then it was requested ON by at least one driver
 if (a) < (b) then it was requested OFF by at least one driver

This allows determining whether or not it's safe to elide some
code entirely.

For added safety, add a HW registration time check for it.

With our iwlwifi/mvm driver, this reduces mac80211's code size
by just over 6KB (on x86/64), or about 1%. It's not that much,
but a fair amount of it (just under 1KB) is in the TX/RX/status
paths which are the hottest code in mac80211.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 drivers/net/wireless/Kconfig                  |  20 ++++
 drivers/net/wireless/ath/ar5523/Kconfig       |   2 +
 drivers/net/wireless/ath/ath10k/Kconfig       |   2 +
 drivers/net/wireless/ath/ath9k/Kconfig        |   2 +
 drivers/net/wireless/ath/wcn36xx/Kconfig      |   2 +
 drivers/net/wireless/b43/Kconfig              |   2 +
 drivers/net/wireless/b43legacy/Kconfig        |   2 +
 drivers/net/wireless/brcm80211/Kconfig        |   2 +
 drivers/net/wireless/cw1200/Kconfig           |   2 +
 drivers/net/wireless/iwlegacy/Kconfig         |   4 +
 drivers/net/wireless/iwlwifi/Kconfig          |   4 +
 drivers/net/wireless/mediatek/mt7601u/Kconfig |   2 +
 drivers/net/wireless/p54/Kconfig              |   2 +
 drivers/net/wireless/realtek/rtl818x/Kconfig  |   4 +
 drivers/net/wireless/realtek/rtl8xxxu/Kconfig |   2 +
 drivers/net/wireless/realtek/rtlwifi/Kconfig  |   2 +
 drivers/net/wireless/rsi/Kconfig              |   2 +
 drivers/net/wireless/rt2x00/Kconfig           |   2 +
 drivers/net/wireless/ti/wl1251/Kconfig        |   2 +
 drivers/net/wireless/ti/wl12xx/Kconfig        |   2 +
 drivers/net/wireless/ti/wl18xx/Kconfig        |   2 +
 drivers/staging/vt6655/Kconfig                |   2 +
 drivers/staging/vt6656/Kconfig                |   2 +
 include/net/mac80211.h                        |  36 +++++-
 net/mac80211/Kconfig                          |   9 ++
 net/mac80211/Kconfig.hwflags                  | 160 ++++++++++++++++++++++++++
 net/mac80211/Makefile                         |   3 +-
 net/mac80211/main.c                           |  25 ++++
 28 files changed, 296 insertions(+), 7 deletions(-)
 create mode 100644 net/mac80211/Kconfig.hwflags

diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index f9f94229bf1b..873b6c7b18b8 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -35,6 +35,8 @@ config PCMCIA_RAYCS
 config LIBERTAS_THINFIRM
 	tristate "Marvell 8xxx Libertas WLAN driver support with thin firmware"
 	depends on MAC80211
+	count MAC80211_NUM_DRIVERS
+	select MAC80211_DRIVER_NO_HWFLAGS
 	select FW_LOADER
 	---help---
 	  A library for Marvell Libertas 8xxx devices using thinfirm.
@@ -109,6 +111,8 @@ config PCMCIA_ATMEL
 config AT76C50X_USB
         tristate "Atmel at76c503/at76c505/at76c505a USB cards"
         depends on MAC80211 && USB
+	count MAC80211_NUM_DRIVERS
+	select MAC80211_DRIVER_NO_HWFLAGS
         select FW_LOADER
         ---help---
           Enable support for USB Wireless devices using Atmel at76c503,
@@ -217,6 +221,8 @@ config USB_NET_RNDIS_WLAN
 config ADM8211
 	tristate "ADMtek ADM8211 support"
 	depends on MAC80211 && PCI
+	count MAC80211_NUM_DRIVERS
+	select MAC80211_DRIVER_NO_HWFLAGS
 	select CRC32
 	select EEPROM_93CX6
 	---help---
@@ -246,6 +252,18 @@ source "drivers/net/wireless/realtek/rtl818x/Kconfig"
 config MAC80211_HWSIM
 	tristate "Simulated radio testing tool for mac80211"
 	depends on MAC80211
+	count MAC80211_NUM_DRIVERS
+	count MAC80211_HW_SUPPORT_FAST_XMIT
+	count MAC80211_HW_CHANCTX_STA_CSA
+	count MAC80211_HW_SUPPORTS_HT_CCK_RATES
+	count MAC80211_HW_QUEUE_CONTROL
+	count MAC80211_HW_WANT_MONITOR_VIF
+	count MAC80211_HW_AMPDU_AGGREGATION
+	count MAC80211_HW_MFP_CAPABLE
+	count MAC80211_HW_SIGNAL_DBM
+	count MAC80211_HW_TDLS_WIDER_BW
+	select MAC80211_HW_NO_AUTO_VIF_DYN
+	select MAC80211_HW_SUPPORTS_RC_TABLE_DYN
 	---help---
 	  This driver is a developer testing tool that can be used to test
 	  IEEE 802.11 networking stack (mac80211) functionality. This is not
@@ -259,6 +277,8 @@ config MAC80211_HWSIM
 config MWL8K
 	tristate "Marvell 88W8xxx PCI/PCIe Wireless support"
 	depends on MAC80211 && PCI
+	count MAC80211_NUM_DRIVERS
+	select MAC80211_DRIVER_NO_HWFLAGS
 	---help---
 	  This driver supports Marvell TOPDOG 802.11 wireless cards.
 
diff --git a/drivers/net/wireless/ath/ar5523/Kconfig b/drivers/net/wireless/ath/ar5523/Kconfig
index 0d320cc7769b..6534e600429d 100644
--- a/drivers/net/wireless/ath/ar5523/Kconfig
+++ b/drivers/net/wireless/ath/ar5523/Kconfig
@@ -1,6 +1,8 @@
 config AR5523
        tristate "Atheros AR5523 wireless driver support"
        depends on MAC80211 && USB
+	count MAC80211_NUM_DRIVERS
+	select MAC80211_DRIVER_NO_HWFLAGS
        select ATH_COMMON
        select FW_LOADER
        ---help---
diff --git a/drivers/net/wireless/ath/ath10k/Kconfig b/drivers/net/wireless/ath/ath10k/Kconfig
index 72acb822bb11..814d7d25bf1d 100644
--- a/drivers/net/wireless/ath/ath10k/Kconfig
+++ b/drivers/net/wireless/ath/ath10k/Kconfig
@@ -1,6 +1,8 @@
 config ATH10K
         tristate "Atheros 802.11ac wireless cards support"
         depends on MAC80211 && HAS_DMA
+	count MAC80211_NUM_DRIVERS
+	select MAC80211_DRIVER_NO_HWFLAGS
 	select ATH_COMMON
         ---help---
           This module adds support for wireless adapters based on
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig
index fee0cadb0f5e..26d819208e68 100644
--- a/drivers/net/wireless/ath/ath9k/Kconfig
+++ b/drivers/net/wireless/ath/ath9k/Kconfig
@@ -20,6 +20,8 @@ config ATH9K_BTCOEX_SUPPORT
 config ATH9K
 	tristate "Atheros 802.11n wireless cards support"
 	depends on MAC80211 && HAS_DMA
+	count MAC80211_NUM_DRIVERS
+	select MAC80211_DRIVER_NO_HWFLAGS
 	select ATH9K_HW
 	select MAC80211_LEDS
 	select LEDS_CLASS
diff --git a/drivers/net/wireless/ath/wcn36xx/Kconfig b/drivers/net/wireless/ath/wcn36xx/Kconfig
index 591ebaea8265..a977a91021ac 100644
--- a/drivers/net/wireless/ath/wcn36xx/Kconfig
+++ b/drivers/net/wireless/ath/wcn36xx/Kconfig
@@ -1,6 +1,8 @@
 config WCN36XX
 	tristate "Qualcomm Atheros WCN3660/3680 support"
 	depends on MAC80211 && HAS_DMA
+	count MAC80211_NUM_DRIVERS
+	select MAC80211_DRIVER_NO_HWFLAGS
 	---help---
 	  This module adds support for wireless adapters based on
 	  Qualcomm Atheros WCN3660 and WCN3680 mobile chipsets.
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig
index fba856032ca5..2a1f61774475 100644
--- a/drivers/net/wireless/b43/Kconfig
+++ b/drivers/net/wireless/b43/Kconfig
@@ -1,6 +1,8 @@
 config B43
 	tristate "Broadcom 43xx wireless support (mac80211 stack)"
 	depends on (BCMA_POSSIBLE || SSB_POSSIBLE) && MAC80211 && HAS_DMA
+	count MAC80211_NUM_DRIVERS
+	select MAC80211_DRIVER_NO_HWFLAGS
 	select BCMA if B43_BCMA
 	select SSB if B43_SSB
 	select FW_LOADER
diff --git a/drivers/net/wireless/b43legacy/Kconfig b/drivers/net/wireless/b43legacy/Kconfig
index 1ffa28835c58..8ae74e50ba27 100644
--- a/drivers/net/wireless/b43legacy/Kconfig
+++ b/drivers/net/wireless/b43legacy/Kconfig
@@ -1,6 +1,8 @@
 config B43LEGACY
 	tristate "Broadcom 43xx-legacy wireless support (mac80211 stack)"
 	depends on SSB_POSSIBLE && MAC80211 && HAS_DMA
+	count MAC80211_NUM_DRIVERS
+	select MAC80211_DRIVER_NO_HWFLAGS
 	select SSB
 	select FW_LOADER
 	---help---
diff --git a/drivers/net/wireless/brcm80211/Kconfig b/drivers/net/wireless/brcm80211/Kconfig
index ab42b1fea03c..c63cb95b4191 100644
--- a/drivers/net/wireless/brcm80211/Kconfig
+++ b/drivers/net/wireless/brcm80211/Kconfig
@@ -4,6 +4,8 @@ config BRCMUTIL
 config BRCMSMAC
 	tristate "Broadcom IEEE802.11n PCIe SoftMAC WLAN driver"
 	depends on MAC80211
+	count MAC80211_NUM_DRIVERS
+	select MAC80211_DRIVER_NO_HWFLAGS
 	depends on BCMA_POSSIBLE
 	select BCMA
 	select NEW_LEDS if BCMA_DRIVER_GPIO
diff --git a/drivers/net/wireless/cw1200/Kconfig b/drivers/net/wireless/cw1200/Kconfig
index 0880742eab17..06bf2fa61db0 100644
--- a/drivers/net/wireless/cw1200/Kconfig
+++ b/drivers/net/wireless/cw1200/Kconfig
@@ -1,6 +1,8 @@
 config CW1200
 	tristate "CW1200 WLAN support"
 	depends on MAC80211 && CFG80211
+	count MAC80211_NUM_DRIVERS
+	select MAC80211_DRIVER_NO_HWFLAGS
 	help
 	  This is a driver for the ST-E CW1100 & CW1200 WLAN chipsets.
 	  This option just enables the driver core, see below for
diff --git a/drivers/net/wireless/iwlegacy/Kconfig b/drivers/net/wireless/iwlegacy/Kconfig
index fb919727b8bb..67f8f03f421c 100644
--- a/drivers/net/wireless/iwlegacy/Kconfig
+++ b/drivers/net/wireless/iwlegacy/Kconfig
@@ -9,6 +9,8 @@ config IWLEGACY
 config IWL4965
 	tristate "Intel Wireless WiFi 4965AGN (iwl4965)"
 	depends on PCI && MAC80211
+	count MAC80211_NUM_DRIVERS
+	select MAC80211_DRIVER_NO_HWFLAGS
 	select IWLEGACY
 	---help---
 	  This option enables support for
@@ -37,6 +39,8 @@ config IWL4965
 config IWL3945
 	tristate "Intel PRO/Wireless 3945ABG/BG Network Connection (iwl3945)"
 	depends on PCI && MAC80211
+	count MAC80211_NUM_DRIVERS
+	select MAC80211_DRIVER_NO_HWFLAGS
 	select IWLEGACY
 	---help---
 	  Select to build the driver supporting the:
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index 6e949df399d6..3fbee1ec1d33 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -54,6 +54,8 @@ config IWLWIFI_LEDS
 config IWLDVM
 	tristate "Intel Wireless WiFi DVM Firmware support"
 	default IWLWIFI
+	count MAC80211_NUM_DRIVERS
+	select MAC80211_DRIVER_NO_HWFLAGS
 	help
 	  This is the driver that supports the DVM firmware. The list
 	  of the devices that use this firmware is available here:
@@ -62,6 +64,8 @@ config IWLDVM
 config IWLMVM
 	tristate "Intel Wireless WiFi MVM Firmware support"
 	select WANT_DEV_COREDUMP
+	count MAC80211_NUM_DRIVERS
+	select MAC80211_DRIVER_NO_HWFLAGS
 	help
 	  This is the driver that supports the MVM firmware. The list
 	  of the devices that use this firmware is available here:
diff --git a/drivers/net/wireless/mediatek/mt7601u/Kconfig b/drivers/net/wireless/mediatek/mt7601u/Kconfig
index f46bed92796b..31781e2a7a11 100644
--- a/drivers/net/wireless/mediatek/mt7601u/Kconfig
+++ b/drivers/net/wireless/mediatek/mt7601u/Kconfig
@@ -1,6 +1,8 @@
 config MT7601U
 	tristate "MediaTek MT7601U (USB) support"
 	depends on MAC80211
+	count MAC80211_NUM_DRIVERS
+	select MAC80211_DRIVER_NO_HWFLAGS
 	depends on USB
 	---help---
 	  This adds support for MT7601U-based wireless USB dongles.
diff --git a/drivers/net/wireless/p54/Kconfig b/drivers/net/wireless/p54/Kconfig
index cdafb8c73e82..0a60e2b5e0b1 100644
--- a/drivers/net/wireless/p54/Kconfig
+++ b/drivers/net/wireless/p54/Kconfig
@@ -1,6 +1,8 @@
 config P54_COMMON
 	tristate "Softmac Prism54 support"
 	depends on MAC80211
+	count MAC80211_NUM_DRIVERS
+	select MAC80211_DRIVER_NO_HWFLAGS
 	select FW_LOADER
 	select CRC_CCITT
 	---help---
diff --git a/drivers/net/wireless/realtek/rtl818x/Kconfig b/drivers/net/wireless/realtek/rtl818x/Kconfig
index 1ce1d55f0010..e17dad1ad531 100644
--- a/drivers/net/wireless/realtek/rtl818x/Kconfig
+++ b/drivers/net/wireless/realtek/rtl818x/Kconfig
@@ -4,6 +4,8 @@
 config RTL8180
 	tristate "Realtek 8180/8185/8187SE PCI support"
 	depends on MAC80211 && PCI
+	count MAC80211_NUM_DRIVERS
+	select MAC80211_DRIVER_NO_HWFLAGS
 	select EEPROM_93CX6
 	---help---
 	  This is a driver for RTL8180, RTL8185 and RTL8187SE based cards.
@@ -60,6 +62,8 @@ config RTL8180
 config RTL8187
 	tristate "Realtek 8187 and 8187B USB support"
 	depends on MAC80211 && USB
+	count MAC80211_NUM_DRIVERS
+	select MAC80211_DRIVER_NO_HWFLAGS
 	select EEPROM_93CX6
 	---help---
 	  This is a driver for RTL8187 and RTL8187B based cards.
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/Kconfig b/drivers/net/wireless/realtek/rtl8xxxu/Kconfig
index dd4d626aecbc..c1a1d89ad6aa 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/Kconfig
+++ b/drivers/net/wireless/realtek/rtl8xxxu/Kconfig
@@ -4,6 +4,8 @@
 config RTL8XXXU
 	tristate "RTL8723AU/RTL8188[CR]U/RTL819[12]CU (mac80211) support"
 	depends on MAC80211 && USB
+	count MAC80211_NUM_DRIVERS
+	select MAC80211_DRIVER_NO_HWFLAGS
 	---help---
 	  This is an alternative driver for various Realtek RTL8XXX
 	  parts written to utilize the Linux mac80211 stack.
diff --git a/drivers/net/wireless/realtek/rtlwifi/Kconfig b/drivers/net/wireless/realtek/rtlwifi/Kconfig
index 73067cac289c..bfd079c0205c 100644
--- a/drivers/net/wireless/realtek/rtlwifi/Kconfig
+++ b/drivers/net/wireless/realtek/rtlwifi/Kconfig
@@ -1,6 +1,8 @@
 menuconfig RTL_CARDS
 	tristate "Realtek rtlwifi family of devices"
 	depends on MAC80211 && (PCI || USB)
+	count MAC80211_NUM_DRIVERS
+	select MAC80211_DRIVER_NO_HWFLAGS
 	default y
 	---help---
 	  This option will enable support for the Realtek mac80211-based
diff --git a/drivers/net/wireless/rsi/Kconfig b/drivers/net/wireless/rsi/Kconfig
index 35245f994c10..f206b1e38ca6 100644
--- a/drivers/net/wireless/rsi/Kconfig
+++ b/drivers/net/wireless/rsi/Kconfig
@@ -1,6 +1,8 @@
 config RSI_91X
 	tristate "Redpine Signals Inc 91x WLAN driver support"
 	depends on MAC80211
+	count MAC80211_NUM_DRIVERS
+	select MAC80211_DRIVER_NO_HWFLAGS
 	---help---
 	  This option enabes support for RSI 1x1 devices.
 	  Select M (recommended), if you have a RSI 1x1 wireless module.
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig
index de62f5dcb62f..90f9efc0cc49 100644
--- a/drivers/net/wireless/rt2x00/Kconfig
+++ b/drivers/net/wireless/rt2x00/Kconfig
@@ -1,6 +1,8 @@
 menuconfig RT2X00
 	tristate "Ralink driver support"
 	depends on MAC80211 && HAS_DMA
+	count MAC80211_NUM_DRIVERS
+	select MAC80211_DRIVER_NO_HWFLAGS
 	---help---
 	  This will enable the support for the Ralink drivers,
 	  developed in the rt2x00 project <http://rt2x00.serialmonkey.com>.
diff --git a/drivers/net/wireless/ti/wl1251/Kconfig b/drivers/net/wireless/ti/wl1251/Kconfig
index 477a206c098e..dc6309d22e26 100644
--- a/drivers/net/wireless/ti/wl1251/Kconfig
+++ b/drivers/net/wireless/ti/wl1251/Kconfig
@@ -1,6 +1,8 @@
 menuconfig WL1251
 	tristate "TI wl1251 driver support"
 	depends on MAC80211
+	count MAC80211_NUM_DRIVERS
+	select MAC80211_DRIVER_NO_HWFLAGS
 	select FW_LOADER
 	select CRC7
 	---help---
diff --git a/drivers/net/wireless/ti/wl12xx/Kconfig b/drivers/net/wireless/ti/wl12xx/Kconfig
index c2183594655a..48eb701e647d 100644
--- a/drivers/net/wireless/ti/wl12xx/Kconfig
+++ b/drivers/net/wireless/ti/wl12xx/Kconfig
@@ -1,6 +1,8 @@
 config WL12XX
        tristate "TI wl12xx support"
 	depends on MAC80211
+	count MAC80211_NUM_DRIVERS
+	select MAC80211_DRIVER_NO_HWFLAGS
        select WLCORE
        ---help---
 	  This module adds support for wireless adapters based on TI wl1271,
diff --git a/drivers/net/wireless/ti/wl18xx/Kconfig b/drivers/net/wireless/ti/wl18xx/Kconfig
index 1cfdb2548821..6670f41ab0b0 100644
--- a/drivers/net/wireless/ti/wl18xx/Kconfig
+++ b/drivers/net/wireless/ti/wl18xx/Kconfig
@@ -1,6 +1,8 @@
 config WL18XX
 	tristate "TI wl18xx support"
 	depends on MAC80211
+	count MAC80211_NUM_DRIVERS
+	select MAC80211_DRIVER_NO_HWFLAGS
 	select WLCORE
 	---help---
 	  This module adds support for wireless adapters based on TI
diff --git a/drivers/staging/vt6655/Kconfig b/drivers/staging/vt6655/Kconfig
index 77cfc708c516..dfc0bfef6222 100644
--- a/drivers/staging/vt6655/Kconfig
+++ b/drivers/staging/vt6655/Kconfig
@@ -1,6 +1,8 @@
 config VT6655
    tristate "VIA Technologies VT6655 support"
    depends on PCI && MAC80211 && m
+   count MAC80211_NUM_DRIVERS
+   select MAC80211_DRIVER_NO_HWFLAGS
    ---help---
    This is a vendor-written driver for VIA VT6655.
 
diff --git a/drivers/staging/vt6656/Kconfig b/drivers/staging/vt6656/Kconfig
index b602ef175d55..f6c2811fed21 100644
--- a/drivers/staging/vt6656/Kconfig
+++ b/drivers/staging/vt6656/Kconfig
@@ -1,6 +1,8 @@
 config VT6656
 	tristate "VIA Technologies VT6656 support"
 	depends on MAC80211 && USB && WLAN && m
+	count MAC80211_NUM_DRIVERS
+	select MAC80211_DRIVER_NO_HWFLAGS
 	select FW_LOADER
 	---help---
 	This is a vendor-written driver for VIA VT6656.
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 2345d3d43300..485d4a728163 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2040,12 +2040,36 @@ struct ieee80211_hw {
 	int txq_ac_max_pending;
 };
 
-static inline bool _ieee80211_hw_check(struct ieee80211_hw *hw,
-				       enum ieee80211_hw_flags flg)
-{
-	return test_bit(flg, hw->flags);
-}
-#define ieee80211_hw_check(hw, flg)	_ieee80211_hw_check(hw, IEEE80211_HW_##flg)
+enum hwflags_states {
+#define __DEFINE_HWFLAG(_flg, _dyn, _on, _off)				\
+	HWFLAGS_STATE_##_flg = -1 + (!(_dyn)) * (((_on) ^ (_off)) * (1 + (_on))),
+#define DEFINE_HWFLAG(_flg)						\
+	__DEFINE_HWFLAG(_flg,						\
+			IS_ENABLED(CONFIG_MAC80211_HW_##_flg##_DYN),	\
+			CONFIG_MAC80211_HW_##_flg > 0,			\
+			CONFIG_MAC80211_HW_##_flg < CONFIG_MAC80211_NUM_DRIVERS)
+#include <net/mac80211-hwflags.h>
+#undef DEFINE_HWFLAG
+};
+
+bool _____optimisation_missing(void);
+
+#define ieee80211_hw_check(hw, flg)					\
+({									\
+	enum ieee80211_hw_flags flag = IEEE80211_HW_##flg;		\
+	bool result;							\
+									\
+	if (HWFLAGS_STATE_##flg == -1)					\
+		result = test_bit(flag, (hw)->flags);			\
+	else if (HWFLAGS_STATE_##flg == 1)				\
+		result = true;						\
+	else if (HWFLAGS_STATE_##flg == 0)				\
+		result = false;						\
+	else								\
+		result = _____optimisation_missing();			\
+									\
+	result;								\
+})
 
 static inline void _ieee80211_hw_set(struct ieee80211_hw *hw,
 				     enum ieee80211_hw_flags flg)
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
index 3891cbd2adea..5760dc91f468 100644
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -11,6 +11,13 @@ config MAC80211
 	  This option enables the hardware independent IEEE 802.11
 	  networking stack.
 
+config MAC80211_NUM_DRIVERS
+	int
+	depends on MAC80211
+
+config MAC80211_DRIVER_NO_HWFLAGS
+	bool
+
 comment "CFG80211 needs to be enabled for MAC80211"
 	depends on CFG80211=n
 
@@ -318,3 +325,5 @@ config MAC80211_STA_HASH_MAX_SIZE
 	  connect more stations than the number selected here.)
 
 	  If unsure, leave the default of 0.
+
+source "net/mac80211/Kconfig.hwflags"
diff --git a/net/mac80211/Kconfig.hwflags b/net/mac80211/Kconfig.hwflags
new file mode 100644
index 000000000000..43beeab9a1d8
--- /dev/null
+++ b/net/mac80211/Kconfig.hwflags
@@ -0,0 +1,160 @@
+config MAC80211_HW_HAS_RATE_CONTROL
+	int
+	default 0
+config MAC80211_HW_HAS_RATE_CONTROL_DYN
+	bool
+config MAC80211_HW_RX_INCLUDES_FCS
+	int
+	default 0
+config MAC80211_HW_RX_INCLUDES_FCS_DYN
+	bool
+config MAC80211_HW_HOST_BROADCAST_PS_BUFFERING
+	int
+	default 0
+config MAC80211_HW_HOST_BROADCAST_PS_BUFFERING_DYN
+	bool
+config MAC80211_HW_SIGNAL_UNSPEC
+	int
+	default 0
+config MAC80211_HW_SIGNAL_UNSPEC_DYN
+	bool
+config MAC80211_HW_SIGNAL_DBM
+	int
+	default 0
+config MAC80211_HW_SIGNAL_DBM_DYN
+	bool
+config MAC80211_HW_NEED_DTIM_BEFORE_ASSOC
+	int
+	default 0
+config MAC80211_HW_NEED_DTIM_BEFORE_ASSOC_DYN
+	bool
+config MAC80211_HW_SPECTRUM_MGMT
+	int
+	default 0
+config MAC80211_HW_SPECTRUM_MGMT_DYN
+	bool
+config MAC80211_HW_AMPDU_AGGREGATION
+	int
+	default 0
+config MAC80211_HW_AMPDU_AGGREGATION_DYN
+	bool
+config MAC80211_HW_SUPPORTS_PS
+	int
+	default 0
+config MAC80211_HW_SUPPORTS_PS_DYN
+	bool
+config MAC80211_HW_PS_NULLFUNC_STACK
+	int
+	default 0
+config MAC80211_HW_PS_NULLFUNC_STACK_DYN
+	bool
+config MAC80211_HW_SUPPORTS_DYNAMIC_PS
+	int
+	default 0
+config MAC80211_HW_SUPPORTS_DYNAMIC_PS_DYN
+	bool
+config MAC80211_HW_MFP_CAPABLE
+	int
+	default 0
+config MAC80211_HW_MFP_CAPABLE_DYN
+	bool
+config MAC80211_HW_WANT_MONITOR_VIF
+	int
+	default 0
+config MAC80211_HW_WANT_MONITOR_VIF_DYN
+	bool
+config MAC80211_HW_NO_AUTO_VIF
+	int
+	default 0
+config MAC80211_HW_NO_AUTO_VIF_DYN
+	bool
+config MAC80211_HW_SW_CRYPTO_CONTROL
+	int
+	default 0
+config MAC80211_HW_SW_CRYPTO_CONTROL_DYN
+	bool
+config MAC80211_HW_SUPPORT_FAST_XMIT
+	int
+	default 0
+config MAC80211_HW_SUPPORT_FAST_XMIT_DYN
+	bool
+config MAC80211_HW_REPORTS_TX_ACK_STATUS
+	int
+	default 0
+config MAC80211_HW_REPORTS_TX_ACK_STATUS_DYN
+	bool
+config MAC80211_HW_CONNECTION_MONITOR
+	int
+	default 0
+config MAC80211_HW_CONNECTION_MONITOR_DYN
+	bool
+config MAC80211_HW_QUEUE_CONTROL
+	int
+	default 0
+config MAC80211_HW_QUEUE_CONTROL_DYN
+	bool
+config MAC80211_HW_SUPPORTS_PER_STA_GTK
+	int
+	default 0
+config MAC80211_HW_SUPPORTS_PER_STA_GTK_DYN
+	bool
+config MAC80211_HW_AP_LINK_PS
+	int
+	default 0
+config MAC80211_HW_AP_LINK_PS_DYN
+	bool
+config MAC80211_HW_TX_AMPDU_SETUP_IN_HW
+	int
+	default 0
+config MAC80211_HW_TX_AMPDU_SETUP_IN_HW_DYN
+	bool
+config MAC80211_HW_SUPPORTS_RC_TABLE
+	int
+	default 0
+config MAC80211_HW_SUPPORTS_RC_TABLE_DYN
+	bool
+config MAC80211_HW_P2P_DEV_ADDR_FOR_INTF
+	int
+	default 0
+config MAC80211_HW_P2P_DEV_ADDR_FOR_INTF_DYN
+	bool
+config MAC80211_HW_TIMING_BEACON_ONLY
+	int
+	default 0
+config MAC80211_HW_TIMING_BEACON_ONLY_DYN
+	bool
+config MAC80211_HW_SUPPORTS_HT_CCK_RATES
+	int
+	default 0
+config MAC80211_HW_SUPPORTS_HT_CCK_RATES_DYN
+	bool
+config MAC80211_HW_CHANCTX_STA_CSA
+	int
+	default 0
+config MAC80211_HW_CHANCTX_STA_CSA_DYN
+	bool
+config MAC80211_HW_SUPPORTS_CLONED_SKBS
+	int
+	default 0
+config MAC80211_HW_SUPPORTS_CLONED_SKBS_DYN
+	bool
+config MAC80211_HW_SINGLE_SCAN_ON_ALL_BANDS
+	int
+	default 0
+config MAC80211_HW_SINGLE_SCAN_ON_ALL_BANDS_DYN
+	bool
+config MAC80211_HW_TDLS_WIDER_BW
+	int
+	default 0
+config MAC80211_HW_TDLS_WIDER_BW_DYN
+	bool
+config MAC80211_HW_SUPPORTS_AMSDU_IN_AMPDU
+	int
+	default 0
+config MAC80211_HW_SUPPORTS_AMSDU_IN_AMPDU_DYN
+	bool
+config MAC80211_HW_BEACON_TX_STATUS
+	int
+	default 0
+config MAC80211_HW_BEACON_TX_STATUS_DYN
+	bool
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile
index f9137a8341f4..eeff93b5f1c6 100644
--- a/net/mac80211/Makefile
+++ b/net/mac80211/Makefile
@@ -30,7 +30,8 @@ mac80211-y := \
 	chan.o \
 	trace.o mlme.o \
 	tdls.o \
-	ocb.o
+	ocb.o \
+	hwflags.o
 
 mac80211-$(CONFIG_MAC80211_LEDS) += led.o
 mac80211-$(CONFIG_MAC80211_DEBUGFS) += \
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 858f6b1cb149..d70b9f1feb52 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -789,6 +789,28 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local)
 	return 0;
 }
 
+static s8 hwflags_state[] = {
+#define DEFINE_HWFLAG(_flg)	\
+	[IEEE80211_HW_##_flg] = HWFLAGS_STATE_##_flg,
+#include <net/mac80211-hwflags.h>
+#undef DEFINE_HWFLAG
+};
+
+static int ieee80211_hwflags_check(unsigned long *flags)
+{
+	unsigned int flg;
+
+	for (flg = 0; flg < NUM_IEEE80211_HW_FLAGS; flg++) {
+		if (hwflags_state[flg] == -1)
+			continue;
+		if (WARN(hwflags_state[flg] != !!test_bit(flg, flags),
+			 "hw flag %d doesn't match Kconfig\n", flg))
+			return -EINVAL;
+	}
+
+	return 0;
+}
+
 int ieee80211_register_hw(struct ieee80211_hw *hw)
 {
 	struct ieee80211_local *local = hw_to_local(hw);
@@ -799,6 +821,9 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
 	netdev_features_t feature_whitelist;
 	struct cfg80211_chan_def dflt_chandef = {};
 
+	if (ieee80211_hwflags_check(local->hw.flags))
+		return -EINVAL;
+
 	if (ieee80211_hw_check(hw, QUEUE_CONTROL) &&
 	    (local->hw.offchannel_tx_hw_queue == IEEE80211_INVAL_HW_QUEUE ||
 	     local->hw.offchannel_tx_hw_queue >= local->hw.queues))
-- 
2.6.2


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [RFC v5 5/5] iwlwifi: mvm: add Kconfig settings for hw flags
  2015-11-12 22:00 [RFC v5 0/5] mac80211: elide code for static hw flags Johannes Berg
                   ` (3 preceding siblings ...)
  2015-11-12 22:00 ` [RFC v5 4/5] mac80211: use Kconfig counters to elide unnecessary code Johannes Berg
@ 2015-11-12 22:00 ` Johannes Berg
  4 siblings, 0 replies; 16+ messages in thread
From: Johannes Berg @ 2015-11-12 22:00 UTC (permalink / raw)
  To: linux-wireless; +Cc: Michal Marek, Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

Copy the hardware flags settings into Kconfig for iwlwifi/mvm.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 drivers/net/wireless/iwlwifi/Kconfig | 18 +++++++++++++++++-
 1 file changed, 17 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index 3fbee1ec1d33..74416361b154 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -65,7 +65,23 @@ config IWLMVM
 	tristate "Intel Wireless WiFi MVM Firmware support"
 	select WANT_DEV_COREDUMP
 	count MAC80211_NUM_DRIVERS
-	select MAC80211_DRIVER_NO_HWFLAGS
+	count MAC80211_HW_SIGNAL_DBM
+	count MAC80211_HW_SPECTRUM_MGMT
+	count MAC80211_HW_REPORTS_TX_ACK_STATUS
+	count MAC80211_HW_QUEUE_CONTROL
+	count MAC80211_HW_WANT_MONITOR_VIF
+	count MAC80211_HW_SUPPORTS_PS
+	count MAC80211_HW_SUPPORTS_DYNAMIC_PS
+	count MAC80211_HW_AMPDU_AGGREGATION
+	count MAC80211_HW_TIMING_BEACON_ONLY
+	count MAC80211_HW_CONNECTION_MONITOR
+	count MAC80211_HW_CHANCTX_STA_CSA
+	count MAC80211_HW_SUPPORT_FAST_XMIT
+	count MAC80211_HW_SUPPORTS_CLONED_SKBS
+	count MAC80211_HW_SINGLE_SCAN_ON_ALL_BANDS
+	select MAC80211_HW_MFP_CAPABLE_DYN
+	select MAC80211_HW_RX_INCLUDES_FCS_DYN
+	select MAC80211_HW_TDLS_WIDER_BW_DYN
 	help
 	  This is the driver that supports the MVM firmware. The list
 	  of the devices that use this firmware is available here:
-- 
2.6.2


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [RFC v5 4/5] mac80211: use Kconfig counters to elide unnecessary code
  2015-11-12 22:00 ` [RFC v5 4/5] mac80211: use Kconfig counters to elide unnecessary code Johannes Berg
@ 2015-11-13  9:48   ` Julian Calaby
  2015-11-13  9:52     ` Johannes Berg
  2015-11-20 15:24   ` Michal Marek
  2015-11-23 14:52   ` Michal Marek
  2 siblings, 1 reply; 16+ messages in thread
From: Julian Calaby @ 2015-11-13  9:48 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless, Michal Marek, Johannes Berg

Hi Johannes,

On Fri, Nov 13, 2015 at 9:00 AM, Johannes Berg
<johannes@sipsolutions.net> wrote:
> From: Johannes Berg <johannes.berg@intel.com>
>
> There are many drivers with different behaviour, but in a lot of
> systems only a single driver will ever be built. In that case we
> can get rid of code paths that this driver doesn't need and also
> optimize the ones that it always takes to not have a check.
>
> To make that possible, make use Kconfig counters to
>  (a) the number of times each feature flag was desired
>  (b) the number of mac80211 drivers built
> and use Kconfig selects to select those flags that any drivers
> need to be dynamic (e.g. if they can only determine this flag's
> setting at runtime.)
>
> If the dynamic request isn't set then
>
>  if (a) > 0 then it was requested ON by at least one driver
>  if (a) < (b) then it was requested OFF by at least one driver
>
> This allows determining whether or not it's safe to elide some
> code entirely.
>
> For added safety, add a HW registration time check for it.
>
> With our iwlwifi/mvm driver, this reduces mac80211's code size
> by just over 6KB (on x86/64), or about 1%. It's not that much,
> but a fair amount of it (just under 1KB) is in the TX/RX/status
> paths which are the hottest code in mac80211.
>
> Signed-off-by: Johannes Berg <johannes.berg@intel.com>
> ---
>  drivers/net/wireless/Kconfig                  |  20 ++++
>  drivers/net/wireless/ath/ar5523/Kconfig       |   2 +
>  drivers/net/wireless/ath/ath10k/Kconfig       |   2 +
>  drivers/net/wireless/ath/ath9k/Kconfig        |   2 +
>  drivers/net/wireless/ath/wcn36xx/Kconfig      |   2 +
>  drivers/net/wireless/b43/Kconfig              |   2 +
>  drivers/net/wireless/b43legacy/Kconfig        |   2 +
>  drivers/net/wireless/brcm80211/Kconfig        |   2 +
>  drivers/net/wireless/cw1200/Kconfig           |   2 +
>  drivers/net/wireless/iwlegacy/Kconfig         |   4 +
>  drivers/net/wireless/iwlwifi/Kconfig          |   4 +
>  drivers/net/wireless/mediatek/mt7601u/Kconfig |   2 +
>  drivers/net/wireless/p54/Kconfig              |   2 +
>  drivers/net/wireless/realtek/rtl818x/Kconfig  |   4 +
>  drivers/net/wireless/realtek/rtl8xxxu/Kconfig |   2 +
>  drivers/net/wireless/realtek/rtlwifi/Kconfig  |   2 +
>  drivers/net/wireless/rsi/Kconfig              |   2 +
>  drivers/net/wireless/rt2x00/Kconfig           |   2 +
>  drivers/net/wireless/ti/wl1251/Kconfig        |   2 +
>  drivers/net/wireless/ti/wl12xx/Kconfig        |   2 +
>  drivers/net/wireless/ti/wl18xx/Kconfig        |   2 +
>  drivers/staging/vt6655/Kconfig                |   2 +
>  drivers/staging/vt6656/Kconfig                |   2 +
>  include/net/mac80211.h                        |  36 +++++-
>  net/mac80211/Kconfig                          |   9 ++
>  net/mac80211/Kconfig.hwflags                  | 160 ++++++++++++++++++++++++++
>  net/mac80211/Makefile                         |   3 +-
>  net/mac80211/main.c                           |  25 ++++
>  28 files changed, 296 insertions(+), 7 deletions(-)
>  create mode 100644 net/mac80211/Kconfig.hwflags
>
> diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
> index f9f94229bf1b..873b6c7b18b8 100644
> --- a/drivers/net/wireless/Kconfig
> +++ b/drivers/net/wireless/Kconfig
> @@ -35,6 +35,8 @@ config PCMCIA_RAYCS
>  config LIBERTAS_THINFIRM
>         tristate "Marvell 8xxx Libertas WLAN driver support with thin firmware"
>         depends on MAC80211
> +       count MAC80211_NUM_DRIVERS
> +       select MAC80211_DRIVER_NO_HWFLAGS

Am I missing something or are you not actually doing anything with
MAC80211_DRIVER_NO_HWFLAGS?

Thanks,

-- 
Julian Calaby

Email: julian.calaby@gmail.com
Profile: http://www.google.com/profiles/julian.calaby/

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC v5 4/5] mac80211: use Kconfig counters to elide unnecessary code
  2015-11-13  9:48   ` Julian Calaby
@ 2015-11-13  9:52     ` Johannes Berg
  2015-11-13  9:55       ` Johannes Berg
  0 siblings, 1 reply; 16+ messages in thread
From: Johannes Berg @ 2015-11-13  9:52 UTC (permalink / raw)
  To: Julian Calaby; +Cc: linux-wireless, Michal Marek

On Fri, 2015-11-13 at 20:48 +1100, Julian Calaby wrote:
> 
> Am I missing something or are you not actually doing anything with
> MAC80211_DRIVER_NO_HWFLAGS?
> 

Crap. I meant to pass it to the macro like this (I think):

#define __DEFINE_HWFLAG(_flg, _dyn, _on, _off)                         \
       HWFLAGS_STATE_##_flg = -1 + (!(_dyn)) * (((_on) ^ (_off)) * (1 + (_on))),
#define DEFINE_HWFLAG(_flg)                                            \
       __DEFINE_HWFLAG(_flg,                                           \
                       IS_ENABLED(CONFIG_MAC80211_HW_##_flg##_DYN) ||  \
                       (CONFIG_MAC80211_DRIVER_NO_HWFLAGS > 0),        \
                       CONFIG_MAC80211_HW_##_flg > 0,                  \
                       CONFIG_MAC80211_HW_##_flg < CONFIG_MAC80211_NUM_DRIVERS)

I'll take a closer look.

FWIW, I pushed this into the hwflags-elide branch in mac80211-next.git
(kernel.org) - will update there (also already fixed a compile issue)

johannes

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC v5 4/5] mac80211: use Kconfig counters to elide unnecessary code
  2015-11-13  9:52     ` Johannes Berg
@ 2015-11-13  9:55       ` Johannes Berg
  0 siblings, 0 replies; 16+ messages in thread
From: Johannes Berg @ 2015-11-13  9:55 UTC (permalink / raw)
  To: Julian Calaby; +Cc: linux-wireless, Michal Marek

On Fri, 2015-11-13 at 10:52 +0100, Johannes Berg wrote:
> 
>                        (CONFIG_MAC80211_DRIVER_NO_HWFLAGS > 0),      

Of course not, it's a bool. Anyway, thanks!

johannes
> 

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC v5 4/5] mac80211: use Kconfig counters to elide unnecessary code
  2015-11-12 22:00 ` [RFC v5 4/5] mac80211: use Kconfig counters to elide unnecessary code Johannes Berg
  2015-11-13  9:48   ` Julian Calaby
@ 2015-11-20 15:24   ` Michal Marek
  2015-11-20 15:29     ` Johannes Berg
  2015-11-23 14:52   ` Michal Marek
  2 siblings, 1 reply; 16+ messages in thread
From: Michal Marek @ 2015-11-20 15:24 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless, Johannes Berg

On 2015-11-12 23:00, Johannes Berg wrote:
> +	count MAC80211_NUM_DRIVERS
> +	select MAC80211_DRIVER_NO_HWFLAGS

Hi Johannes,

The MAC80211_DRIVER_NO_HWFLAGS config does not seem to be used anywhere
in the logic.

Michal

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC v5 4/5] mac80211: use Kconfig counters to elide unnecessary code
  2015-11-20 15:24   ` Michal Marek
@ 2015-11-20 15:29     ` Johannes Berg
  2015-11-20 16:37       ` Michal Marek
  0 siblings, 1 reply; 16+ messages in thread
From: Johannes Berg @ 2015-11-20 15:29 UTC (permalink / raw)
  To: Michal Marek; +Cc: linux-wireless

On Fri, 2015-11-20 at 16:24 +0100, Michal Marek wrote:
> On 2015-11-12 23:00, Johannes Berg wrote:
> > +	count MAC80211_NUM_DRIVERS
> > +	select MAC80211_DRIVER_NO_HWFLAGS
> 
> Hi Johannes,
> 
> The MAC80211_DRIVER_NO_HWFLAGS config does not seem to be used
> anywhere in the logic.
> 

Yeah, I forgot in this version. I have an updated one at

https://git.kernel.org/cgit/linux/kernel/git/jberg/mac80211-next.git/lo
g/?h=hwflags-elide

haven't sent it yet though because I'm not really sure it's worth it at
all?

johannes

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC v5 4/5] mac80211: use Kconfig counters to elide unnecessary code
  2015-11-20 15:29     ` Johannes Berg
@ 2015-11-20 16:37       ` Michal Marek
  0 siblings, 0 replies; 16+ messages in thread
From: Michal Marek @ 2015-11-20 16:37 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless

On 2015-11-20 16:29, Johannes Berg wrote:
> On Fri, 2015-11-20 at 16:24 +0100, Michal Marek wrote:
>> On 2015-11-12 23:00, Johannes Berg wrote:
>>> +	count MAC80211_NUM_DRIVERS
>>> +	select MAC80211_DRIVER_NO_HWFLAGS
>>
>> Hi Johannes,
>>
>> The MAC80211_DRIVER_NO_HWFLAGS config does not seem to be used
>> anywhere in the logic.
>>
> 
> Yeah, I forgot in this version. I have an updated one at
> 
> https://git.kernel.org/cgit/linux/kernel/git/jberg/mac80211-next.git/lo
> g/?h=hwflags-elide


OK.

> haven't sent it yet though because I'm not really sure it's worth it at
> all?

I did not have time to look at your series until today.

Michal

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC v5 4/5] mac80211: use Kconfig counters to elide unnecessary code
  2015-11-12 22:00 ` [RFC v5 4/5] mac80211: use Kconfig counters to elide unnecessary code Johannes Berg
  2015-11-13  9:48   ` Julian Calaby
  2015-11-20 15:24   ` Michal Marek
@ 2015-11-23 14:52   ` Michal Marek
  2015-11-23 14:58     ` Johannes Berg
  2 siblings, 1 reply; 16+ messages in thread
From: Michal Marek @ 2015-11-23 14:52 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless, Johannes Berg

On 2015-11-12 23:00, Johannes Berg wrote:
> From: Johannes Berg <johannes.berg@intel.com>
> 
> There are many drivers with different behaviour, but in a lot of
> systems only a single driver will ever be built. In that case we
> can get rid of code paths that this driver doesn't need and also
> optimize the ones that it always takes to not have a check.
> 
> To make that possible, make use Kconfig counters to
>  (a) the number of times each feature flag was desired
>  (b) the number of mac80211 drivers built
> and use Kconfig selects to select those flags that any drivers
> need to be dynamic (e.g. if they can only determine this flag's
> setting at runtime.)
> 
> If the dynamic request isn't set then
> 
>  if (a) > 0 then it was requested ON by at least one driver
>  if (a) < (b) then it was requested OFF by at least one driver

So one issue with this logic is that it is not safe to build and use an
out-of-tree mac80211 driver after the kernel has been built. Also, any
new driver needs the 'count MAC80211_NUM_DRIVERS' annotation, but there
is the runtime check to catch omissions. Since this is targeting users
of very specific configs, how about an opt-in scheme à la

- User has to select CONFIG_MAC80211_SINGLE_DRIVER, the help text
  explains the caveats and lists drivers known to work in such mode.
- mac80211 uses the Kconfig-defined constants + dynamic bits iff
  CONFIG_MAC80211_SINGLE_DRIVER=y, otherwise it behaves as before.
- Some build- or compile-time check ensuring that we are not building /
  loading multiple drivers with CONFIG_MAC80211_SINGLE_DRIVER=y.

? It's not very robust either, but at least it would only be used by
those who know what they are doing.

Michal

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC v5 4/5] mac80211: use Kconfig counters to elide unnecessary code
  2015-11-23 14:52   ` Michal Marek
@ 2015-11-23 14:58     ` Johannes Berg
  2015-11-23 15:06       ` Michal Marek
  0 siblings, 1 reply; 16+ messages in thread
From: Johannes Berg @ 2015-11-23 14:58 UTC (permalink / raw)
  To: Michal Marek; +Cc: linux-wireless

On Mon, 2015-11-23 at 15:52 +0100, Michal Marek wrote:
> 
> So one issue with this logic is that it is not safe to build and use an
> out-of-tree mac80211 driver after the kernel has been built. Also, any
> new driver needs the 'count MAC80211_NUM_DRIVERS' annotation, but there
> is the runtime check to catch omissions. 

Indeed, the runtime check will catch both of these.

> Since this is targeting users
> of very specific configs, how about an opt-in scheme à la
> 
> - User has to select CONFIG_MAC80211_SINGLE_DRIVER, the help text
>   explains the caveats and lists drivers known to work in such mode.
> - mac80211 uses the Kconfig-defined constants + dynamic bits iff
>   CONFIG_MAC80211_SINGLE_DRIVER=y, otherwise it behaves as before.
> - Some build- or compile-time check ensuring that we are not building /
>   loading multiple drivers with CONFIG_MAC80211_SINGLE_DRIVER=y.

That'd be possible - but I know of at least one potential use case that
would like to have two similar drivers, with similar flags: some
routers ship with ath9k hardware for the 2.4 GHz band and ath10k
hardware for the 5 GHz band. Doing "single-driver" and avoiding the
counters would not allow those to have any kind of optimisation, and
such low-power platforms are the ones who'd most likely benefit from
it...

That said, we really do need to figure out whether this makes sense at
all.

I'd actually Cc'ed you out of confusion, thinking you were maintaining
kconfig. I guess I really should've Cc'ed Yann instead.

johannes

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC v5 4/5] mac80211: use Kconfig counters to elide unnecessary code
  2015-11-23 14:58     ` Johannes Berg
@ 2015-11-23 15:06       ` Michal Marek
  2015-11-23 15:15         ` Johannes Berg
  0 siblings, 1 reply; 16+ messages in thread
From: Michal Marek @ 2015-11-23 15:06 UTC (permalink / raw)
  To: Johannes Berg; +Cc: linux-wireless

On 2015-11-23 15:58, Johannes Berg wrote:
> On Mon, 2015-11-23 at 15:52 +0100, Michal Marek wrote:
>>  
>> So one issue with this logic is that it is not safe to build and use an
>> out-of-tree mac80211 driver after the kernel has been built. Also, any
>> new driver needs the 'count MAC80211_NUM_DRIVERS' annotation, but there
>> is the runtime check to catch omissions. 
> 
> Indeed, the runtime check will catch both of these.

Will it catch the former case? The driver built out of has not way to
select or increment any of the CONFIG_MAC80211_* options.


>> Since this is targeting users
>> of very specific configs, how about an opt-in scheme à la
>>
>> - User has to select CONFIG_MAC80211_SINGLE_DRIVER, the help text
>>   explains the caveats and lists drivers known to work in such mode.
>> - mac80211 uses the Kconfig-defined constants + dynamic bits iff
>>   CONFIG_MAC80211_SINGLE_DRIVER=y, otherwise it behaves as before.
>> - Some build- or compile-time check ensuring that we are not building /
>>   loading multiple drivers with CONFIG_MAC80211_SINGLE_DRIVER=y.
> 
> That'd be possible - but I know of at least one potential use case that
> would like to have two similar drivers, with similar flags: some
> routers ship with ath9k hardware for the 2.4 GHz band and ath10k
> hardware for the 5 GHz band. Doing "single-driver" and avoiding the
> counters would not allow those to have any kind of optimisation, and
> such low-power platforms are the ones who'd most likely benefit from
> it...

I see.


> I'd actually Cc'ed you out of confusion, thinking you were maintaining
> kconfig. I guess I really should've Cc'ed Yann instead.

That's fine. It is a very interesting problem :-).

Michal


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [RFC v5 4/5] mac80211: use Kconfig counters to elide unnecessary code
  2015-11-23 15:06       ` Michal Marek
@ 2015-11-23 15:15         ` Johannes Berg
  0 siblings, 0 replies; 16+ messages in thread
From: Johannes Berg @ 2015-11-23 15:15 UTC (permalink / raw)
  To: Michal Marek; +Cc: linux-wireless

On Mon, 2015-11-23 at 16:06 +0100, Michal Marek wrote:
> 
> > Indeed, the runtime check will catch both of these.
> 
> Will it catch the former case? The driver built out of has not way to
> select or increment any of the CONFIG_MAC80211_* options.

Correct, but ieee80211_hwflags_check() will verify that the flags are
compatible with the compilation settings, regardless of the respective
source. Note that our preferred way of working out-of-tree is backports
anyway and that ships with mac80211 and cfg80211 due to the relatively
tight coupling between all the pieces.

In any case - consider first compiling mac80211 with a driver that does
"count CONFIG_HWFLAG_XYZ", and no other drivers. This means
that hwflags_state[XYZ] will end up as 1. So once the other (out-of-
tree) driver is registered, it'll pass hw->flags with the bit of XYZ
not set. This would cause a warning and refusal to register
in ieee80211_hwflags_check().

johannes

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2015-11-23 15:15 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-11-12 22:00 [RFC v5 0/5] mac80211: elide code for static hw flags Johannes Berg
2015-11-12 22:00 ` [RFC v5 1/5] kconfig: introduce "count" Johannes Berg
2015-11-12 22:00 ` [RFC v5 2/5] kconfig: regenerate the shipped files Johannes Berg
2015-11-12 22:00 ` [RFC v5 3/5] mac80211: generate hw flags from include file Johannes Berg
2015-11-12 22:00 ` [RFC v5 4/5] mac80211: use Kconfig counters to elide unnecessary code Johannes Berg
2015-11-13  9:48   ` Julian Calaby
2015-11-13  9:52     ` Johannes Berg
2015-11-13  9:55       ` Johannes Berg
2015-11-20 15:24   ` Michal Marek
2015-11-20 15:29     ` Johannes Berg
2015-11-20 16:37       ` Michal Marek
2015-11-23 14:52   ` Michal Marek
2015-11-23 14:58     ` Johannes Berg
2015-11-23 15:06       ` Michal Marek
2015-11-23 15:15         ` Johannes Berg
2015-11-12 22:00 ` [RFC v5 5/5] iwlwifi: mvm: add Kconfig settings for hw flags Johannes Berg

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.