2013-04-20 19:42:59 +02:00
/****************************************************************************
* tools / kconfig2html . c
*
* Copyright ( C ) 2013 Gregory Nutt . All rights reserved .
* Author : Gregory Nutt < gnutt @ nuttx . org >
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
*
* 1. Redistributions of source code must retain the above copyright
* notice , this list of conditions and the following disclaimer .
* 2. Redistributions in binary form must reproduce the above copyright
* notice , this list of conditions and the following disclaimer in
* the documentation and / or other materials provided with the
* distribution .
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission .
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* " AS IS " AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT
* LIMITED TO , THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT , INDIRECT ,
* INCIDENTAL , SPECIAL , EXEMPLARY , OR CONSEQUENTIAL DAMAGES ( INCLUDING ,
* BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES ; LOSS
* OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION ) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT , STRICT
* LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/****************************************************************************
* Included Files
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# include <stdbool.h>
# include <stdio.h>
# include <stdlib.h>
# include <stdarg.h>
# include <unistd.h>
# include <time.h>
# include <string.h>
# include <ctype.h>
# include <libgen.h>
# include <errno.h>
/****************************************************************************
* Pre - processor Definitions
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-04-23 19:01:18 +02:00
# undef USE_JQUERY
2013-04-20 19:42:59 +02:00
# define LINE_SIZE 1024
2013-04-22 19:20:54 +02:00
# define SCRATCH_SIZE 2048
2013-04-20 19:42:59 +02:00
# define MAX_DEPENDENCIES 100
# define MAX_LEVELS 100
2014-06-16 18:58:38 +02:00
# define MAX_SELECT 64
2013-10-28 21:59:32 +01:00
# define MAX_DEFAULTS 128
2013-04-20 22:18:08 +02:00
# define TAB_SIZE 4
2013-04-21 19:01:46 +02:00
# define VAR_SIZE 80
# define HTML_VAR_SIZE (2*VAR_SIZE + 64)
2013-04-20 19:42:59 +02:00
2013-04-22 19:20:54 +02:00
# define BODYFILE_NAME ".k2h-body.dat"
# define APNDXFILE_NAME ".k2h-apndx.dat"
2013-04-20 19:42:59 +02:00
/****************************************************************************
* Private Types
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
enum token_type_e
{
TOKEN_NONE = 0 ,
TOKEN_NOTRESERVED ,
2013-04-21 01:05:45 +02:00
TOKEN_COMMENT ,
2013-04-20 19:42:59 +02:00
TOKEN_CONFIG ,
2013-04-21 01:05:45 +02:00
TOKEN_MENUCONFIG ,
2013-04-20 19:42:59 +02:00
TOKEN_BOOL ,
TOKEN_INT ,
TOKEN_HEX ,
TOKEN_STRING ,
TOKEN_DEFAULT ,
2013-04-21 01:29:10 +02:00
TOKEN_RANGE ,
2013-04-21 01:05:45 +02:00
TOKEN_SELECT ,
TOKEN_DEPENDS ,
TOKEN_ON ,
TOKEN_OPTION ,
2013-04-20 19:42:59 +02:00
TOKEN_HELP ,
2013-04-21 01:05:45 +02:00
TOKEN_MAINMENU ,
2013-04-20 19:42:59 +02:00
TOKEN_MENU ,
TOKEN_ENDMENU ,
TOKEN_CHOICE ,
TOKEN_ENDCHOICE ,
2013-04-20 22:18:08 +02:00
TOKEN_PROMPT ,
2013-04-20 19:42:59 +02:00
TOKEN_IF ,
TOKEN_ENDIF ,
TOKEN_SOURCE
} ;
enum config_type_e
{
VALUE_NONE = 0 ,
VALUE_INT ,
VALUE_HEX ,
VALUE_BOOL ,
VALUE_STRING
} ;
enum error_e
{
ERROR_UNRECOGNIZED_OPTION = 1 ,
ERROR_MISSING_OPTION_ARGUMENT ,
ERROR_UNEXPECTED_OPTION ,
ERROR_TOO_MANY_ARGUMENTS ,
ERROR_OUTFILE_OPEN_FAILURE ,
2013-04-22 19:20:54 +02:00
ERROR_BODYFILE_OPEN_FAILURE ,
ERROR_APNDXFILE_OPEN_FAILURE ,
2013-04-20 19:42:59 +02:00
ERROR_KCONFIG_OPEN_FAILURE ,
2013-04-22 19:20:54 +02:00
ERROR_APPENDFILE_OPEN_FAILURE ,
2013-04-22 21:58:02 +02:00
ERROR_MENU_LEVEL_UNDERRUN ,
2013-04-22 15:22:55 +02:00
ERROR_TOO_MANY_DEFAULTS ,
ERROR_MISSING_DEFAULT_VALUE ,
ERROR_GARBAGE_AFTER_DEFAULT ,
ERROR_DEFAULT_UNDERFLOW ,
2013-04-21 01:05:45 +02:00
ERROR_TOO_MANY_SELECT ,
2013-04-20 19:42:59 +02:00
ERROR_TOO_MANY_DEPENDENCIES ,
ERROR_DEPENDENCIES_UNDERFLOW ,
2013-04-22 15:22:55 +02:00
ERRROR_MISSING_ON_AFTER_DEPENDS ,
2013-04-21 01:05:45 +02:00
ERRROR_ON_AFTER_DEPENDS ,
2013-04-20 19:42:59 +02:00
ERROR_NESTING_TOO_DEEP ,
ERROR_NESTING_UNDERFLOW
} ;
2013-04-22 19:20:54 +02:00
typedef void ( * output_t ) ( const char * fmt , . . . ) ;
2013-04-20 19:42:59 +02:00
struct reserved_s
{
enum token_type_e ttype ;
2013-04-22 15:22:55 +02:00
const char * tname ;
2013-04-20 19:42:59 +02:00
} ;
2013-04-22 15:22:55 +02:00
struct default_item_s
2013-04-20 19:42:59 +02:00
{
2013-04-22 19:20:54 +02:00
char * d_default ;
char * d_dependency ;
2013-04-22 15:22:55 +02:00
} ;
struct default_s
{
2013-04-22 19:20:54 +02:00
int d_nitems ;
struct default_item_s d_item [ MAX_DEFAULTS ] ;
2013-04-22 15:22:55 +02:00
} ;
struct select_s
{
2013-04-22 19:20:54 +02:00
int s_nvar ;
char * s_varname [ MAX_SELECT ] ;
2013-04-20 19:42:59 +02:00
} ;
struct config_s
{
2013-04-22 19:20:54 +02:00
enum config_type_e c_type ;
char * c_name ;
char * c_desc ;
char * c_lower ;
char * c_upper ;
struct default_s c_default ;
struct select_s c_select ;
int c_ndependencies ;
2013-04-20 19:42:59 +02:00
} ;
2013-04-20 22:18:08 +02:00
struct choice_s
{
2013-04-22 19:20:54 +02:00
char * c_prompt ;
struct default_s c_default ;
int c_ndependencies ;
2013-04-21 01:05:45 +02:00
} ;
struct menu_s
{
2013-04-22 19:20:54 +02:00
char * m_name ;
int m_ndependencies ;
2013-04-20 22:18:08 +02:00
} ;
2013-04-20 19:42:59 +02:00
/****************************************************************************
* Private Data
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static char g_line [ LINE_SIZE + 1 ] ;
static char g_scratch [ SCRATCH_SIZE + 1 ] ;
static FILE * g_outfile ;
2013-04-22 19:20:54 +02:00
static FILE * g_bodyfile ;
static FILE * g_apndxfile ;
2013-04-22 15:22:55 +02:00
static char * g_lnptr ;
2013-04-20 19:42:59 +02:00
static bool g_debug ;
2013-04-20 22:18:08 +02:00
static bool g_preread ;
2013-04-20 19:42:59 +02:00
static const char * g_kconfigroot ;
static const char * g_appsdir ;
static int g_paranum [ MAX_LEVELS ] ;
static int g_level ;
static char * g_dependencies [ MAX_DEPENDENCIES ] ;
static int g_ndependencies ;
static int g_inchoice ;
static int g_menu_number ;
static int g_choice_number ;
2013-04-22 21:58:02 +02:00
static int g_toggle_number ;
2013-04-20 19:42:59 +02:00
2013-04-22 15:22:55 +02:00
static const char g_delimiters [ ] = " , " ;
2013-04-20 19:42:59 +02:00
static struct reserved_s g_reserved [ ] =
{
2013-04-21 01:05:45 +02:00
{ TOKEN_COMMENT , " comment " } ,
2013-04-20 19:42:59 +02:00
{ TOKEN_CONFIG , " config " } ,
2013-04-21 01:05:45 +02:00
{ TOKEN_MENUCONFIG , " menuconfig " } ,
2013-04-20 19:42:59 +02:00
{ TOKEN_BOOL , " bool " } ,
{ TOKEN_INT , " int " } ,
{ TOKEN_HEX , " hex " } ,
{ TOKEN_STRING , " string " } ,
{ TOKEN_DEFAULT , " default " } ,
2013-04-21 01:29:10 +02:00
{ TOKEN_RANGE , " range " } ,
2013-04-21 01:05:45 +02:00
{ TOKEN_SELECT , " select " } ,
{ TOKEN_DEPENDS , " depends " } ,
{ TOKEN_ON , " on " } ,
{ TOKEN_OPTION , " option " } ,
2013-04-20 19:42:59 +02:00
{ TOKEN_HELP , " help " } ,
{ TOKEN_HELP , " ---help--- " } ,
2013-04-21 01:05:45 +02:00
{ TOKEN_MAINMENU , " mainmenu " } ,
2013-04-20 19:42:59 +02:00
{ TOKEN_MENU , " menu " } ,
{ TOKEN_ENDMENU , " endmenu " } ,
{ TOKEN_CHOICE , " choice " } ,
{ TOKEN_ENDCHOICE , " endchoice " } ,
2013-04-20 22:18:08 +02:00
{ TOKEN_PROMPT , " prompt " } ,
2013-04-20 19:42:59 +02:00
{ TOKEN_SOURCE , " source " } ,
{ TOKEN_IF , " if " } ,
{ TOKEN_ENDIF , " endif " } ,
{ TOKEN_NOTRESERVED , NULL } /* Terminates list */
} ;
/****************************************************************************
* Public Data
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/****************************************************************************
* Private Functions
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-04-20 22:18:08 +02:00
/****************************************************************************
2013-04-21 17:37:45 +02:00
* Name : debug
2013-04-20 22:18:08 +02:00
*
* Description :
2013-04-21 17:37:45 +02:00
* Debug output ( conditional )
2013-04-20 22:18:08 +02:00
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-04-21 17:37:45 +02:00
static void debug ( const char * fmt , . . . )
2013-04-20 19:42:59 +02:00
{
2013-04-21 17:37:45 +02:00
va_list ap ;
2013-04-20 19:42:59 +02:00
2013-04-21 17:37:45 +02:00
if ( g_debug )
{
va_start ( ap , fmt ) ;
( void ) vfprintf ( stderr , fmt , ap ) ;
va_end ( ap ) ;
}
2013-04-20 19:42:59 +02:00
}
2013-04-20 22:18:08 +02:00
/****************************************************************************
2013-04-21 17:37:45 +02:00
* Name : error
2013-04-20 22:18:08 +02:00
*
* Description :
2013-04-21 17:37:45 +02:00
* Error output ( unconditional )
2013-04-20 22:18:08 +02:00
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-04-20 19:42:59 +02:00
2013-04-21 17:37:45 +02:00
static void error ( const char * fmt , . . . )
2013-04-20 19:42:59 +02:00
{
va_list ap ;
2013-04-21 17:37:45 +02:00
va_start ( ap , fmt ) ;
( void ) vfprintf ( stderr , fmt , ap ) ;
va_end ( ap ) ;
2013-04-20 19:42:59 +02:00
}
2013-04-20 22:18:08 +02:00
/****************************************************************************
* Name : output
*
* Description :
* Output to the final HTML file
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-04-20 19:42:59 +02:00
static void output ( const char * fmt , . . . )
{
va_list ap ;
va_start ( ap , fmt ) ;
( void ) vfprintf ( g_outfile , fmt , ap ) ;
va_end ( ap ) ;
}
2013-04-20 22:18:08 +02:00
/****************************************************************************
* Name : body
*
* Description :
* HTML body output to a temporary file .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-04-20 19:42:59 +02:00
static void body ( const char * fmt , . . . )
{
va_list ap ;
va_start ( ap , fmt ) ;
2013-04-22 19:20:54 +02:00
( void ) vfprintf ( g_bodyfile , fmt , ap ) ;
2013-04-20 19:42:59 +02:00
va_end ( ap ) ;
}
2013-04-22 19:20:54 +02:00
/****************************************************************************
* Name : appendix
*
* Description :
* Output to a appendix file .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void appendix ( const char * fmt , . . . )
{
va_list ap ;
va_start ( ap , fmt ) ;
( void ) vfprintf ( g_apndxfile , fmt , ap ) ;
va_end ( ap ) ;
}
/****************************************************************************
* Name : append_file
*
* Description :
* Append the specified file to the output file and remove it .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void append_file ( const char * filename )
{
FILE * stream ;
int ch ;
/* Open the file for reading */
stream = fopen ( filename , " r " ) ;
if ( ! stream )
{
error ( " open %s failed: %s \n " , filename , strerror ( errno ) ) ;
exit ( ERROR_APPENDFILE_OPEN_FAILURE ) ;
}
/* Copy the file to the output */
while ( ( ch = getc ( stream ) ) ! = EOF )
{
( void ) putc ( ch , g_outfile ) ;
}
/* Close and remove the file */
fclose ( stream ) ;
unlink ( filename ) ;
}
2013-04-21 17:37:45 +02:00
/****************************************************************************
* Name : show_usage
*
* Description :
* Show usage of this program and exit with the specified error code
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void show_usage ( const char * progname , int exitcode )
{
2013-04-22 19:20:54 +02:00
error ( " USAGE: %s [-d] [-a <apps directory>] {-o <out file>] [<Kconfig root>] \n " , progname ) ;
2013-04-21 17:37:45 +02:00
error ( " %s [-h] \n \n " , progname ) ;
error ( " Where: \n \n " ) ;
error ( " \t -a : Select relative path to the apps/ directory. Theis path is relative \n " ) ;
error ( " \t to the <Kconfig directory>. Default: ../apps \n " ) ;
error ( " \t -o : Send output to <out file>. Default: Output goes to stdout \n " ) ;
error ( " \t -d : Enable debug output \n " ) ;
error ( " \t -h : Prints this message and exits \n " ) ;
error ( " \t <Kconfig root> is the directory containing the root Kconfig file. \n " ) ;
error ( " \t Default <Kconfig directory>: . \n " ) ;
exit ( exitcode ) ;
}
/****************************************************************************
* Name : skip_space
*
* Description :
* Skip over any spaces
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static char * skip_space ( char * ptr )
{
while ( * ptr & & isspace ( ( int ) * ptr ) ) ptr + + ;
return ptr ;
}
2013-04-20 22:18:08 +02:00
/****************************************************************************
* Name : dequote
*
* Description :
* Remove quotation marks from a string .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-04-20 19:42:59 +02:00
static char * dequote ( char * ptr )
{
int len ;
/* Check if there is a traiing quote */
len = strlen ( ptr ) ;
if ( ptr [ len - 1 ] = = ' " ' )
{
/* Yes... replace it with a terminator */
ptr [ len - 1 ] = ' \0 ' ;
len - - ;
}
/* Is there a leading quote? */
if ( ptr [ 0 ] = = ' " ' )
{
/* Yes.. skip over the leading quote */
ptr + + ;
len - - ;
}
/* Handle the case where nothing is left after dequoting */
if ( len < = 0 )
{
ptr = NULL ;
}
return ptr ;
}
2013-04-21 17:37:45 +02:00
/****************************************************************************
2013-04-21 19:01:46 +02:00
* Name : htmlize_character
2013-04-21 17:37:45 +02:00
*
* Description :
2013-04-21 19:01:46 +02:00
* Transfer and HTML - ize a character . Convert characters :
2013-04-21 17:37:45 +02:00
*
* " " quotation mark
2013-04-21 19:01:46 +02:00
* ' & apos ; apostrophe
2013-04-21 17:37:45 +02:00
* & & amp ; ampersand
* < & lt ; less - than
* > & gt ; greater - than
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-04-21 19:01:46 +02:00
static int htmlize_character ( char * dest , char ch )
2013-04-21 17:37:45 +02:00
{
const char * str ;
2013-04-21 19:01:46 +02:00
/* Transfer the character from into the destination buffer, perform the
2013-08-27 17:40:19 +02:00
* conversion only if the character is one of the special characters .
2013-04-21 19:01:46 +02:00
*/
str = NULL ;
switch ( ch )
{
case ' " ' :
str = " " " ;
break ;
case ' \' ' :
str = " ' " ;
break ;
case ' & ' :
str = " & " ;
break ;
case ' < ' :
str = " < " ;
break ;
case ' > ' :
str = " > " ;
break ;
default :
* dest + + = ch ;
* dest = ' \0 ' ;
return 1 ;
}
/* Transfer a string */
* dest = ' \0 ' ;
strcat ( dest , str ) ;
return strlen ( str ) ;
}
/****************************************************************************
* Name : htmlize_text
*
* Description :
* HTML - ize a free - text string . This function preforms the conversions of
* in htmlize_character ( ) for a text string .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static char * htmlize_text ( const char * src )
{
char * dest = g_scratch ;
2013-04-23 19:25:52 +02:00
/* We may get here with the source pointer equal to NULL (or a pointer to
* a NUL string ) . Return the
2013-04-21 19:01:46 +02:00
* disfavor .
*/
2013-04-23 19:25:52 +02:00
if ( ! src | | ! * src )
2013-04-21 19:01:46 +02:00
{
return NULL ;
}
/* Transfer each character from the source string into the scratch buffer */
for ( ; * src ; src + + )
{
2013-04-22 19:20:54 +02:00
/* Expand characters as necessary. NOTE: There is no check if the
* HTML - expanded text overflows the g_scratch [ ] buffer . If you see
* errors , be suspicous .
*/
2013-04-21 19:01:46 +02:00
dest + = htmlize_character ( dest , * src ) ;
}
return g_scratch ;
}
/****************************************************************************
* Name : htmlize_expression
*
* Description :
* HTML - ize an expression of configuration variables . This function
* preforms the same conversions as in htmlize_character ( ) , but also
* expands and adds hyper links for configuration variables .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static char * htmlize_expression ( const char * src )
{
char varname [ VAR_SIZE + 1 ] ;
char htmlvar [ HTML_VAR_SIZE + 1 ] ;
char * dest = g_scratch ;
char ch = ' \0 ' ;
char lastc ;
2013-04-21 17:37:45 +02:00
/* We may get here with the source pointer equal to NULL. Return the
* disfavor .
*/
if ( ! src )
{
return NULL ;
}
/* Transfer each character from the source string into the scratch buffer */
dest = g_scratch ;
* dest = ' \0 ' ;
2013-04-21 19:01:46 +02:00
while ( * src )
2013-04-21 17:37:45 +02:00
{
2013-04-21 19:01:46 +02:00
/* Remember the last character and advance to the next character */
lastc = ch ;
ch = * src ;
2013-04-21 17:37:45 +02:00
2013-04-21 19:01:46 +02:00
/* Skip control characters and out-of-range 7-bit ASCII characters */
if ( * src < 0x20 | | * src > 0x7e )
2013-04-21 17:37:45 +02:00
{
2013-04-21 19:01:46 +02:00
src + + ;
continue ;
}
2013-04-21 17:37:45 +02:00
2013-04-21 19:01:46 +02:00
/* Output no more than one consecutive space character. This depends
* on the fact that kconfig_line has replaces all of the forms of
* whitespace with a space character .
*/
2013-04-21 17:37:45 +02:00
2013-04-21 19:01:46 +02:00
if ( * src = = ' ' )
{
if ( lastc ! = ' ' )
{
* dest + + = * src ;
* dest = ' \0 ' ;
}
2013-04-21 17:37:45 +02:00
2013-04-21 19:01:46 +02:00
src + + ;
continue ;
}
2013-04-21 17:37:45 +02:00
2013-04-21 19:01:46 +02:00
/* Concatenate variable name strings. There strings probably begin
* with a uppercase letter , but here all alphanumeric values ( plus ' _ ' _
* are concatenated .
*/
2013-04-21 17:37:45 +02:00
2013-04-21 19:01:46 +02:00
if ( isalnum ( ( ( int ) * src ) ) | | * src = = ' _ ' )
{
int namlen = 0 ;
do
{
/* Don't overflow the tiny variable name buffer */
if ( namlen > = VAR_SIZE )
{
error ( " Configuration variable name too long \n " ) ;
break ;
}
/* Add the next character to the name */
varname [ namlen ] = * src + + ;
namlen + + ;
varname [ namlen ] = ' \0 ' ;
}
while ( isalnum ( ( ( int ) * src ) ) | | * src = = ' _ ' ) ;
/* HTML-ize the name into our bigger, local scratch buffer */
snprintf ( htmlvar , HTML_VAR_SIZE , " <a href= \" #CONFIG_%s \" ><code>CONFIG_%s</code></a> " ,
varname , varname ) ;
/* Then transfer the string into the scratch buffer */
strcat ( dest , htmlvar ) ;
dest + = strlen ( htmlvar ) ;
2013-04-21 17:37:45 +02:00
}
2013-04-21 19:01:46 +02:00
/* All that remains are space and the punctuation characters */
else
{
/* Expand characters as necessary */
2013-04-21 17:37:45 +02:00
2013-04-21 19:01:46 +02:00
dest + = htmlize_character ( dest , * src ) ;
src + + ;
}
2013-04-21 17:37:45 +02:00
}
return g_scratch ;
}
2013-04-20 22:18:08 +02:00
/****************************************************************************
* Name : read_line
*
* Description :
2013-04-21 17:37:45 +02:00
* Read a new line from the Kconfig file into the g_line [ ] buffer , using
* the g_scratch buffer if necessary to concatenate lines that end with a
* line continuation character ( backslash ) .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static char * read_line ( FILE * stream )
{
char * ptr ;
int len ;
2013-04-22 15:22:55 +02:00
g_lnptr = NULL ;
2013-04-21 17:37:45 +02:00
/* Read the next line */
g_line [ LINE_SIZE ] = ' \0 ' ;
if ( ! fgets ( g_line , LINE_SIZE , stream ) )
{
return NULL ;
}
/* Loop to handle continuation lines */
2014-04-12 21:28:22 +02:00
for ( ; ; )
2013-04-21 17:37:45 +02:00
{
/* How long is the line so far? */
len = strlen ( g_line ) ;
/* Remove any newline character at the end of the buffer */
if ( g_line [ len - 1 ] = = ' \n ' )
{
len - - ;
g_line [ len ] = ' \0 ' ;
}
/* Does this continue on the next line? Note taht this check
* could erroneoulsy combine two lines if a comment line ends with
* a line continuation . . . Don ' t do that !
*/
if ( g_line [ len - 1 ] ! = ' \\ ' )
{
/* No.. return now */
2013-04-22 15:22:55 +02:00
g_lnptr = g_line ;
2013-04-21 17:37:45 +02:00
return g_line ;
}
/* Yes.. Replace the backslash with a space delimiter */
g_line [ len - 1 ] = ' ' ;
/* Read the next line into the scratch buffer */
g_scratch [ SCRATCH_SIZE ] = ' \0 ' ;
if ( ! fgets ( g_scratch , SCRATCH_SIZE , stream ) )
{
return NULL ;
}
/* Skip any leading whitespace and copy the rest of the next line
* into the line buffer . Note that the leading white space is
* replaced with a single character to serve as a delimiter .
*/
ptr = skip_space ( g_scratch ) ;
strncpy ( & g_line [ len ] , ptr , LINE_SIZE - len ) ;
}
}
/****************************************************************************
* Name : kconfig_line
*
* Description :
2013-04-20 22:18:08 +02:00
* Read a new line , skipping over leading white space and ignore lines
* that contain only comments .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-04-21 17:37:45 +02:00
static char * kconfig_line ( FILE * stream )
2013-04-20 19:42:59 +02:00
{
char * ptr ;
for ( ; ; )
{
2013-04-21 17:37:45 +02:00
/* Read the next line from the Kconfig file */
2013-04-20 22:18:08 +02:00
/* Is there already valid data in the line buffer? This can happen while parsing
* help text and we read one line too far .
*/
2013-04-20 19:42:59 +02:00
2013-04-20 22:18:08 +02:00
if ( ! g_preread )
{
2013-04-21 17:37:45 +02:00
/* Read the next line */
if ( ! read_line ( stream ) )
2013-04-20 19:42:59 +02:00
{
2013-04-20 22:18:08 +02:00
return NULL ;
2013-04-20 19:42:59 +02:00
}
2013-04-20 22:18:08 +02:00
}
g_preread = false ;
2013-04-20 19:42:59 +02:00
2013-04-20 22:18:08 +02:00
/* Replace all whitespace characters with spaces to simplify parsing */
2013-04-20 19:42:59 +02:00
2013-04-20 22:18:08 +02:00
for ( ptr = g_line ; * ptr ; ptr + + )
{
if ( isspace ( ( ( int ) * ptr ) ) )
2013-04-20 19:42:59 +02:00
{
2013-04-20 22:18:08 +02:00
* ptr = ' ' ;
2013-04-20 19:42:59 +02:00
}
}
2013-04-20 22:18:08 +02:00
/* Skip any leading whitespace. Ignore empty lines and lines that
* contain only comments .
*/
ptr = skip_space ( g_line ) ;
if ( * ptr & & * ptr ! = ' # ' & & * ptr ! = ' \n ' )
{
2013-04-22 15:22:55 +02:00
g_lnptr = ptr ;
2013-04-20 22:18:08 +02:00
return ptr ;
}
2013-04-20 19:42:59 +02:00
}
}
2013-04-20 22:18:08 +02:00
/****************************************************************************
* Name : tokenize
*
* Description :
* Check if this string corresponds to a string in the reserved word table .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-04-20 19:42:59 +02:00
2013-04-20 22:18:08 +02:00
static enum token_type_e tokenize ( const char * token )
2013-04-20 19:42:59 +02:00
{
struct reserved_s * ptr ;
for ( ptr = g_reserved ; ptr - > tname ; ptr + + )
{
if ( strcmp ( token , ptr - > tname ) = = 0 )
{
break ;
}
}
return ptr - > ttype ;
}
2013-04-20 22:18:08 +02:00
/****************************************************************************
2013-04-22 15:22:55 +02:00
* Name : findchar
2013-04-20 22:18:08 +02:00
*
* Description :
2013-04-22 15:22:55 +02:00
* Find a character in a string . This differs from strchr ( ) because it
* skips over quoted characters . For example , if you are searching for
* ' " ' , encountering ' " ' will terminate the search , but " \" " will not .
2013-04-20 22:18:08 +02:00
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-04-22 15:22:55 +02:00
static char * findchar ( char * ptr , char ch )
2013-04-20 19:42:59 +02:00
{
2013-04-22 15:22:55 +02:00
bool escaped = false ;
2013-04-20 19:42:59 +02:00
2013-04-22 15:22:55 +02:00
/* Search for the leading quotation marked */
2013-04-20 19:42:59 +02:00
2013-04-22 15:22:55 +02:00
for ( ; * ptr ; ptr + + )
2013-04-20 19:42:59 +02:00
{
2013-04-22 15:22:55 +02:00
if ( escaped )
{
/* Skip over this character and reset the escaped flag */
escaped = false ;
}
else if ( * ptr = = ' \\ ' )
{
/* Set the escaped flag to skip over the next character */
escaped = true ;
}
else if ( * ptr = = ch )
{
/* We have found the (unescaped) character we are looking for */
return ptr ;
}
2013-04-20 19:42:59 +02:00
}
2013-04-22 15:22:55 +02:00
return NULL ;
}
/****************************************************************************
* Name : get_token
*
* Description :
* Get the next delimited token from the line buffer .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static char * get_token ( void )
{
char * pbegin ;
char * pend = NULL ;
/* The position to begin/resume parsing is in g_lnptr. */
if ( g_lnptr & & * g_lnptr )
2013-04-20 19:42:59 +02:00
{
2013-04-22 15:22:55 +02:00
pbegin = g_lnptr ;
2013-04-20 19:42:59 +02:00
}
else
{
return NULL ;
}
/* Find the beginning of the next token */
for ( ;
2013-04-22 15:22:55 +02:00
* pbegin & & strchr ( g_delimiters , * pbegin ) ! = NULL ;
2013-04-20 19:42:59 +02:00
pbegin + + ) ;
/* If we are at the end of the string with nothing
* but delimiters found , then return NULL .
*/
if ( ! * pbegin )
{
2013-04-22 15:22:55 +02:00
g_lnptr = pbegin ;
2013-04-20 19:42:59 +02:00
return NULL ;
}
2013-04-22 15:22:55 +02:00
/* Get if the token is a quoted string */
2013-04-20 19:42:59 +02:00
2013-04-22 15:22:55 +02:00
if ( * pbegin = = ' " ' )
{
/* Search for the trailing quotation mark */
pend = findchar ( pbegin + 1 , ' " ' ) ;
2013-04-23 19:01:18 +02:00
/* Did we find the trailing quotation mark */
if ( pend )
{
/* Yes.. skip over it */
pend + + ;
}
2013-04-22 15:22:55 +02:00
}
else
{
/* Find the end of the token */
for ( pend = pbegin + 1 ;
* pend & & strchr ( g_delimiters , * pend ) = = NULL ;
pend + + ) ;
}
2013-04-20 19:42:59 +02:00
/* 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 .
*/
2013-04-22 15:22:55 +02:00
g_lnptr = pend ;
2013-04-20 19:42:59 +02:00
return pbegin ;
}
2013-04-20 22:18:08 +02:00
/****************************************************************************
2013-04-22 15:22:55 +02:00
* Name : get_html_string
2013-04-20 22:18:08 +02:00
*
* Description :
2013-04-22 15:22:55 +02:00
* Extract a quoted string from the line buffer , dequote it , and make it
* HTML ready .
2013-04-20 22:18:08 +02:00
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-04-22 15:22:55 +02:00
static char * get_html_string ( void )
2013-04-20 19:42:59 +02:00
{
2013-04-22 15:22:55 +02:00
char * pbegin ;
char * pend ;
2013-04-23 19:25:52 +02:00
int len ;
2013-04-20 19:42:59 +02:00
2013-04-22 15:22:55 +02:00
/* Search for the leading quotation mark in the line buffer */
2013-04-20 19:42:59 +02:00
2013-04-22 15:22:55 +02:00
pbegin = strchr ( g_lnptr , ' " ' ) ;
if ( pbegin )
2013-04-20 19:42:59 +02:00
{
2013-04-23 19:01:18 +02:00
/* We found the leading quote. Skip over the leading quote */
2013-04-20 19:42:59 +02:00
2013-04-22 15:22:55 +02:00
pbegin + + ;
2013-04-23 19:01:18 +02:00
}
else
{
/* The string is unquoted. The beginning of the string is here,
* skipping over any leading whitespace .
*/
2013-04-20 19:42:59 +02:00
2013-04-23 19:01:18 +02:00
pbegin = skip_space ( g_lnptr ) ;
}
2013-04-20 19:42:59 +02:00
2013-04-23 19:01:18 +02:00
/* Search for the trailing quotation mark. If there is none, then
* the string goes to the end of the line .
*/
2013-04-20 19:42:59 +02:00
2013-04-23 19:01:18 +02:00
pend = findchar ( pbegin , ' " ' ) ;
if ( pend )
{
/* Replace the final quote with a NUL. g_lnptr is set to to
* the next valid character after the terminating quote .
*/
* pend = ' \0 ' ;
g_lnptr = pend + 1 ;
}
else
{
2013-04-23 19:25:52 +02:00
/* Get the length of the string. Return NULL if all that is
* left on the line is a NUL string .
*/
len = strlen ( pbegin ) ;
if ( len < 1 )
{
return NULL ;
}
2013-04-23 19:01:18 +02:00
/* Use the rest of the line. g_lnptr is set to point at the
* terminating NUL .
*/
2013-04-23 19:25:52 +02:00
pend = pbegin + len ;
2013-04-23 19:01:18 +02:00
g_lnptr = pend ;
2013-04-20 19:42:59 +02:00
}
2013-04-22 15:22:55 +02:00
return htmlize_text ( pbegin ) ;
2013-04-20 19:42:59 +02:00
}
2013-04-20 22:18:08 +02:00
/****************************************************************************
* Name : push_dependency
*
* Description :
* Add the new dependency to the current list of dependencies .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-04-20 19:42:59 +02:00
static void push_dependency ( const char * dependency )
{
int ndx = g_ndependencies ;
if ( ndx > = MAX_DEPENDENCIES )
{
2013-04-21 17:37:45 +02:00
error ( " Too many dependencies, aborting \n " ) ;
2013-04-20 19:42:59 +02:00
exit ( ERROR_TOO_MANY_DEPENDENCIES ) ;
}
g_dependencies [ ndx ] = strdup ( dependency ) ;
g_ndependencies = ndx + 1 ;
}
2013-04-20 22:18:08 +02:00
/****************************************************************************
* Name : pop_dependency
*
* Description :
* Remove the last , pushed dependency
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-04-20 19:42:59 +02:00
static void pop_dependency ( void )
{
int ndx = g_ndependencies - 1 ;
if ( ndx < 0 )
{
2013-04-21 17:37:45 +02:00
error ( " Dependency underflow, aborting \n " ) ;
2013-04-20 19:42:59 +02:00
exit ( ERROR_DEPENDENCIES_UNDERFLOW ) ;
}
if ( g_dependencies [ ndx ] )
{
free ( g_dependencies [ ndx ] ) ;
g_dependencies [ ndx ] = NULL ;
}
g_ndependencies = ndx ;
}
2013-04-20 22:18:08 +02:00
/****************************************************************************
* Name : incr_level
*
* Description :
* Increment the paragraph numbering level
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-04-20 19:42:59 +02:00
static void incr_level ( void )
{
int ndx = g_level ;
if ( ndx > = MAX_LEVELS )
{
2013-04-21 17:37:45 +02:00
error ( " Nesting level is too deep, aborting \n " ) ;
2013-04-20 19:42:59 +02:00
exit ( ERROR_NESTING_TOO_DEEP ) ;
}
g_paranum [ ndx ] = 1 ;
g_level = ndx + 1 ;
}
2013-04-20 22:18:08 +02:00
/****************************************************************************
* Name : decr_level
*
* Description :
* Decrease the paragraph numbering level .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-04-20 19:42:59 +02:00
static void decr_level ( void )
{
int ndx = g_level ;
g_paranum [ ndx ] = ' \0 ' ;
ndx - - ;
if ( ndx < 0 )
{
2013-04-21 17:37:45 +02:00
error ( " Nesting level underflow, aborting \n " ) ;
2013-04-20 19:42:59 +02:00
exit ( ERROR_NESTING_UNDERFLOW ) ;
}
g_level = ndx ;
}
2013-04-20 22:18:08 +02:00
/****************************************************************************
* Name : incr_paranum
*
* Description :
* Increment the paragraph number at this level
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-04-20 19:42:59 +02:00
static void incr_paranum ( void )
{
int ndx = g_level - 1 ;
if ( ndx < 0 )
{
2013-04-21 17:37:45 +02:00
error ( " Nesting level underflow, aborting \n " ) ;
2013-04-20 19:42:59 +02:00
exit ( ERROR_NESTING_UNDERFLOW ) ;
}
g_paranum [ ndx ] + + ;
}
2013-04-20 22:18:08 +02:00
/****************************************************************************
* Name : get_paranum
*
* Description :
* Return a string for this paragraph ( uses g_scratch [ ] ) .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-04-20 19:42:59 +02:00
static const char * get_paranum ( void )
{
char buffer [ 16 ] ;
int i ;
g_scratch [ 0 ] = ' \0 ' ;
for ( i = 0 ; i < g_level ; i + + )
{
if ( i > 0 )
{
strcat ( g_scratch , " . " ) ;
}
snprintf ( buffer , 16 , " %d " , g_paranum [ i ] ) ;
strcat ( g_scratch , buffer ) ;
}
return g_scratch ;
}
2013-04-20 22:18:08 +02:00
/****************************************************************************
* Name : type2str
*
* Description :
* Return a string given a member of the configuration variable type
* enumeration .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-04-20 19:42:59 +02:00
static const char * type2str ( enum config_type_e valtype )
{
switch ( valtype )
{
case VALUE_BOOL :
return " Boolean " ;
case VALUE_INT :
return " Integer " ;
case VALUE_HEX :
return " Hexadecimal " ;
case VALUE_STRING :
return " String " ;
default :
break ;
}
return " Unknown " ;
}
2013-04-20 22:18:08 +02:00
/****************************************************************************
* Name : process_help
*
* Description :
* Read and generate HTML for the help text that is expected after the
* configuration configuration variable description .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-04-22 19:20:54 +02:00
static inline void process_help ( FILE * stream , output_t outfunc )
2013-04-20 22:18:08 +02:00
{
char * ptr ;
int help_indent = 0 ;
int indent ;
bool blank ;
bool done ;
bool newpara ;
2013-04-22 17:10:58 +02:00
bool preformatted ;
2013-04-20 22:18:08 +02:00
/* Read each comment line */
newpara = true ;
2013-04-22 17:10:58 +02:00
preformatted = false ;
2013-04-20 22:18:08 +02:00
for ( ; ; )
{
/* Read the next line of comment text */
2013-04-21 17:37:45 +02:00
if ( ! read_line ( stream ) )
2013-04-20 22:18:08 +02:00
{
break ;
}
/* What is the indentation level? The first help line sets the
* indentation level . The first line encounter with lower
* indentation terminates the help .
*/
ptr = g_line ;
indent = 0 ;
blank = false ;
done = false ;
while ( ! done )
{
int ch = ( int ) * ptr ;
switch ( ch )
{
case ' ' :
indent + + ;
ptr + + ;
break ;
case ' \t ' :
indent + = TAB_SIZE ;
ptr + + ;
break ;
case ' # ' :
#if 0
blank = true ;
# endif
done = true ;
break ;
case ' \n ' :
case ' \0 ' :
blank = true ;
done = true ;
break ;
default :
done = true ;
break ;
}
}
/* Blank lines are a special case */
if ( blank )
{
/* Avoid putting an empty paragraph at the end of the help */
2013-04-22 21:58:02 +02:00
if ( preformatted )
{
outfunc ( " </pre></ul> \n " ) ;
preformatted = false ;
}
2013-04-20 22:18:08 +02:00
if ( ! newpara )
{
2013-04-22 21:58:02 +02:00
outfunc ( " </p> \n " ) ;
2013-04-20 22:18:08 +02:00
newpara = true ;
}
continue ;
}
/* Check the indentation level */
if ( indent = = 0 )
{
g_preread = true ;
break ;
}
else if ( ! help_indent )
{
help_indent = indent ;
}
else if ( indent < help_indent )
{
g_preread = true ;
break ;
}
/* Add the next line of help text */
if ( newpara )
{
2013-04-22 19:20:54 +02:00
outfunc ( " <p> \n " ) ;
2013-04-20 22:18:08 +02:00
newpara = false ;
}
2013-04-22 17:10:58 +02:00
/* Lines that are indented at greater levels are assumed to be
* pre - formatted text . This is not part of the Kconfig language but
* rather simply a NuttX Kconfig convention .
*/
if ( indent > help_indent )
{
if ( ! preformatted )
{
2013-04-22 21:58:02 +02:00
outfunc ( " <ul><pre> \n " ) ;
newpara = false ;
2013-04-22 17:10:58 +02:00
preformatted = true ;
}
2013-04-22 19:20:54 +02:00
outfunc ( " %s \n " , htmlize_text ( ptr ) ) ;
2013-04-22 17:10:58 +02:00
}
else
{
if ( preformatted )
{
2013-04-22 19:20:54 +02:00
outfunc ( " </pre></ul> \n " ) ;
2013-04-22 17:10:58 +02:00
preformatted = false ;
}
2013-04-22 19:20:54 +02:00
outfunc ( " %s " , htmlize_text ( ptr ) ) ;
2013-04-22 17:10:58 +02:00
}
2013-04-20 22:18:08 +02:00
}
if ( ! newpara )
{
2013-04-22 19:20:54 +02:00
outfunc ( " \n </p> \n " ) ;
2013-04-22 17:10:58 +02:00
}
if ( preformatted )
{
2013-04-22 19:20:54 +02:00
outfunc ( " </pre></ul> \n " ) ;
2013-04-20 22:18:08 +02:00
}
}
2013-04-22 15:22:55 +02:00
/****************************************************************************
* 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 */
2013-04-22 19:20:54 +02:00
ndx = defp - > d_nitems ;
2013-04-22 15:22:55 +02:00
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 ) ;
}
2013-04-22 19:20:54 +02:00
defp - > d_item [ ndx ] . d_default = strdup ( token ) ;
defp - > d_item [ ndx ] . d_dependency = NULL ;
2013-04-22 15:22:55 +02:00
/* 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 */
2013-04-22 19:20:54 +02:00
defp - > d_item [ ndx ] . d_dependency = strdup ( g_lnptr ) ;
2013-04-22 15:22:55 +02:00
}
/* Update the number of defaults we have encountered in this block */
2013-04-22 19:20:54 +02:00
defp - > d_nitems + + ;
2013-04-22 15:22:55 +02:00
}
/****************************************************************************
* Name : print_default
*
* Description :
2013-08-27 17:40:19 +02:00
* Output and the list of defaults to the HTML body file .
2013-04-22 15:22:55 +02:00
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-04-22 19:20:54 +02:00
static void print_default ( struct default_s * defp , output_t outfunc )
2013-04-22 15:22:55 +02:00
{
struct default_item_s * item ;
int i ;
/* Check if there are any default value */
2013-04-22 19:20:54 +02:00
if ( defp - > d_nitems > 0 )
2013-04-22 15:22:55 +02:00
{
/* Yes, output the defaults differently if there is only one */
2013-04-22 19:20:54 +02:00
if ( defp - > d_nitems = = 1 )
2013-04-22 15:22:55 +02:00
{
/* Output the Default */
2013-04-22 19:20:54 +02:00
item = & defp - > d_item [ 0 ] ;
outfunc ( " <li> \n " ) ;
outfunc ( " <i>Default</i>: %s \n " , item - > d_default ) ;
2013-04-22 15:22:55 +02:00
/* Output the dependency */
2013-04-22 19:20:54 +02:00
if ( item - > d_dependency )
2013-04-22 15:22:55 +02:00
{
2013-04-22 19:20:54 +02:00
outfunc ( " <p> \n " ) ;
outfunc ( " <i>Dependency:</i> \n " ) ;
outfunc ( " %s \n " , htmlize_expression ( item - > d_dependency ) ) ;
outfunc ( " </p> \n " ) ;
2013-04-22 15:22:55 +02:00
}
2013-04-22 19:20:54 +02:00
outfunc ( " </li> \n " ) ;
2013-04-22 15:22:55 +02:00
}
else
{
/* Output a sub-list of defaults. */
2013-04-22 19:20:54 +02:00
outfunc ( " <li> \n " ) ;
outfunc ( " <i>Default Values</i>: \n " ) ;
outfunc ( " <ul> \n " ) ;
2013-04-22 15:22:55 +02:00
2013-04-22 19:20:54 +02:00
for ( i = 0 ; i < defp - > d_nitems ; i + + )
2013-04-22 15:22:55 +02:00
{
/* Output the Default */
2013-04-22 19:20:54 +02:00
item = & defp - > d_item [ i ] ;
outfunc ( " <li> \n " ) ;
outfunc ( " <i>Default</i>: %s \n " , item - > d_default ) ;
2013-04-22 15:22:55 +02:00
/* Output the dependency */
2013-04-22 19:20:54 +02:00
if ( item - > d_dependency )
2013-04-22 15:22:55 +02:00
{
2013-04-22 19:20:54 +02:00
outfunc ( " <p> \n " ) ;
outfunc ( " <i>Dependency:</i> \n " ) ;
outfunc ( " %s \n " , htmlize_expression ( item - > d_dependency ) ) ;
outfunc ( " </p> \n " ) ;
2013-04-22 15:22:55 +02:00
}
}
2013-04-22 19:20:54 +02:00
outfunc ( " </ul> \n " ) ;
outfunc ( " </li> \n " ) ;
2013-04-22 15:22:55 +02:00
}
}
}
/****************************************************************************
* Name : free_default
*
* Description :
2013-08-27 17:40:19 +02:00
* Output and the list of defaults to the HTML body file .
2013-04-22 15:22:55 +02:00
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void free_default ( struct default_s * defp )
{
struct default_item_s * item ;
int i ;
/* Free strings for each default */
2013-04-22 19:20:54 +02:00
for ( i = 0 ; i < defp - > d_nitems ; i + + )
2013-04-22 15:22:55 +02:00
{
/* Free the default value string */
2013-04-22 19:20:54 +02:00
item = & defp - > d_item [ i ] ;
free ( item - > d_default ) ;
2013-04-22 15:22:55 +02:00
/* Free any dependency on the default */
2013-04-22 19:20:54 +02:00
if ( item - > d_dependency )
{
free ( item - > d_dependency ) ;
}
}
}
/****************************************************************************
* Name : process_dependson
*
* Description :
* Parse a " depends on " dependency and add the new dependency to the
* stack of dependencies .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void process_dependson ( void )
{
char * value = get_token ( ) ;
if ( strcmp ( value , " on " ) ! = 0 )
{
error ( " Expected \" on \" after \" depends \" \n " ) ;
exit ( ERRROR_ON_AFTER_DEPENDS ) ;
}
push_dependency ( htmlize_expression ( g_lnptr ) ) ;
}
/****************************************************************************
* Name : print_dependencies
*
* Description :
* Output the current stack of depenencies
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void print_dependencies ( output_t outfunc )
{
int i ;
if ( g_ndependencies > 0 )
{
outfunc ( " <li><i>Dependencies</i>: %s " , g_dependencies [ 0 ] ) ;
for ( i = 1 ; i < g_ndependencies ; i + + )
2013-04-22 15:22:55 +02:00
{
2013-04-22 19:20:54 +02:00
outfunc ( " , %s \n " , g_dependencies [ i ] ) ;
2013-04-22 15:22:55 +02:00
}
2013-04-22 19:20:54 +02:00
outfunc ( " </li> \n " ) ;
}
}
/****************************************************************************
* Name : free_dependencies
*
* Description :
* Pop dependencies from the stack .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void free_dependencies ( int ndependencies )
{
int i ;
for ( i = 0 ; i < ndependencies ; i + + )
{
pop_dependency ( ) ;
2013-04-22 15:22:55 +02:00
}
}
2013-04-20 22:18:08 +02:00
/****************************************************************************
* Name : process_config
*
* Description :
* Process one configuration variable paragraph
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static inline char * process_config ( FILE * stream , const char * configname ,
const char * kconfigdir )
2013-04-20 19:42:59 +02:00
{
enum token_type_e tokid ;
struct config_s config ;
2013-04-22 19:20:54 +02:00
output_t outfunc ;
2013-04-20 19:42:59 +02:00
bool help ;
2013-04-22 19:20:54 +02:00
bool hidden ;
2013-04-20 19:42:59 +02:00
const char * paranum ;
char * token ;
char * ptr ;
2013-04-21 01:05:45 +02:00
int i ;
2013-04-20 19:42:59 +02:00
/* Get the configuration information */
memset ( & config , 0 , sizeof ( struct config_s ) ) ;
2013-04-22 19:20:54 +02:00
config . c_name = strdup ( configname ) ;
2013-04-20 19:42:59 +02:00
/* Process each line in the configuration */
help = false ;
2013-04-23 19:01:18 +02:00
token = NULL ;
2013-04-20 19:42:59 +02:00
2013-04-21 17:37:45 +02:00
while ( ( ptr = kconfig_line ( stream ) ) ! = NULL )
2013-04-20 19:42:59 +02:00
{
/* Process the first token on the Kconfig file line */
2013-04-22 15:22:55 +02:00
token = get_token ( ) ;
2013-04-20 19:42:59 +02:00
if ( token ! = NULL )
{
tokid = tokenize ( token ) ;
switch ( tokid )
{
case TOKEN_BOOL :
{
/* Save the type of the configuration variable */
2013-04-22 19:20:54 +02:00
config . c_type = VALUE_BOOL ;
2013-04-20 19:42:59 +02:00
/* Get the description following the type */
2013-04-22 15:22:55 +02:00
ptr = get_html_string ( ) ;
2013-04-20 19:42:59 +02:00
if ( ptr )
{
2013-04-22 19:20:54 +02:00
config . c_desc = strdup ( ptr ) ;
2013-04-20 19:42:59 +02:00
}
/* Indicate that the line has been consumed */
token = NULL ;
}
break ;
case TOKEN_INT :
{
/* Save the type of the configuration variable */
2013-04-22 19:20:54 +02:00
config . c_type = VALUE_INT ;
2013-04-20 19:42:59 +02:00
/* Get the description following the type */
2013-04-22 15:22:55 +02:00
ptr = get_html_string ( ) ;
2013-04-20 19:42:59 +02:00
if ( ptr )
{
2013-04-22 19:20:54 +02:00
config . c_desc = strdup ( ptr ) ;
2013-04-20 19:42:59 +02:00
}
/* Indicate that the line has been consumed */
token = NULL ;
}
break ;
case TOKEN_HEX :
{
/* Save the type of the configuration variable */
2013-04-22 19:20:54 +02:00
config . c_type = VALUE_HEX ;
2013-04-20 19:42:59 +02:00
/* Get the description following the type */
2013-04-22 15:22:55 +02:00
ptr = get_html_string ( ) ;
2013-04-20 19:42:59 +02:00
if ( ptr )
{
2013-04-22 19:20:54 +02:00
config . c_desc = strdup ( ptr ) ;
2013-04-20 19:42:59 +02:00
}
/* Indicate that the line has been consumed */
token = NULL ;
}
break ;
case TOKEN_STRING :
{
/* Save the type of the configuration variable */
2013-04-22 19:20:54 +02:00
config . c_type = VALUE_STRING ;
2013-04-20 19:42:59 +02:00
/* Get the description following the type */
2013-04-22 15:22:55 +02:00
ptr = get_html_string ( ) ;
2013-04-20 19:42:59 +02:00
if ( ptr )
{
2013-04-22 19:20:54 +02:00
config . c_desc = strdup ( ptr ) ;
2013-04-20 19:42:59 +02:00
}
/* Indicate that the line has been consumed */
token = NULL ;
}
break ;
case TOKEN_DEFAULT :
{
2013-04-22 19:20:54 +02:00
process_default ( stream , & config . c_default ) ;
2013-04-20 19:42:59 +02:00
token = NULL ;
}
break ;
2013-04-21 01:29:10 +02:00
case TOKEN_RANGE :
{
2013-04-22 15:22:55 +02:00
char * value = get_token ( ) ;
2013-04-21 01:29:10 +02:00
if ( value )
{
2013-04-22 19:20:54 +02:00
config . c_lower = strdup ( value ) ;
2013-04-21 01:29:10 +02:00
2013-04-22 15:22:55 +02:00
value = get_token ( ) ;
2013-04-21 01:29:10 +02:00
if ( value )
{
2013-04-22 19:20:54 +02:00
config . c_upper = strdup ( value ) ;
2013-04-21 01:29:10 +02:00
}
}
token = NULL ;
}
break ;
2013-04-21 01:05:45 +02:00
case TOKEN_SELECT :
{
char * value ;
int ndx ;
2013-04-22 19:20:54 +02:00
ndx = config . c_select . s_nvar ;
2013-04-21 01:56:16 +02:00
if ( ndx > = MAX_SELECT )
2013-04-21 01:05:45 +02:00
{
2013-04-21 17:37:45 +02:00
error ( " Too many 'select' lines \n " ) ;
2013-04-21 01:05:45 +02:00
exit ( ERROR_TOO_MANY_SELECT ) ;
}
2013-04-22 15:22:55 +02:00
value = get_token ( ) ;
2013-04-22 19:20:54 +02:00
config . c_select . s_varname [ ndx ] = strdup ( value ) ;
config . c_select . s_nvar = ndx + 1 ;
2013-04-22 15:22:55 +02:00
token = NULL ;
2013-04-21 01:05:45 +02:00
}
break ;
case TOKEN_DEPENDS :
{
2013-04-22 19:20:54 +02:00
process_dependson ( ) ;
config . c_ndependencies + + ;
2013-04-21 01:05:45 +02:00
token = NULL ;
}
break ;
case TOKEN_OPTION :
{
token = NULL ; /* Ignored */
}
break ;
2013-04-20 19:42:59 +02:00
case TOKEN_HELP :
{
help = true ;
token = NULL ;
}
break ;
default :
{
2013-04-21 17:37:45 +02:00
debug ( " CONFIG_%s: Terminating token: %s \n " ,
2013-04-22 19:20:54 +02:00
config . c_name , token ) ;
2013-04-20 19:42:59 +02:00
}
break ;
}
2013-04-20 22:18:08 +02:00
/* Break out on the help token (or the first unhandled token) */
2013-04-20 19:42:59 +02:00
2013-04-20 22:18:08 +02:00
if ( help | | token ! = NULL )
2013-04-20 19:42:59 +02:00
{
break ;
}
}
}
2013-04-23 19:01:18 +02:00
/* Is this an internal configuration varaible with no description?
2013-04-22 19:20:54 +02:00
* If so , send the output to the appendix file .
2013-04-20 19:42:59 +02:00
*/
2013-04-22 19:20:54 +02:00
hidden = ( config . c_desc = = NULL ) ;
outfunc = hidden ? appendix : body ;
hidden | = g_inchoice ;
2013-04-20 19:42:59 +02:00
2013-04-22 19:20:54 +02:00
/* Print the configuration variable name and the short description */
2013-04-20 19:42:59 +02:00
2013-04-22 19:20:54 +02:00
outfunc ( " <h3><a name= \" CONFIG_%s \" > " , config . c_name ) ;
2013-04-20 19:42:59 +02:00
2013-04-22 19:20:54 +02:00
/* If we are not in a choice block, than give the variable a paragraph
* number and put it in the table of contents .
*/
2013-04-20 19:42:59 +02:00
2013-04-22 19:20:54 +02:00
if ( ! hidden )
{
paranum = get_paranum ( ) ;
output ( " <li><a href= \" #CONFIG_%s \" >%s <code>CONFIG_%s</code> " ,
config . c_name , paranum , config . c_name ) ;
outfunc ( " %s " , paranum ) ;
incr_paranum ( ) ;
}
2013-04-20 19:42:59 +02:00
2013-04-22 19:20:54 +02:00
outfunc ( " <code>CONFIG_%s</code> " , config . c_name ) ;
2013-04-20 19:42:59 +02:00
2013-04-22 19:20:54 +02:00
/* Output the short description in the paragraph title (if we have one) */
2013-04-20 19:42:59 +02:00
2013-04-22 19:20:54 +02:00
if ( config . c_desc )
{
if ( ! hidden )
2013-04-20 19:42:59 +02:00
{
2013-04-22 19:20:54 +02:00
output ( " : %s " , config . c_desc ) ;
2013-04-20 19:42:59 +02:00
}
2013-04-22 19:20:54 +02:00
outfunc ( " : %s " , config . c_desc ) ;
}
2013-04-20 19:42:59 +02:00
2013-04-22 19:20:54 +02:00
outfunc ( " </a></h3> \n " ) ;
2013-04-20 19:42:59 +02:00
2013-04-22 19:20:54 +02:00
if ( ! hidden )
{
output ( " </a></li> \n " ) ;
}
2013-04-20 19:42:59 +02:00
2013-04-22 19:20:54 +02:00
/* Configuration description is indented */
2013-04-20 19:42:59 +02:00
2013-04-22 19:20:54 +02:00
outfunc ( " <ul> \n " ) ;
2013-04-20 19:42:59 +02:00
2013-04-22 19:20:54 +02:00
/* Print the type of the configuration variable */
2013-04-21 01:05:45 +02:00
2013-04-22 19:20:54 +02:00
if ( config . c_type ! = VALUE_NONE )
{
outfunc ( " <li><i>Type</i>: %s</li> \n " , type2str ( config . c_type ) ) ;
}
2013-04-21 01:29:10 +02:00
2013-04-22 19:20:54 +02:00
/* Print the default values of the configuration variable */
2013-04-21 01:29:10 +02:00
2013-04-22 19:20:54 +02:00
print_default ( & config . c_default , outfunc ) ;
2013-04-21 01:29:10 +02:00
2013-04-22 19:20:54 +02:00
/* Print the range of values of the configuration variable */
2013-04-21 01:29:10 +02:00
2013-04-22 19:20:54 +02:00
if ( config . c_lower | | config . c_upper )
{
outfunc ( " <li><i>Range</i>: \n " ) ;
if ( config . c_lower )
{
outfunc ( " %s " , config . c_lower ) ;
2013-04-21 01:29:10 +02:00
}
2013-04-22 19:20:54 +02:00
outfunc ( " - " , config . c_lower ) ;
2013-04-21 01:05:45 +02:00
2013-04-22 19:20:54 +02:00
if ( config . c_upper )
2013-04-21 01:05:45 +02:00
{
2013-04-22 19:20:54 +02:00
outfunc ( " %s " , config . c_upper ) ;
2013-04-20 19:42:59 +02:00
}
2013-04-22 19:20:54 +02:00
outfunc ( " </li> \n " ) ;
}
2013-04-20 19:42:59 +02:00
2013-04-22 19:20:54 +02:00
/* Print the default value of the configuration variable auto-selected by this setting */
2013-04-21 01:05:45 +02:00
2013-04-22 19:20:54 +02:00
if ( config . c_select . s_nvar > 0 )
{
2013-04-23 01:36:27 +02:00
outfunc ( " <li><i>Selects</i>: <a href= \" #CONFIG_%s \" ><code>CONFIG_%s</code></a> " ,
2013-04-22 19:20:54 +02:00
config . c_select . s_varname [ 0 ] , config . c_select . s_varname [ 0 ] ) ;
2013-04-21 01:05:45 +02:00
2013-04-22 19:20:54 +02:00
for ( i = 1 ; i < config . c_select . s_nvar ; i + + )
{
2013-04-23 01:36:27 +02:00
outfunc ( " , <a href= \" #CONFIG_%s \" ><code>CONFIG_%s</code></a> " ,
2013-04-22 19:20:54 +02:00
config . c_select . s_varname [ i ] , config . c_select . s_varname [ i ] ) ;
2013-04-20 19:42:59 +02:00
}
2013-04-22 19:20:54 +02:00
outfunc ( " </li> \n " ) ;
}
2013-04-20 19:42:59 +02:00
2013-04-22 19:20:54 +02:00
/* Print the list of dependencies (if any) */
2013-04-20 19:42:59 +02:00
2013-04-22 19:20:54 +02:00
print_dependencies ( outfunc ) ;
2013-04-20 19:42:59 +02:00
2013-04-22 19:20:54 +02:00
/* Show the configuration file */
2013-04-20 19:42:59 +02:00
2013-04-22 19:20:54 +02:00
outfunc ( " <li><i>Kconfig file</i>: <code>%s/Kconfig</code> \n " , kconfigdir ) ;
2013-04-20 19:42:59 +02:00
2013-04-22 19:20:54 +02:00
/* Print any help text */
2013-04-21 01:05:45 +02:00
2013-04-22 19:20:54 +02:00
if ( help )
2013-04-21 01:05:45 +02:00
{
2013-04-22 19:20:54 +02:00
process_help ( stream , outfunc ) ;
token = NULL ;
2013-04-21 01:05:45 +02:00
}
2013-04-22 19:20:54 +02:00
/* End of configuration description */
outfunc ( " </ul> \n " ) ;
2013-04-20 19:42:59 +02:00
/* Free allocated memory */
2013-04-22 19:20:54 +02:00
free_dependencies ( config . c_ndependencies ) ;
free_default ( & config . c_default ) ;
2013-04-22 15:22:55 +02:00
2013-04-22 19:20:54 +02:00
if ( config . c_name )
2013-04-20 19:42:59 +02:00
{
2013-04-22 19:20:54 +02:00
free ( config . c_name ) ;
2013-04-20 19:42:59 +02:00
}
2013-04-22 19:20:54 +02:00
if ( config . c_desc )
2013-04-20 19:42:59 +02:00
{
2013-04-22 19:20:54 +02:00
free ( config . c_desc ) ;
2013-04-20 19:42:59 +02:00
}
2013-04-22 19:20:54 +02:00
if ( config . c_lower )
2013-04-21 01:29:10 +02:00
{
2013-04-22 19:20:54 +02:00
free ( config . c_lower ) ;
2013-04-21 01:29:10 +02:00
}
2013-04-22 19:20:54 +02:00
if ( config . c_upper )
2013-04-21 01:29:10 +02:00
{
2013-04-22 19:20:54 +02:00
free ( config . c_upper ) ;
2013-04-21 01:29:10 +02:00
}
2013-04-22 19:20:54 +02:00
if ( config . c_select . s_nvar > 0 )
2013-04-21 01:05:45 +02:00
{
2013-04-22 19:20:54 +02:00
for ( i = 0 ; i < config . c_select . s_nvar ; i + + )
2013-04-21 01:05:45 +02:00
{
2013-04-22 19:20:54 +02:00
free ( config . c_select . s_varname [ i ] ) ;
2013-04-21 01:05:45 +02:00
}
}
2013-04-20 19:42:59 +02:00
return token ;
}
2013-04-20 22:18:08 +02:00
/****************************************************************************
* Name : process_choice
*
* Description :
* Process a choice paragraph
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static char * parse_kconfigfile ( FILE * stream , const char * kconfigdir ) ; /* Forward reference */
static inline char * process_choice ( FILE * stream , const char * kconfigdir )
{
enum token_type_e tokid ;
struct choice_s choice ;
const char * paranum ;
2013-04-21 01:05:45 +02:00
char * token = NULL ;
2013-04-20 22:18:08 +02:00
char * ptr ;
2013-04-22 17:10:58 +02:00
bool help = false ;
2013-04-20 22:18:08 +02:00
/* Get the choice information */
memset ( & choice , 0 , sizeof ( struct choice_s ) ) ;
/* Process each line in the choice */
2013-04-21 17:37:45 +02:00
while ( ( ptr = kconfig_line ( stream ) ) ! = NULL )
2013-04-20 22:18:08 +02:00
{
/* Process the first token on the Kconfig file line */
2013-04-22 15:22:55 +02:00
token = get_token ( ) ;
2013-04-20 22:18:08 +02:00
if ( token ! = NULL )
{
tokid = tokenize ( token ) ;
switch ( tokid )
{
case TOKEN_PROMPT :
{
/* Get the prompt string */
2013-04-22 15:22:55 +02:00
ptr = get_html_string ( ) ;
2013-04-20 22:18:08 +02:00
if ( ptr )
{
2013-04-22 19:20:54 +02:00
choice . c_prompt = strdup ( ptr ) ;
2013-04-20 22:18:08 +02:00
}
/* Indicate that the line has been consumed */
token = NULL ;
}
break ;
case TOKEN_DEFAULT :
{
2013-04-22 19:20:54 +02:00
process_default ( stream , & choice . c_default ) ;
2013-04-20 22:18:08 +02:00
token = NULL ;
}
break ;
2013-04-21 01:05:45 +02:00
case TOKEN_DEPENDS :
{
2013-04-22 19:20:54 +02:00
process_dependson ( ) ;
choice . c_ndependencies + + ;
2013-04-21 01:05:45 +02:00
token = NULL ;
}
break ;
case TOKEN_HELP :
{
help = true ;
token = NULL ;
}
break ;
2013-04-20 22:18:08 +02:00
default :
{
2013-04-21 17:37:45 +02:00
debug ( " Choice: Terminating token: %s \n " , token ) ;
2013-04-20 22:18:08 +02:00
}
break ;
}
2013-04-21 01:05:45 +02:00
/* Break out on the help token (or the first unhandled token) */
2013-04-20 22:18:08 +02:00
2013-04-21 01:05:45 +02:00
if ( help | | token ! = NULL )
2013-04-20 22:18:08 +02:00
{
break ;
}
}
}
2013-04-21 01:05:45 +02:00
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 ) ;
2013-04-22 19:20:54 +02:00
if ( choice . c_prompt )
2013-04-21 01:05:45 +02:00
{
2013-04-22 19:20:54 +02:00
output ( " : %s " , choice . c_prompt ) ;
body ( " : %s " , choice . c_prompt ) ;
2013-04-21 01:05:45 +02:00
}
output ( " </a></li> \n " ) ;
body ( " </a></h3> \n " ) ;
g_choice_number + + ;
2013-04-20 22:18:08 +02:00
2013-04-22 15:22:55 +02:00
/* Print the default values of the configuration variable */
2013-04-21 01:05:45 +02:00
body ( " <ul> \n " ) ;
2013-04-22 19:20:54 +02:00
print_default ( & choice . c_default , body ) ;
2013-04-21 01:05:45 +02:00
/* Print the list of dependencies (if any) */
2013-04-22 19:20:54 +02:00
print_dependencies ( body ) ;
2013-04-20 22:18:08 +02:00
/* Show the configuration file */
2013-04-21 01:05:45 +02:00
body ( " <li><i>Kconfig file</i>: <code>%s/Kconfig</code> \n </li> " , kconfigdir ) ;
/* Print any help text */
if ( help )
{
2013-04-22 19:20:54 +02:00
process_help ( stream , body ) ;
2013-04-21 01:05:45 +02:00
token = NULL ;
}
body ( " </ul> \n " ) ;
/* Then show the choice options */
body ( " <p><b>Choice Options:</b></p> " , kconfigdir ) ;
2013-04-20 22:18:08 +02:00
body ( " <ul> \n " ) ;
/* Free allocated memory */
2013-04-22 19:20:54 +02:00
free_dependencies ( choice . c_ndependencies ) ;
free_default ( & choice . c_default ) ;
2013-04-22 15:22:55 +02:00
2013-04-22 19:20:54 +02:00
if ( choice . c_prompt )
2013-04-20 22:18:08 +02:00
{
2013-04-22 19:20:54 +02:00
free ( choice . c_prompt ) ;
2013-04-20 22:18:08 +02:00
}
2013-04-22 21:58:02 +02:00
/* Increment the paragraph level */
2013-04-20 22:18:08 +02:00
2013-04-22 19:20:54 +02:00
incr_level ( ) ;
2013-04-20 22:18:08 +02:00
2013-04-22 19:20:54 +02:00
debug ( " process_choice: TOKEN_CHOICE \n " ) ;
debug ( " kconfigdir: %s \n " , kconfigdir ) ;
debug ( " level: %d \n " , g_level ) ;
2013-04-20 22:18:08 +02:00
2013-04-22 19:20:54 +02:00
/* Then return in choice mode */
2013-04-20 22:18:08 +02:00
2013-04-22 19:20:54 +02:00
g_inchoice + + ;
return token ;
2013-04-21 01:05:45 +02:00
}
/****************************************************************************
* 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 ;
/* Get the menu information */
memset ( & menu , 0 , sizeof ( struct menu_s ) ) ;
/* Get the menu name */
2013-04-22 15:22:55 +02:00
menuname = get_html_string ( ) ;
2013-04-22 19:20:54 +02:00
menu . m_name = strdup ( menuname ) ;
2013-04-21 01:05:45 +02:00
/* Process each line in the choice */
2014-02-11 01:08:49 +01:00
while ( kconfig_line ( stream ) ! = NULL )
2013-04-21 01:05:45 +02:00
{
/* Process the first token on the Kconfig file line */
2013-04-22 15:22:55 +02:00
token = get_token ( ) ;
2013-04-21 01:05:45 +02:00
if ( token ! = NULL )
{
tokid = tokenize ( token ) ;
switch ( tokid )
{
case TOKEN_DEPENDS :
{
2013-04-22 19:20:54 +02:00
process_dependson ( ) ;
menu . m_ndependencies + + ;
2013-04-21 01:05:45 +02:00
token = NULL ;
}
break ;
default :
{
2013-04-21 17:37:45 +02:00
debug ( " Menu: Terminating token: %s \n " , token ) ;
2013-04-21 01:05:45 +02:00
}
break ;
}
/* Break out on the first unhandled token */
if ( token ! = NULL )
{
break ;
}
}
}
/* Output menu information */
paranum = get_paranum ( ) ;
2013-04-22 19:20:54 +02:00
if ( menu . m_name )
2013-04-21 01:05:45 +02:00
{
2013-04-23 19:01:18 +02:00
output ( " <li><a name= \" menu_%d_toc \" ><a href= \" #menu_%d \" >%s Menu: %s</a></a></li> \n " ,
g_menu_number , g_menu_number , paranum , menu . m_name ) ;
2013-04-22 21:58:02 +02:00
body ( " \n <h1><a name= \" menu_%d \" >%s Menu: %s</a></h1> \n " ,
g_menu_number , paranum , menu . m_name ) ;
2013-04-21 01:05:45 +02:00
}
else
{
2013-04-23 19:01:18 +02:00
output ( " <li><a name= \" menu_%d_toc \" ><a href= \" #menu_%d \" >%s Menu</a></a></li> \n " ,
g_menu_number , g_menu_number , paranum ) ;
2013-04-21 01:05:45 +02:00
body ( " \n <h1><a name= \" menu_%d \" >%s Menu</a></h1> \n " ,
g_menu_number , paranum ) ;
}
2013-04-22 21:58:02 +02:00
/* Output logic to toggle the contents below the menu in the table of
* contents .
*/
2013-04-23 19:01:18 +02:00
# ifdef USE_JQUERY
output ( " <a id= \" link_%d \" href= \" #menu_%d_toc \" onclick= \" toggle('toggle_%d', 'link_%d') \" >Expand</a> \n " ,
g_menu_number , g_toggle_number , g_toggle_number ) ;
# else
output ( " <a href= \" #menu_%d_toc \" onclick= \" toggle('toggle_%d', this) \" >Expand</a> \n " ,
g_menu_number , g_toggle_number ) ;
# endif
2013-04-22 21:58:02 +02:00
output ( " <ul id= \" toggle_%d \" style= \" display:none \" > \n " ,
g_toggle_number ) ;
2013-04-23 19:01:18 +02:00
g_menu_number + + ;
2013-04-22 21:58:02 +02:00
g_toggle_number + + ;
2013-04-21 01:05:45 +02:00
/* Print the list of dependencies (if any) */
2013-04-21 01:56:16 +02:00
body ( " <ul> \n " ) ;
2013-04-22 19:20:54 +02:00
print_dependencies ( body ) ;
2013-04-21 01:05:45 +02:00
2013-04-21 01:56:16 +02:00
/* Show the configuration file */
body ( " <li><i>Kconfig file</i>: <code>%s/Kconfig</code> \n " , kconfigdir ) ;
body ( " </ul> \n " ) ;
2013-04-21 01:05:45 +02:00
2013-04-21 01:29:10 +02:00
/* Free any allocated memory */
2013-04-22 19:20:54 +02:00
free_dependencies ( menu . m_ndependencies ) ;
if ( menu . m_name )
2013-04-21 01:29:10 +02:00
{
2013-04-22 19:20:54 +02:00
free ( menu . m_name ) ;
2013-04-21 01:29:10 +02:00
}
2013-04-22 21:58:02 +02:00
/* Increment the paragraph level */
2013-04-21 01:05:45 +02:00
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 ;
2013-04-20 22:18:08 +02:00
}
/****************************************************************************
* Name : parse_kconfigfile
*
* Description :
* Parse a Kconfig file .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-04-20 19:42:59 +02:00
static void process_kconfigfile ( const char * kconfigdir ) ; /* Forward reference */
static char * parse_kconfigfile ( FILE * stream , const char * kconfigdir )
{
enum token_type_e tokid ;
2013-04-21 01:05:45 +02:00
char * token = NULL ;
2013-04-20 19:42:59 +02:00
/* Process each line in the Kconfig file */
2014-02-11 01:08:49 +01:00
while ( kconfig_line ( stream ) ! = NULL )
2013-04-20 19:42:59 +02:00
{
/* Process the first token on the Kconfig file line */
2013-04-22 15:22:55 +02:00
token = get_token ( ) ;
2013-04-20 19:42:59 +02:00
while ( token ! = NULL )
{
tokid = tokenize ( token ) ;
switch ( tokid )
{
case TOKEN_SOURCE :
{
/* Get the relative path from the Kconfig file line */
2013-04-22 15:22:55 +02:00
char * relpath = get_token ( ) ;
2013-04-20 19:42:59 +02:00
/* Remove optional quoting */
relpath = dequote ( relpath ) ;
if ( relpath )
{
char * subdir = dirname ( relpath ) ;
char * dirpath ;
/* Check if the directory path contains $APPSDIR */
char * appsdir = strstr ( subdir , " $APPSDIR " ) ;
if ( appsdir )
{
char * tmp = appsdir + strlen ( " $APPSDIR " ) ;
* appsdir = ' \0 ' ;
asprintf ( & dirpath , " %s/%s%s%s " , g_kconfigroot , subdir , g_appsdir , tmp ) ;
}
else
{
asprintf ( & dirpath , " %s/%s " , g_kconfigroot , subdir ) ;
}
debug ( " parse_kconfigfile: Recursing for TOKEN_SOURCE \n " ) ;
debug ( " relpath: %s \n " , relpath ) ;
debug ( " subdir: %s \n " , subdir ) ;
debug ( " dirpath: %s \n " , dirpath ) ;
/* Then recurse */
process_kconfigfile ( dirpath ) ;
token = NULL ;
free ( dirpath ) ;
}
/* Set the token string to NULL to indicate that we need to read the next line */
token = NULL ;
}
break ;
case TOKEN_CONFIG :
2013-04-21 01:05:45 +02:00
case TOKEN_MENUCONFIG :
2013-04-20 19:42:59 +02:00
{
2013-04-22 15:22:55 +02:00
char * configname = get_token ( ) ;
2013-04-20 19:42:59 +02:00
token = process_config ( stream , configname , kconfigdir ) ;
}
break ;
2013-04-21 01:05:45 +02:00
case TOKEN_COMMENT :
case TOKEN_MAINMENU :
2013-04-20 19:42:59 +02:00
{
2013-04-21 01:05:45 +02:00
token = NULL ; /* ignored */
}
break ;
2013-04-20 19:42:59 +02:00
2013-04-21 01:05:45 +02:00
case TOKEN_MENU :
{
token = process_menu ( stream , kconfigdir ) ;
2013-04-20 19:42:59 +02:00
}
break ;
case TOKEN_CHOICE :
{
2013-04-20 22:18:08 +02:00
token = process_choice ( stream , kconfigdir ) ;
2013-04-20 19:42:59 +02:00
}
break ;
case TOKEN_ENDCHOICE :
{
/* Reduce body indentation level */
body ( " </ul> \n " ) ;
g_inchoice - - ;
2013-04-22 21:58:02 +02:00
/* Decrement the paragraph level */
2013-04-20 19:42:59 +02:00
decr_level ( ) ;
incr_paranum ( ) ;
2013-04-21 01:05:45 +02:00
token = NULL ;
2013-04-20 19:42:59 +02:00
}
break ;
case TOKEN_ENDMENU :
{
2013-04-22 21:58:02 +02:00
/* Reduce table of contents indentation level. NOTE that
* this also terminates the toggle block that began with the
* matching < ul >
*/
2013-04-20 19:42:59 +02:00
output ( " </ul> \n " ) ;
2013-04-22 21:58:02 +02:00
/* Decrement the paragraph level */
2013-04-20 19:42:59 +02:00
decr_level ( ) ;
incr_paranum ( ) ;
2013-04-21 01:05:45 +02:00
token = NULL ;
2013-04-20 19:42:59 +02:00
}
break ;
case TOKEN_IF :
{
2013-04-22 15:22:55 +02:00
char * dependency = get_token ( ) ;
2013-04-21 19:01:46 +02:00
push_dependency ( htmlize_expression ( dependency ) ) ;
2013-04-20 19:42:59 +02:00
token = NULL ;
}
break ;
case TOKEN_ENDIF :
{
pop_dependency ( ) ;
token = NULL ;
}
break ;
default :
{
/* Set token to NULL to skip to the next line */
2013-05-03 20:52:33 +02:00
error ( " File %s/Kconfig Unhandled token: %s \n " ,
kconfigdir , token ) ;
2013-04-20 19:42:59 +02:00
token = NULL ;
}
break ;
}
}
}
return token ;
}
2013-04-20 22:18:08 +02:00
/****************************************************************************
* Name : process_kconfigfile
*
* Description :
* Open and parse a Kconfig file
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-04-20 19:42:59 +02:00
static void process_kconfigfile ( const char * kconfigdir )
{
FILE * stream ;
char * kconfigpath ;
/* Create the full path to the Kconfig file */
asprintf ( & kconfigpath , " %s/Kconfig " , kconfigdir ) ;
debug ( " process_kconfigfile: Entry \n " ) ;
debug ( " kconfigdir: %s \n " , kconfigdir ) ;
debug ( " kconfigpath: %s \n " , kconfigpath ) ;
debug ( " level: %d \n " , g_level ) ;
/* Open the Kconfig file */
stream = fopen ( kconfigpath , " r " ) ;
if ( ! stream )
{
2013-04-21 17:37:45 +02:00
error ( " open %s failed: %s \n " , kconfigpath , strerror ( errno ) ) ;
2013-04-20 19:42:59 +02:00
exit ( ERROR_KCONFIG_OPEN_FAILURE ) ;
}
/* Process each line in the Kconfig file */
parse_kconfigfile ( stream , kconfigdir ) ;
/* Close the Kconfig file and release the memory holding the full path */
fclose ( stream ) ;
free ( kconfigpath ) ;
}
/****************************************************************************
* Public Functions
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-04-20 22:18:08 +02:00
/****************************************************************************
* Name : main
*
* Description :
* Program entry point .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2013-04-20 19:42:59 +02:00
int main ( int argc , char * * argv , char * * envp )
{
char * outfile ;
const char * paranum ;
time_t now ;
struct tm * ptm ;
int ch ;
/* Parse command line options */
g_debug = false ;
g_kconfigroot = " . " ;
g_appsdir = " ../apps " ;
g_outfile = stdout ;
outfile = NULL ;
2013-04-22 19:20:54 +02:00
while ( ( ch = getopt ( argc , argv , " :dhia:o: " ) ) > 0 )
2013-04-20 19:42:59 +02:00
{
switch ( ch )
{
case ' a ' :
g_appsdir = optarg ;
break ;
case ' o ' :
outfile = optarg ;
break ;
case ' h ' :
show_usage ( argv [ 0 ] , 0 ) ;
case ' d ' :
g_debug = true ;
break ;
case ' ? ' :
2013-04-21 17:37:45 +02:00
error ( " Unrecognized option: %c \n " , optopt ) ;
2013-04-20 19:42:59 +02:00
show_usage ( argv [ 0 ] , ERROR_UNRECOGNIZED_OPTION ) ;
case ' : ' :
2013-04-21 17:37:45 +02:00
error ( " Missing option argument, option: %c \n " , optopt ) ;
2013-04-20 19:42:59 +02:00
show_usage ( argv [ 0 ] , ERROR_MISSING_OPTION_ARGUMENT ) ;
2014-02-11 01:08:49 +01:00
default :
2013-04-21 17:37:45 +02:00
error ( " Unexpected option: %c \n " , ch ) ;
2013-04-20 19:42:59 +02:00
show_usage ( argv [ 0 ] , ERROR_UNEXPECTED_OPTION ) ;
}
}
if ( optind < argc )
{
g_kconfigroot = argv [ optind ] ;
optind + + ;
}
debug ( " Using <Kconfig directory>: %s \n " , g_kconfigroot ) ;
debug ( " Using <apps directory>: %s \n " , g_appsdir ) ;
debug ( " Using <out file>: %s \n " , outfile ? outfile : " stdout " ) ;
if ( optind < argc )
{
2013-04-21 17:37:45 +02:00
error ( " Unexpected garbage at the end of the line \n " ) ;
2013-04-20 19:42:59 +02:00
show_usage ( argv [ 0 ] , ERROR_TOO_MANY_ARGUMENTS ) ;
}
2013-04-22 19:20:54 +02:00
/* Open the output file (if any). The output file will hold the
* Table of Contents as the HTML document is generated .
*/
2013-04-20 19:42:59 +02:00
if ( outfile )
{
g_outfile = fopen ( outfile , " w " ) ;
if ( ! g_outfile )
{
2013-04-21 17:37:45 +02:00
error ( " open %s failed: %s \n " , outfile , strerror ( errno ) ) ;
2013-04-20 19:42:59 +02:00
exit ( ERROR_OUTFILE_OPEN_FAILURE ) ;
}
}
2013-04-22 19:20:54 +02:00
/* Open the temporary file that holds the HTML body. The HTML
* body will be appended after the Table of contents .
*/
g_bodyfile = fopen ( BODYFILE_NAME , " w " ) ;
if ( ! g_bodyfile )
{
error ( " open %s failed: %s \n " , BODYFILE_NAME , strerror ( errno ) ) ;
exit ( ERROR_BODYFILE_OPEN_FAILURE ) ;
}
/* Open the temporary file that holds the appendix. The appendix
* will be appended after the HTML body .
*/
2013-04-20 19:42:59 +02:00
2013-04-22 19:20:54 +02:00
g_apndxfile = fopen ( APNDXFILE_NAME , " w " ) ;
if ( ! g_apndxfile )
2013-04-20 19:42:59 +02:00
{
2013-04-22 19:20:54 +02:00
error ( " open %s failed: %s \n " , APNDXFILE_NAME , strerror ( errno ) ) ;
exit ( ERROR_APNDXFILE_OPEN_FAILURE ) ;
2013-04-20 19:42:59 +02:00
}
/* Get the current date string in the scratch buffer */
now = time ( NULL ) ;
ptm = localtime ( & now ) ;
( void ) strftime ( g_scratch , SCRATCH_SIZE , " %B %d, %Y " , ptm ) ;
/* Output header boilerplater */
output ( " <html> \n " ) ;
output ( " <head> \n " ) ;
output ( " <title>NuttX Configuration Options</title> \n " ) ;
output ( " </head> \n " ) ;
2013-04-22 21:58:02 +02:00
2013-04-20 19:42:59 +02:00
output ( " <body background= \" backgd.gif \" > \n " ) ;
output ( " <hr><hr> \n " ) ;
output ( " <table width = \" 100%% \" > \n " ) ;
output ( " <tr align= \" center \" bgcolor= \" #e4e4e4 \" > \n " ) ;
output ( " <td> \n " ) ;
output ( " <h1><big><font color= \" #3c34ec \" ><i>NuttX Configuration Variables</i></font></big></h1> \n " ) ;
output ( " <p>Last Updated: %s</p> \n " , g_scratch ) ;
output ( " </td> \n " ) ;
output ( " </tr> \n " ) ;
output ( " </table> \n " ) ;
2013-04-23 19:01:18 +02:00
# ifdef USE_JQUERY
output ( " <script src= \" http://code.jquery.com/jquery-1.9.1.js \" ></script> \n " ) ;
output ( " <script type= \" text/javascript \" > \n " ) ;
output ( " function toggle(list_id, link_id) { \n " ) ;
output ( " var list = $('#' + list_id); \n " ) ;
output ( " var link = $('#' + link_id); \n " ) ;
output ( " if (list.is( \" :visible \" )) { \n " ) ;
output ( " list.hide(); \n " ) ;
output ( " link.text('Expand'); \n " ) ;
output ( " } else { \n " ) ;
output ( " list.show(); \n " ) ;
output ( " link.text('Collapse'); \n " ) ;
output ( " } \n " ) ;
output ( " } \n " ) ;
output ( " </script> \n " ) ;
# else
2013-04-22 21:58:02 +02:00
output ( " <script type= \" text/javascript \" > \n " ) ;
output ( " function toggle(id, link) { \n " ) ;
output ( " var e = document.getElementById(id); \n " ) ;
output ( " if (e.style.display == '') { \n " ) ;
output ( " e.style.display = 'none'; \n " ) ;
output ( " link.innerHTML = 'Expand'; \n " ) ;
output ( " } else { \n " ) ;
output ( " e.style.display = ''; \n " ) ;
output ( " link.innerHTML = 'Collapse'; \n " ) ;
output ( " } \n " ) ;
output ( " } \n " ) ;
output ( " </script> \n " ) ;
2013-04-23 19:01:18 +02:00
# endif
2013-04-22 21:58:02 +02:00
2013-04-23 00:46:15 +02:00
output ( " <hr><hr> \n " ) ;
output ( " <table width = \" 100%% \" > \n " ) ;
output ( " <tr bgcolor= \" #e4e4e4 \" > \n " ) ;
output ( " <td> \n " ) ;
output ( " <h1>Table of Contents</h1> \n " ) ;
output ( " </td> \n " ) ;
output ( " </tr> \n " ) ;
output ( " </table> \n " ) ;
2013-04-20 19:42:59 +02:00
output ( " <ul> \n " ) ;
incr_level ( ) ;
paranum = get_paranum ( ) ;
2013-04-21 01:56:16 +02:00
output ( " <li><a href= \" #menu_%d \" >%s Menu: Main</a></li> \n " ,
2013-04-20 19:42:59 +02:00
g_menu_number , paranum ) ;
2013-04-23 00:46:15 +02:00
body ( " <table width = \" 100%% \" > \n " ) ;
body ( " <tr bgcolor= \" #e4e4e4 \" > \n " ) ;
body ( " <td> \n " ) ;
body ( " <a name= \" menu_%d \" ><h1>%s Menu: Main</h1></a> \n " ,
2013-04-20 19:42:59 +02:00
g_menu_number , paranum ) ;
2013-04-23 00:46:15 +02:00
body ( " </td> \n " ) ;
body ( " </tr> \n " ) ;
body ( " </table> \n " ) ;
2013-04-20 19:42:59 +02:00
g_menu_number + + ;
2013-04-22 21:58:02 +02:00
/* Increment the paragraph level again: Everything is included within the main menu. */
2013-04-22 19:20:54 +02:00
incr_level ( ) ;
2013-04-21 19:01:46 +02:00
/* Tell the reader that this is an auto-generated file */
body ( " <p> \n " ) ;
2013-04-22 15:22:55 +02:00
body ( " <b>Overview</b>. \n " ) ;
2013-04-21 19:01:46 +02:00
body ( " The NuttX RTOS is highly configurable. \n " ) ;
body ( " The NuttX configuration files are maintained using the <a href= \" http://ymorin.is-a-geek.org/projects/kconfig-frontends \" >kconfig-frontends</a> tool. \n " ) ;
body ( " That configuration tool uses <code>Kconfig</code> files that can be found through the NuttX source tree. \n " ) ;
body ( " Each <code>Kconfig</code> files contains declarations of configuration variables. \n " ) ;
body ( " Each configuration variable provides one configuration option for the NuttX RTOS. \n " ) ;
body ( " This configurable options are descrived in this document. \n " ) ;
body ( " </p> \n " ) ;
body ( " <p> \n " ) ;
2013-04-22 19:20:54 +02:00
body ( " <b>Main Menu</b>. \n " ) ;
body ( " The normal way to start the NuttX configuration is to enter this command line from the NuttX build directory: <code>make menuconfig</code>. \n " ) ;
body ( " Note that NuttX must first be configured <i>before</i> this command so that the configuration file (<code>.config</code>) is present in the top-level build directory. \n " ) ;
body ( " The main menu is the name give to the opening menu display after this command is executed. \n " ) ;
body ( " </p> \n " ) ;
body ( " <p> \n " ) ;
2013-04-22 15:22:55 +02:00
body ( " <b>Mainenance Note</b>. \n " ) ;
2013-04-21 19:01:46 +02:00
body ( " This documenation was auto-generated using the <a href= \" http://sourceforge.net/p/nuttx/git/ci/master/tree/nuttx/tools/kconfig2html.c \" >kconfig2html</a> tool \n " ) ;
2013-04-23 00:46:15 +02:00
body ( " That tool analyzes the NuttX <code>Kconfig</code> files and generates this HTML document. \n " ) ;
2013-04-21 19:01:46 +02:00
body ( " This HTML document file should not be editted manually. \n " ) ;
body ( " In order to make changes to this document, you should instead modify the <code>Kconfig</code> file(s) that were used to generated this document and then execute the <code>kconfig2html</code> again to regenerate the HTML document file. \n " ) ;
body ( " </p> \n " ) ;
2013-04-20 19:42:59 +02:00
/* Process the Kconfig files through recursive descent */
process_kconfigfile ( g_kconfigroot ) ;
/* Terminate the table of contents */
2013-04-23 00:46:15 +02:00
output ( " <li><a href= \" #appendixa \" >Appendix A: Hidden Configuration Variables</a></li> \n " ) ;
2013-04-20 19:42:59 +02:00
output ( " </ul> \n " ) ;
2013-04-22 19:20:54 +02:00
/* Close the HMTL body file and copy it to the output file */
2013-04-20 19:42:59 +02:00
2013-04-22 19:20:54 +02:00
fclose ( g_bodyfile ) ;
append_file ( BODYFILE_NAME ) ;
2013-04-20 19:42:59 +02:00
2013-04-22 19:20:54 +02:00
/* Output introductory information for the appendix */
2013-04-20 19:42:59 +02:00
2013-04-23 00:46:15 +02:00
output ( " <table width = \" 100%% \" > \n " ) ;
output ( " <tr bgcolor= \" #e4e4e4 \" > \n " ) ;
output ( " <td> \n " ) ;
output ( " <a name= \" appendixa \" ><h1>Appendix A: Hidden Configuration Variables</h1></a> \n " ) ;
output ( " </td> \n " ) ;
output ( " </tr> \n " ) ;
output ( " </table> \n " ) ;
2013-04-22 19:20:54 +02:00
output ( " <p> \n " ) ;
2013-05-22 15:35:54 +02:00
output ( " This appendix holds internal configurations variables that are not visible to the user. \n " ) ;
2013-04-22 19:20:54 +02:00
output ( " These settings are presented out-of-context because they cannot be directly controlled by the user. \n " ) ;
output ( " Many of these settings are selected automatically and indirectly when other, visible configuration variables are selected. \n " ) ;
output ( " One purpose of these hidden configuration variables is to control menuing in the kconfig-frontends configuration tool. \n " ) ;
output ( " Many configuration variables with a form like <code>CONFIG_ARCH_HAVE_</code><i>feature</i>, for example, are used only to indicate that the selected archicture supports <i>feature</i> and so addition selection associated with <i>feature</i> will become accessible to the user. \n " ) ;
output ( " </p> \n " ) ;
output ( " <ul> \n " ) ;
/* Close the appendix file and copy it to the output file */
2013-04-20 19:42:59 +02:00
2013-04-22 19:20:54 +02:00
fclose ( g_apndxfile ) ;
append_file ( APNDXFILE_NAME ) ;
2013-04-20 19:42:59 +02:00
/* Output trailer boilerplater */
2013-04-22 19:20:54 +02:00
output ( " </ul> \n " ) ;
2013-04-20 19:42:59 +02:00
output ( " </body> \n " ) ;
output ( " </html> \n " ) ;
/* Close the output file (if any) and the temporary file*/
if ( outfile )
{
fclose ( g_outfile ) ;
}
return 0 ;
}