diff --git a/tools/kconfig2html.c b/tools/kconfig2html.c index 6a0745674ab..05e09663d8c 100644 --- a/tools/kconfig2html.c +++ b/tools/kconfig2html.c @@ -57,6 +57,7 @@ #define MAX_DEPENDENCIES 100 #define MAX_LEVELS 100 #define MAX_SELECT 16 +#define MAX_DEFAULTS 80 #define TAB_SIZE 4 #define VAR_SIZE 80 #define HTML_VAR_SIZE (2*VAR_SIZE + 64) @@ -114,9 +115,14 @@ enum error_e ERROR_OUTFILE_OPEN_FAILURE, ERROR_TMPFILE_OPEN_FAILURE, ERROR_KCONFIG_OPEN_FAILURE, + ERROR_TOO_MANY_DEFAULTS, + ERROR_MISSING_DEFAULT_VALUE, + ERROR_GARBAGE_AFTER_DEFAULT, + ERROR_DEFAULT_UNDERFLOW, ERROR_TOO_MANY_SELECT, ERROR_TOO_MANY_DEPENDENCIES, ERROR_DEPENDENCIES_UNDERFLOW, + ERRROR_MISSING_ON_AFTER_DEPENDS, ERRROR_ON_AFTER_DEPENDS, ERROR_NESTING_TOO_DEEP, ERROR_NESTING_UNDERFLOW @@ -125,40 +131,50 @@ enum error_e struct reserved_s { enum token_type_e ttype; - const char *tname; + const char *tname; }; -union value_u +struct default_item_s { - char *s; - int i; - bool b; + char *ddefault; + char *ddependency; +}; + +struct default_s +{ + int dnitems; + struct default_item_s ditem[MAX_DEFAULTS]; +}; + +struct select_s +{ + int snvar; + char *svarname[MAX_SELECT]; }; struct config_s { enum config_type_e ctype; - char *cname; - char *cdesc; - char *cdefault; - char *clower; - char *cupper; - char *cselect[MAX_SELECT]; - int cnselect; - int cndependencies; + char *cname; + char *cdesc; + char *clower; + char *cupper; + struct default_s cdefault; + struct select_s cselect; + int cndependencies; }; struct choice_s { - char *cprompt; - char *cdefault; - int cndependencies; + char *cprompt; + struct default_s cdefault; + int cndependencies; }; struct menu_s { - char *mname; - int mndependencies; + char *mname; + int mndependencies; }; /**************************************************************************** @@ -169,7 +185,7 @@ static char g_line[LINE_SIZE+1]; static char g_scratch[SCRATCH_SIZE+1]; static FILE *g_outfile; static FILE *g_tmpfile; -static char *g_lasts; +static char *g_lnptr; static bool g_debug; static bool g_internal; static bool g_preread; @@ -183,6 +199,8 @@ static int g_inchoice; static int g_menu_number; static int g_choice_number; +static const char g_delimiters[] = " ,"; + static struct reserved_s g_reserved[] = { {TOKEN_COMMENT, "comment"}, @@ -596,6 +614,8 @@ static char *read_line(FILE *stream) char *ptr; int len; + g_lnptr = NULL; + /* Read the next line */ g_line[LINE_SIZE] = '\0'; @@ -629,6 +649,7 @@ static char *read_line(FILE *stream) { /* No.. return now */ + g_lnptr = g_line; return g_line; } @@ -703,6 +724,7 @@ static char *kconfig_line(FILE *stream) ptr = skip_space(g_line); if (*ptr && *ptr != '#' && *ptr != '\n') { + g_lnptr = ptr; return ptr; } } @@ -731,84 +753,6 @@ static enum token_type_e tokenize(const char *token) return ptr->ttype; } -/**************************************************************************** - * Name: MY_strtok_r - * - * Description: - * A replacement that can be used if your platform does not support strtok_r. - * - ****************************************************************************/ - -#ifndef HAVE_STRTOK_R -static char *MY_strtok_r(char *str, const char *delim, char **saveptr) -{ - char *pbegin; - char *pend = NULL; - - /* Decide if we are starting a new string or continuing from - * the point we left off. - */ - - if (str) - { - pbegin = str; - } - else if (saveptr && *saveptr) - { - pbegin = *saveptr; - } - else - { - return NULL; - } - - /* Find the beginning of the next token */ - - for (; - *pbegin && strchr(delim, *pbegin) != NULL; - pbegin++); - - /* If we are at the end of the string with nothing - * but delimiters found, then return NULL. - */ - - if (!*pbegin) - { - return NULL; - } - - /* Find the end of the token */ - - for (pend = pbegin + 1; - *pend && strchr(delim, *pend) == NULL; - pend++); - - /* pend either points to the end of the string or to - * the first delimiter after the string. - */ - - if (*pend) - { - /* Turn the delimiter into a null terminator */ - - *pend++ = '\0'; - } - - /* Save the pointer where we left off and return the - * beginning of the token. - */ - - if (saveptr) - { - *saveptr = pend; - } - - return pbegin; -} - -#define strtok_r MY_strtok_r -#endif - /**************************************************************************** * Name: findchar * @@ -851,38 +795,117 @@ static char *findchar(char *ptr, char ch) } /**************************************************************************** - * Name: getstring + * Name: get_token * * Description: - * Extract a quoted string + * Get the next delimited token from the line buffer. * ****************************************************************************/ -static char *getstring(char *ptr) +static char *get_token(void) { - char *endptr; + char *pbegin; + char *pend = NULL; - /* Search for the leading quotation mark */ + /* The position to begin/resume parsing is in g_lnptr. */ - ptr = findchar(ptr, '"'); - if (ptr) + if (g_lnptr && *g_lnptr) + { + pbegin = g_lnptr; + } + else + { + return NULL; + } + + /* Find the beginning of the next token */ + + for (; + *pbegin && strchr(g_delimiters, *pbegin) != NULL; + pbegin++); + + /* If we are at the end of the string with nothing + * but delimiters found, then return NULL. + */ + + if (!*pbegin) + { + g_lnptr = pbegin; + return NULL; + } + + /* Get if the token is a quoted string */ + + if (*pbegin == '"') + { + /* Search for the trailing quotation mark */ + + pend = findchar(pbegin + 1, '"'); + } + else + { + /* Find the end of the token */ + + for (pend = pbegin + 1; + *pend && strchr(g_delimiters, *pend) == NULL; + pend++); + } + + /* pend either points to the end of the string or to + * the first delimiter after the string. + */ + + if (*pend) + { + /* Turn the delimiter into a null terminator */ + + *pend++ = '\0'; + } + + /* Save the pointer where we left off and return the + * beginning of the token. + */ + + g_lnptr = pend; + return pbegin; +} + +/**************************************************************************** + * Name: get_html_string + * + * Description: + * Extract a quoted string from the line buffer, dequote it, and make it + * HTML ready. + * + ****************************************************************************/ + +static char *get_html_string(void) +{ + char *pbegin; + char *pend; + + /* Search for the leading quotation mark in the line buffer */ + + pbegin = strchr(g_lnptr, '"'); + if (pbegin) { /* Skip over the quote */ - ptr++; + pbegin++; /* Search for the trailing quotation mark */ - endptr = findchar(ptr, '"'); - if (endptr) + pend = findchar(pbegin, '"'); + if (pend) { /* Replace the final quote with a NUL */ - *endptr = '\0'; + *pend = '\0'; } } - return htmlize_text(ptr); + g_lnptr = pend + 1; + return htmlize_text(pbegin); } /**************************************************************************** @@ -1183,6 +1206,168 @@ static inline void process_help(FILE *stream) } } +/**************************************************************************** + * Name: process_default + * + * Description: + * Read and parse the Kconfig default statement. + * + ****************************************************************************/ + +static void process_default(FILE *stream, struct default_s *defp) +{ + enum token_type_e tokid; + char *token; + int ndx; + + /* Check if we have space for another default value */ + + ndx = defp->dnitems; + if (ndx >= MAX_DEFAULTS) + { + error("Too many default values\n"); + exit(ERROR_TOO_MANY_DEFAULTS); + } + + /* Get the next token which will be the value of the default */ + + token = get_token(); + if (!token) + { + error("Missing default value\n"); + exit(ERROR_MISSING_DEFAULT_VALUE); + } + + defp->ditem[ndx].ddefault = strdup(token); + defp->ditem[ndx].ddependency = NULL; + + /* Check if the default value is followed by "depends on" */ + + token = get_token(); + if (token) + { + /* Yes.. something follows the default value. */ + + tokid = tokenize(token); + if (tokid != TOKEN_IF) + { + error("Unrecognized garbage after default value\n"); + exit(ERROR_GARBAGE_AFTER_DEFAULT); + } + + /* The rest of the line is the dependency */ + + defp->ditem[ndx].ddependency = strdup(g_lnptr); + } + + /* Update the number of defaults we have encountered in this block */ + + defp->dnitems++; +} + +/**************************************************************************** + * Name: print_default + * + * Description: + * Output and the list of defaults to the the HTML body file. + * + ****************************************************************************/ + +static void print_default(struct default_s *defp) +{ + struct default_item_s *item; + int i; + + /* Check if there are any default value */ + + if (defp->dnitems > 0) + { + /* Yes, output the defaults differently if there is only one */ + + if (defp->dnitems == 1) + { + /* Output the Default */ + + item = &defp->ditem[0]; + body("
\n"); + body(" Dependency:\n"); + body(" %s\n", htmlize_expression(item->ddependency)); + body("
\n"); + } + + body("\n"); + body(" Dependency:\n"); + body(" %s\n", htmlize_expression(item->ddependency)); + body("
\n"); + } + } + + body("CONFIG_%s\n\n");
- body(" Maintaining this Document.\n");
+ body(" Overview.\n");
body(" The NuttX RTOS is highly configurable.\n");
body(" The NuttX configuration files are maintained using the kconfig-frontends tool.\n");
body(" That configuration tool uses Kconfig files that can be found through the NuttX source tree.\n");
@@ -2241,7 +2408,7 @@ int main(int argc, char **argv, char **envp)
body(" This configurable options are descrived in this document.\n");
body("
\n");
- body(" NOTE:\n");
+ body(" Mainenance Note.\n");
body(" This documenation was auto-generated using the kconfig2html tool\n");
body(" That tools analyzes the NuttX Kconfig and generates this HTML document.\n");
body(" This HTML document file should not be editted manually.\n");