More kconfg2html logic

This commit is contained in:
Gregory Nutt 2013-04-20 17:05:45 -06:00
parent 27c28f542e
commit 8cbca09f94
2 changed files with 331 additions and 63 deletions

View file

@ -50,7 +50,7 @@ config WINDOWS_NATIVE
config WINDOWS_CYGWIN
bool "Cygwin"
- --help---
---help---
Build natively in a Cygwin environment with POSIX style paths (like /cygdrive/c/cgywin/home)
config WINDOWS_MSYS

View file

@ -56,6 +56,7 @@
#define SCRATCH_SIZE 1024
#define MAX_DEPENDENCIES 100
#define MAX_LEVELS 100
#define MAX_SELECT 16
#define TAB_SIZE 4
#define TMPFILE_NAME "kconfig2html-tmp.dat"
@ -68,13 +69,20 @@ enum token_type_e
{
TOKEN_NONE = 0,
TOKEN_NOTRESERVED,
TOKEN_COMMENT,
TOKEN_CONFIG,
TOKEN_MENUCONFIG,
TOKEN_BOOL,
TOKEN_INT,
TOKEN_HEX,
TOKEN_STRING,
TOKEN_DEFAULT,
TOKEN_SELECT,
TOKEN_DEPENDS,
TOKEN_ON,
TOKEN_OPTION,
TOKEN_HELP,
TOKEN_MAINMENU,
TOKEN_MENU,
TOKEN_ENDMENU,
TOKEN_CHOICE,
@ -103,8 +111,10 @@ enum error_e
ERROR_OUTFILE_OPEN_FAILURE,
ERROR_TMPFILE_OPEN_FAILURE,
ERROR_KCONFIG_OPEN_FAILURE,
ERROR_TOO_MANY_SELECT,
ERROR_TOO_MANY_DEPENDENCIES,
ERROR_DEPENDENCIES_UNDERFLOW,
ERRROR_ON_AFTER_DEPENDS,
ERROR_NESTING_TOO_DEEP,
ERROR_NESTING_UNDERFLOW
};
@ -128,12 +138,22 @@ struct config_s
char *cname;
char *cdesc;
char *cdefault;
char *cselect[MAX_SELECT];
int cnselect;
int cndependencies;
};
struct choice_s
{
char *cprompt;
char *cdefault;
int cndependencies;
};
struct menu_s
{
char *mname;
int mndependencies;
};
/****************************************************************************
@ -160,14 +180,21 @@ static int g_choice_number;
static struct reserved_s g_reserved[] =
{
{TOKEN_COMMENT, "comment"},
{TOKEN_CONFIG, "config"},
{TOKEN_MENUCONFIG, "menuconfig"},
{TOKEN_BOOL, "bool"},
{TOKEN_INT, "int"},
{TOKEN_HEX, "hex"},
{TOKEN_STRING, "string"},
{TOKEN_DEFAULT, "default"},
{TOKEN_SELECT, "select"},
{TOKEN_DEPENDS, "depends"},
{TOKEN_ON, "on"},
{TOKEN_OPTION, "option"},
{TOKEN_HELP, "help"},
{TOKEN_HELP, "---help---"},
{TOKEN_MAINMENU, "mainmenu"},
{TOKEN_MENU, "menu"},
{TOKEN_ENDMENU, "endmenu"},
{TOKEN_CHOICE, "choice"},
@ -202,7 +229,7 @@ static void show_usage(const char *progname, int exitcode)
fprintf(stderr, "Where:\n\n");
fprintf(stderr, "\t-a : Select relative path to the apps/ directory. Theis path is relative\n");
fprintf(stderr, "\t to the <Kconfig directory>. Default: ../apps\n");
fprintf(stderr, "\t-o : Send output to <out file>. Default: Output goes to stdout\n");
fprintf(stderr, "\t-o : Send output to <out file>. Default: Output goes to stdout\n");
fprintf(stderr, "\t-i : Show hidden, internal configuration variables\n");
fprintf(stderr, "\t-d : Enable debug output\n");
fprintf(stderr, "\t-h : Prints this message and exits\n");
@ -869,6 +896,7 @@ static inline char *process_config(FILE *stream, const char *configname,
const char *paranum;
char *token;
char *ptr;
int i;
/* Get the configuration information */
@ -978,6 +1006,46 @@ static inline char *process_config(FILE *stream, const char *configname,
}
break;
case TOKEN_SELECT:
{
char *value;
int ndx;
ndx = config.cnselect + 1;
if (ndx > MAX_SELECT)
{
fprintf(stderr, "Too many 'select' lines\n");
exit(ERROR_TOO_MANY_SELECT);
}
value = strtok_r(NULL, " ", &g_lasts);
config.cselect[ndx] = strdup(value);
config.cnselect = ndx;
token = NULL;
}
break;
case TOKEN_DEPENDS:
{
char *value = strtok_r(NULL, " ", &g_lasts);
if (strcmp(value, "on") != 0)
{
fprintf(stderr, "Expected \"on\" after \"depends\"\n");
exit(ERRROR_ON_AFTER_DEPENDS);
}
push_dependency(g_lasts);
config.cndependencies++;
token = NULL;
}
break;
case TOKEN_OPTION:
{
token = NULL; /* Ignored */
}
break;
case TOKEN_HELP:
{
help = true;
@ -987,7 +1055,7 @@ static inline char *process_config(FILE *stream, const char *configname,
default:
{
debug("Unhandled token: %s\n", token);
debug("Terminating token: %s\n", token);
}
break;
}
@ -1051,27 +1119,43 @@ static inline char *process_config(FILE *stream, const char *configname,
if (config.ctype != VALUE_NONE)
{
body(" <li><i>Type</i>: %s</li>\n", type2str(config.ctype));
body(" <li><i>Type</i>: %s</li>\n", type2str(config.ctype));
}
/* Print the default value of the configuration variable */
if (config.cdefault)
{
body(" <li><i>Default</i>: %s</li>\n", config.cdefault);
body(" <li><i>Default</i>: %s</li>\n", config.cdefault);
}
/* Print the default value of the configuration variable auto-selected by this setting */
if (config.cnselect > 0)
{
body(" <li><i>Selects</i>: <a href=\"CONFIG_%s\">CONFIG_%s</a>",
config.cselect[0], config.cselect[0]);
for (i = 1; i < config.cnselect; i++)
{
body(", <a href=\"CONFIG_%s\">CONFIG_%s</a>",
config.cselect[i], config.cselect[i]);
}
body("</li>\n");
}
/* Print the list of dependencies (if any) */
if (g_ndependencies > 0)
{
int i;
body(" <li><i>Dependencies</i>: %s", g_dependencies[0]);
for (i = 1; i < g_ndependencies; i++)
{
body(", %s\n", g_dependencies[i]);
}
body("</li>\n");
}
@ -1096,6 +1180,13 @@ static inline char *process_config(FILE *stream, const char *configname,
body("</ul>\n");
}
/* Remove any dependencies that apply only to this configuration */
for (i = 0; i < config.cndependencies; i++)
{
pop_dependency();
}
/* Free allocated memory */
if (config.cname)
@ -1113,6 +1204,14 @@ static inline char *process_config(FILE *stream, const char *configname,
free(config.cdefault);
}
if (config.cnselect > 0)
{
for (i = 0; i < config.cnselect; i++)
{
free(config.cselect[i]);
}
}
return token;
}
@ -1130,8 +1229,10 @@ static inline char *process_choice(FILE *stream, const char *kconfigdir)
enum token_type_e tokid;
struct choice_s choice;
const char *paranum;
char *token;
char *token = NULL;
char *ptr;
bool help;
int i;
/* Get the choice information */
@ -1174,42 +1275,104 @@ static inline char *process_choice(FILE *stream, const char *kconfigdir)
}
break;
case TOKEN_DEPENDS:
{
char *value = strtok_r(NULL, " ", &g_lasts);
if (strcmp(value, "on") != 0)
{
fprintf(stderr, "Expected \"on\" after \"depends\"\n");
exit(ERRROR_ON_AFTER_DEPENDS);
}
push_dependency(g_lasts);
choice.cndependencies++;
token = NULL;
}
break;
case TOKEN_HELP:
{
help = true;
token = NULL;
}
break;
default:
{
debug("Unhandled token: %s\n", token);
debug("Terminating token: %s\n", token);
}
break;
}
/* Break out on the first unhandled token */
/* Break out on the help token (or the first unhandled token) */
if (token != NULL)
if (help || token != NULL)
{
break;
}
}
}
paranum = get_paranum();
output("<li><a href=\"#choice_%d\">%s Choice", g_choice_number, paranum);
body("\n<h3><a name=\"choice_%d\">%s Choice", g_choice_number, paranum);
if (choice.cprompt)
{
output(": %s", choice.cprompt);
body(": %s", choice.cprompt);
}
paranum = get_paranum();
output("<li><a href=\"#choice_%d\">%s Choice", g_choice_number, paranum);
body("\n<h3><a name=\"choice_%d\">%s Choice", g_choice_number, paranum);
output("</a></li>\n");
body("</a></h3>\n");
g_choice_number++;
if (choice.cprompt)
{
output(": %s", choice.cprompt);
body(": %s", choice.cprompt);
}
output("</a></li>\n");
body("</a></h3>\n");
g_choice_number++;
/* Show the default */
body("<ul>\n");
if (choice.cdefault)
{
body(" <li><i>Default</i>: <code>CONFIG_%s</code>\n</li>", choice.cdefault);
}
/* Print the list of dependencies (if any) */
if (g_ndependencies > 0)
{
body(" <li><i>Dependencies</i>: %s", g_dependencies[0]);
for (i = 1; i < g_ndependencies; i++)
{
body(", %s\n", g_dependencies[i]);
}
body("</li>\n");
}
/* Show the configuration file */
body("<p><i>Kconfig file</i>: <code>%s/Kconfig</code>\n</p>", kconfigdir);
body("<p><i>Options</i>:</p>", kconfigdir);
body(" <li><i>Kconfig file</i>: <code>%s/Kconfig</code>\n</li>", kconfigdir);
/* Print any help text */
if (help)
{
process_help(stream);
token = NULL;
}
body("</ul>\n");
/* Then show the choice options */
body("<p><b>Choice Options:</b></p>", kconfigdir);
body("<ul>\n");
/* Remove any dependencies that apply only to this configuration */
for (i = 0; i < choice.cndependencies; i++)
{
pop_dependency();
}
/* Free allocated memory */
if (choice.cprompt)
@ -1226,14 +1389,142 @@ static inline char *process_choice(FILE *stream, const char *kconfigdir)
incr_level();
debug("process_choice: Recursing for TOKEN_CHOICE\n");
debug("process_choice: TOKEN_CHOICE\n");
debug(" kconfigdir: %s\n", kconfigdir);
debug(" level: %d\n", g_level);
/* Then recurse */
/* Then return in choice mode */
g_inchoice++;
return parse_kconfigfile(stream, kconfigdir);
return token;
}
/****************************************************************************
* Name: process_menu
*
* Description:
* Process a menu paragraph
*
****************************************************************************/
static inline char *process_menu(FILE *stream, const char *kconfigdir)
{
enum token_type_e tokid;
struct menu_s menu;
const char *paranum;
char *menuname;
char *token = NULL;
char *ptr;
int i;
/* Get the menu information */
memset(&menu, 0, sizeof(struct menu_s));
/* Get the menu name */
menuname = getstring(g_lasts);
menu.mname = strdup(menuname);
/* Process each line in the choice */
while ((ptr = read_line(stream)) != NULL)
{
/* Process the first token on the Kconfig file line */
g_lasts = NULL;
token = strtok_r(ptr, " ", &g_lasts);
if (token != NULL)
{
tokid = tokenize(token);
switch (tokid)
{
case TOKEN_DEPENDS:
{
char *value = strtok_r(NULL, " ", &g_lasts);
if (strcmp(value, "on") != 0)
{
fprintf(stderr, "Expected \"on\" after \"depends\"\n");
exit(ERRROR_ON_AFTER_DEPENDS);
}
push_dependency(g_lasts);
menu.mndependencies++;
token = NULL;
}
break;
default:
{
debug("Terminating token: %s\n", token);
}
break;
}
/* Break out on the first unhandled token */
if (token != NULL)
{
break;
}
}
}
/* Output menu information */
paranum = get_paranum();
if (menuname)
{
output("<li><a href=\"#menu_%d\">%s Menu: %s</a></li>\n",
g_menu_number, paranum, menuname);
output("<ul>\n");
body("\n<h1><a name=\"menu_%d\">%s Menu: %s</a></h1>\n",
g_menu_number, paranum, menuname);
}
else
{
output("<li><a href=\"#menu_%d\">%s Menu</a></li>\n",
g_menu_number, paranum);
body("\n<h1><a name=\"menu_%d\">%s Menu</a></h1>\n",
g_menu_number, paranum);
}
/* Print the list of dependencies (if any) */
if (g_ndependencies > 0)
{
body("<ul>\n");
body(" <li><i>Dependencies</i>: %s", g_dependencies[0]);
for (i = 1; i < g_ndependencies; i++)
{
body(", %s\n", g_dependencies[i]);
}
body("</li>\n");
body("</ul>\n");
}
g_menu_number++;
/* Remove any dependencies that apply only to this configuration */
for (i = 0; i < menu.mndependencies; i++)
{
pop_dependency();
}
/* Increment the nesting level */
incr_level();
debug("process_menu: TOKEN_MENU\n");
debug(" kconfigdir: %s\n", kconfigdir);
debug(" level: %d\n", g_level);
/* Return the terminating token */
return token;
}
/****************************************************************************
@ -1248,8 +1539,7 @@ static void process_kconfigfile(const char *kconfigdir); /* Forward reference */
static char *parse_kconfigfile(FILE *stream, const char *kconfigdir)
{
enum token_type_e tokid;
const char *paranum;
char *token;
char *token = NULL;
char *ptr;
/* Process each line in the Kconfig file */
@ -1314,45 +1604,23 @@ static char *parse_kconfigfile(FILE *stream, const char *kconfigdir)
break;
case TOKEN_CONFIG:
case TOKEN_MENUCONFIG:
{
char *configname = strtok_r(NULL, " ", &g_lasts);
token = process_config(stream, configname, kconfigdir);
}
break;
case TOKEN_COMMENT:
case TOKEN_MAINMENU:
{
token = NULL; /* ignored */
}
break;
case TOKEN_MENU:
{
char *menuname = getstring(g_lasts);
paranum = get_paranum();
if (menuname)
{
output("<li><a href=\"#menu_%d\">%s Menu: %s</a></li>\n",
g_menu_number, paranum, menuname);
output("<ul>\n");
body("\n<h1><a name=\"menu_%d\">%s Menu: %s</a></h1>\n",
g_menu_number, paranum, menuname);
}
else
{
output("<li><a href=\"#menu_%d\">%s Menu</a></li>\n",
g_menu_number, paranum);
body("\n<h1><a name=\"menu_%d\">%s Menu</a></h1>\n",
g_menu_number, paranum);
}
g_menu_number++;
/* Increment the nesting level */
incr_level();
debug("parse_kconfigfile: Recursing for TOKEN_MENU\n");
debug(" kconfigdir: %s\n", kconfigdir);
debug(" level: %d\n", g_level);
/* Then recurse */
token = parse_kconfigfile(stream, kconfigdir);
token = process_menu(stream, kconfigdir);
}
break;
@ -1373,7 +1641,7 @@ static char *parse_kconfigfile(FILE *stream, const char *kconfigdir)
decr_level();
incr_paranum();
return NULL;
token = NULL;
}
break;
@ -1387,7 +1655,7 @@ static char *parse_kconfigfile(FILE *stream, const char *kconfigdir)
decr_level();
incr_paranum();
return NULL;
token = NULL;
}
break;