/* parser config.in
|
/* parser config.in
|
*
|
*
|
* Version 1.0
|
* Version 1.0
|
* Eric Youngdale
|
* Eric Youngdale
|
* 10/95
|
* 10/95
|
*
|
*
|
* The general idea here is that we want to parse a config.in file and
|
* The general idea here is that we want to parse a config.in file and
|
* from this, we generate a wish script which gives us effectively the
|
* from this, we generate a wish script which gives us effectively the
|
* same functionality that the original config.in script provided.
|
* same functionality that the original config.in script provided.
|
*
|
*
|
* This task is split roughly into 3 parts. The first parse is the parse
|
* This task is split roughly into 3 parts. The first parse is the parse
|
* of the input file itself. The second part is where we analyze the
|
* of the input file itself. The second part is where we analyze the
|
* #ifdef clauses, and attach a linked list of tokens to each of the
|
* #ifdef clauses, and attach a linked list of tokens to each of the
|
* menu items. In this way, each menu item has a complete list of
|
* menu items. In this way, each menu item has a complete list of
|
* dependencies that are used to enable/disable the options.
|
* dependencies that are used to enable/disable the options.
|
* The third part is to take the configuration database we have build,
|
* The third part is to take the configuration database we have build,
|
* and build the actual wish script.
|
* and build the actual wish script.
|
*
|
*
|
* This file contains the code to do the first parse of config.in.
|
* This file contains the code to do the first parse of config.in.
|
*/
|
*/
|
#include <stdlib.h>
|
#include <stdlib.h>
|
#include <stdio.h>
|
#include <stdio.h>
|
#include <string.h>
|
#include <string.h>
|
#include "tkparse.h"
|
#include "tkparse.h"
|
|
|
struct kconfig * config = NULL;
|
struct kconfig * config = NULL;
|
struct kconfig * clast = NULL;
|
struct kconfig * clast = NULL;
|
struct kconfig * koption = NULL;
|
struct kconfig * koption = NULL;
|
static int lineno = 0;
|
static int lineno = 0;
|
static int menus_seen = 0;
|
static int menus_seen = 0;
|
static char * current_file = NULL;
|
static char * current_file = NULL;
|
static int do_source(char * filename);
|
static int do_source(char * filename);
|
static char * get_string(char *pnt, char ** labl);
|
static char * get_string(char *pnt, char ** labl);
|
static int choose_number = 0;
|
static int choose_number = 0;
|
|
|
|
|
/*
|
/*
|
* Simple function just to skip over spaces and tabs in config.in.
|
* Simple function just to skip over spaces and tabs in config.in.
|
*/
|
*/
|
static char * skip_whitespace(char * pnt)
|
static char * skip_whitespace(char * pnt)
|
{
|
{
|
while( *pnt && (*pnt == ' ' || *pnt == '\t')) pnt++;
|
while( *pnt && (*pnt == ' ' || *pnt == '\t')) pnt++;
|
return pnt;
|
return pnt;
|
}
|
}
|
|
|
/*
|
/*
|
* This function parses a conditional from a config.in (i.e. from an ifdef)
|
* This function parses a conditional from a config.in (i.e. from an ifdef)
|
* and generates a linked list of tokens that describes the conditional.
|
* and generates a linked list of tokens that describes the conditional.
|
*/
|
*/
|
static struct condition * parse_if(char * pnt)
|
static struct condition * parse_if(char * pnt)
|
{
|
{
|
char * opnt;
|
char * opnt;
|
struct condition *list;
|
struct condition *list;
|
struct condition *last;
|
struct condition *last;
|
struct condition *cpnt;
|
struct condition *cpnt;
|
char varname[64];
|
char varname[64];
|
char * pnt1;
|
char * pnt1;
|
|
|
opnt = pnt;
|
opnt = pnt;
|
|
|
/*
|
/*
|
* We need to find the various tokens, and build the linked list.
|
* We need to find the various tokens, and build the linked list.
|
*/
|
*/
|
pnt = skip_whitespace(pnt);
|
pnt = skip_whitespace(pnt);
|
if( *pnt != '[' ) return NULL;
|
if( *pnt != '[' ) return NULL;
|
pnt++;
|
pnt++;
|
pnt = skip_whitespace(pnt);
|
pnt = skip_whitespace(pnt);
|
|
|
list = last = NULL;
|
list = last = NULL;
|
while(*pnt && *pnt != ']') {
|
while(*pnt && *pnt != ']') {
|
|
|
pnt = skip_whitespace(pnt);
|
pnt = skip_whitespace(pnt);
|
if(*pnt== '\0' || *pnt == ']') break;
|
if(*pnt== '\0' || *pnt == ']') break;
|
|
|
/*
|
/*
|
* Allocate memory for the token we are about to parse, and insert
|
* Allocate memory for the token we are about to parse, and insert
|
* it in the linked list.
|
* it in the linked list.
|
*/
|
*/
|
cpnt = (struct condition *) malloc(sizeof(struct condition));
|
cpnt = (struct condition *) malloc(sizeof(struct condition));
|
memset(cpnt, 0, sizeof(struct condition));
|
memset(cpnt, 0, sizeof(struct condition));
|
if( last == NULL )
|
if( last == NULL )
|
{
|
{
|
list = last = cpnt;
|
list = last = cpnt;
|
}
|
}
|
else
|
else
|
{
|
{
|
last->next = cpnt;
|
last->next = cpnt;
|
last = cpnt;
|
last = cpnt;
|
}
|
}
|
|
|
/*
|
/*
|
* Determine what type of operation this token represents.
|
* Determine what type of operation this token represents.
|
*/
|
*/
|
if( *pnt == '-' && pnt[1] == 'a' )
|
if( *pnt == '-' && pnt[1] == 'a' )
|
{
|
{
|
cpnt->op = op_and;
|
cpnt->op = op_and;
|
pnt += 2;
|
pnt += 2;
|
continue;
|
continue;
|
}
|
}
|
|
|
if( *pnt == '-' && pnt[1] == 'o' )
|
if( *pnt == '-' && pnt[1] == 'o' )
|
{
|
{
|
cpnt->op = op_or;
|
cpnt->op = op_or;
|
pnt += 2;
|
pnt += 2;
|
continue;
|
continue;
|
}
|
}
|
|
|
if( *pnt == '!' && pnt[1] == '=' )
|
if( *pnt == '!' && pnt[1] == '=' )
|
{
|
{
|
cpnt->op = op_neq;
|
cpnt->op = op_neq;
|
pnt += 2;
|
pnt += 2;
|
continue;
|
continue;
|
}
|
}
|
|
|
if( *pnt == '=')
|
if( *pnt == '=')
|
{
|
{
|
cpnt->op = op_eq;
|
cpnt->op = op_eq;
|
pnt += 1;
|
pnt += 1;
|
continue;
|
continue;
|
}
|
}
|
|
|
if( *pnt == '!')
|
if( *pnt == '!')
|
{
|
{
|
cpnt->op = op_bang;
|
cpnt->op = op_bang;
|
pnt += 1;
|
pnt += 1;
|
continue;
|
continue;
|
}
|
}
|
|
|
if( *pnt != '"' ) goto error; /* This cannot be right. */
|
if( *pnt != '"' ) goto error; /* This cannot be right. */
|
pnt++;
|
pnt++;
|
if( *pnt == '`' )
|
if( *pnt == '`' )
|
{
|
{
|
cpnt->op = op_shellcmd;
|
cpnt->op = op_shellcmd;
|
pnt1 = varname;
|
pnt1 = varname;
|
pnt++;
|
pnt++;
|
while(*pnt && *pnt != '`') *pnt1++ = *pnt++;
|
while(*pnt && *pnt != '`') *pnt1++ = *pnt++;
|
*pnt1++ = '\0';
|
*pnt1++ = '\0';
|
cpnt->variable.str = strdup(varname);
|
cpnt->variable.str = strdup(varname);
|
if( *pnt == '`' ) pnt++;
|
if( *pnt == '`' ) pnt++;
|
if( *pnt == '"' ) pnt++;
|
if( *pnt == '"' ) pnt++;
|
continue;
|
continue;
|
}
|
}
|
if( *pnt == '$' )
|
if( *pnt == '$' )
|
{
|
{
|
cpnt->op = op_variable;
|
cpnt->op = op_variable;
|
pnt1 = varname;
|
pnt1 = varname;
|
pnt++;
|
pnt++;
|
while(*pnt && *pnt != '"') *pnt1++ = *pnt++;
|
while(*pnt && *pnt != '"') *pnt1++ = *pnt++;
|
*pnt1++ = '\0';
|
*pnt1++ = '\0';
|
cpnt->variable.str = strdup(varname);
|
cpnt->variable.str = strdup(varname);
|
if( *pnt == '"' ) pnt++;
|
if( *pnt == '"' ) pnt++;
|
continue;
|
continue;
|
}
|
}
|
|
|
cpnt->op = op_constant;
|
cpnt->op = op_constant;
|
pnt1 = varname;
|
pnt1 = varname;
|
while(*pnt && *pnt != '"') *pnt1++ = *pnt++;
|
while(*pnt && *pnt != '"') *pnt1++ = *pnt++;
|
*pnt1++ = '\0';
|
*pnt1++ = '\0';
|
cpnt->variable.str = strdup(varname);
|
cpnt->variable.str = strdup(varname);
|
if( *pnt == '"' ) pnt++;
|
if( *pnt == '"' ) pnt++;
|
continue;
|
continue;
|
}
|
}
|
|
|
return list;
|
return list;
|
|
|
error:
|
error:
|
if(current_file != NULL)
|
if(current_file != NULL)
|
fprintf(stderr,
|
fprintf(stderr,
|
"Bad if clause at line %d(%s):%s\n", lineno, current_file, opnt);
|
"Bad if clause at line %d(%s):%s\n", lineno, current_file, opnt);
|
else
|
else
|
fprintf(stderr,
|
fprintf(stderr,
|
"Bad if clause at line %d:%s\n", lineno, opnt);
|
"Bad if clause at line %d:%s\n", lineno, opnt);
|
return NULL;
|
return NULL;
|
}
|
}
|
|
|
/*
|
/*
|
* This function looks for a quoted string, from the input buffer, and
|
* This function looks for a quoted string, from the input buffer, and
|
* returns a pointer to a copy of this string. Any characters in
|
* returns a pointer to a copy of this string. Any characters in
|
* the string that need to be "quoted" have a '\' character inserted
|
* the string that need to be "quoted" have a '\' character inserted
|
* in front - this way we can directly write these strings into
|
* in front - this way we can directly write these strings into
|
* wish scripts.
|
* wish scripts.
|
*/
|
*/
|
static char * get_qstring(char *pnt, char ** labl)
|
static char * get_qstring(char *pnt, char ** labl)
|
{
|
{
|
char quotechar;
|
char quotechar;
|
char newlabel[1024];
|
char newlabel[1024];
|
char * pnt1;
|
char * pnt1;
|
char * pnt2;
|
char * pnt2;
|
|
|
while( *pnt && *pnt != '"' && *pnt != '\'') pnt++;
|
while( *pnt && *pnt != '"' && *pnt != '\'') pnt++;
|
if (*pnt == '\0') return pnt;
|
if (*pnt == '\0') return pnt;
|
|
|
quotechar = *pnt++;
|
quotechar = *pnt++;
|
pnt1 = newlabel;
|
pnt1 = newlabel;
|
while(*pnt && *pnt != quotechar && pnt[-1] != '\\')
|
while(*pnt && *pnt != quotechar && pnt[-1] != '\\')
|
{
|
{
|
/*
|
/*
|
* Quote the character if we need to.
|
* Quote the character if we need to.
|
*/
|
*/
|
if( *pnt == '"' || *pnt == '\'' || *pnt == '[' || *pnt == ']')
|
if( *pnt == '"' || *pnt == '\'' || *pnt == '[' || *pnt == ']')
|
*pnt1++ = '\\';
|
*pnt1++ = '\\';
|
|
|
*pnt1++ = *pnt++;
|
*pnt1++ = *pnt++;
|
}
|
}
|
*pnt1++ = '\0';
|
*pnt1++ = '\0';
|
|
|
pnt2 = (char *) malloc(strlen(newlabel) + 1);
|
pnt2 = (char *) malloc(strlen(newlabel) + 1);
|
strcpy(pnt2, newlabel);
|
strcpy(pnt2, newlabel);
|
*labl = pnt2;
|
*labl = pnt2;
|
|
|
/*
|
/*
|
* Skip over last quote, and whitespace.
|
* Skip over last quote, and whitespace.
|
*/
|
*/
|
pnt++;
|
pnt++;
|
pnt = skip_whitespace(pnt);
|
pnt = skip_whitespace(pnt);
|
return pnt;
|
return pnt;
|
}
|
}
|
|
|
static char * parse_choices(struct kconfig * choice_kcfg, char * pnt)
|
static char * parse_choices(struct kconfig * choice_kcfg, char * pnt)
|
{
|
{
|
struct kconfig * kcfg;
|
struct kconfig * kcfg;
|
int index = 1;
|
int index = 1;
|
|
|
/*
|
/*
|
* Choices appear in pairs of strings. The parse is fairly trivial.
|
* Choices appear in pairs of strings. The parse is fairly trivial.
|
*/
|
*/
|
while(1)
|
while(1)
|
{
|
{
|
pnt = skip_whitespace(pnt);
|
pnt = skip_whitespace(pnt);
|
if(*pnt == '\0') break;
|
if(*pnt == '\0') break;
|
|
|
kcfg = (struct kconfig *) malloc(sizeof(struct kconfig));
|
kcfg = (struct kconfig *) malloc(sizeof(struct kconfig));
|
memset(kcfg, 0, sizeof(struct kconfig));
|
memset(kcfg, 0, sizeof(struct kconfig));
|
kcfg->tok = tok_choice;
|
kcfg->tok = tok_choice;
|
if( clast != NULL )
|
if( clast != NULL )
|
{
|
{
|
clast->next = kcfg;
|
clast->next = kcfg;
|
clast = kcfg;
|
clast = kcfg;
|
}
|
}
|
else
|
else
|
{
|
{
|
clast = config = kcfg;
|
clast = config = kcfg;
|
}
|
}
|
|
|
pnt = get_string(pnt, &kcfg->label);
|
pnt = get_string(pnt, &kcfg->label);
|
pnt = skip_whitespace(pnt);
|
pnt = skip_whitespace(pnt);
|
pnt = get_string(pnt, &kcfg->optionname);
|
pnt = get_string(pnt, &kcfg->optionname);
|
kcfg->choice_label = choice_kcfg;
|
kcfg->choice_label = choice_kcfg;
|
kcfg->choice_value = index++;
|
kcfg->choice_value = index++;
|
if( strcmp(kcfg->label, choice_kcfg->value) == 0 )
|
if( strcmp(kcfg->label, choice_kcfg->value) == 0 )
|
choice_kcfg->choice_value = kcfg->choice_value;
|
choice_kcfg->choice_value = kcfg->choice_value;
|
}
|
}
|
|
|
return pnt;
|
return pnt;
|
}
|
}
|
|
|
|
|
/*
|
/*
|
* This function grabs one text token from the input buffer
|
* This function grabs one text token from the input buffer
|
* and returns a pointer to a copy of just the identifier.
|
* and returns a pointer to a copy of just the identifier.
|
* This can be either a variable name (i.e. CONFIG_NET),
|
* This can be either a variable name (i.e. CONFIG_NET),
|
* or it could be the default value for the option.
|
* or it could be the default value for the option.
|
*/
|
*/
|
static char * get_string(char *pnt, char ** labl)
|
static char * get_string(char *pnt, char ** labl)
|
{
|
{
|
char newlabel[1024];
|
char newlabel[1024];
|
char * pnt1;
|
char * pnt1;
|
char * pnt2;
|
char * pnt2;
|
|
|
if (*pnt == '\0') return pnt;
|
if (*pnt == '\0') return pnt;
|
|
|
pnt1 = newlabel;
|
pnt1 = newlabel;
|
while(*pnt && *pnt != ' ' && *pnt != '\t')
|
while(*pnt && *pnt != ' ' && *pnt != '\t')
|
{
|
{
|
*pnt1++ = *pnt++;
|
*pnt1++ = *pnt++;
|
}
|
}
|
*pnt1++ = '\0';
|
*pnt1++ = '\0';
|
|
|
pnt2 = (char *) malloc(strlen(newlabel) + 1);
|
pnt2 = (char *) malloc(strlen(newlabel) + 1);
|
strcpy(pnt2, newlabel);
|
strcpy(pnt2, newlabel);
|
*labl = pnt2;
|
*labl = pnt2;
|
|
|
if( *pnt ) pnt++;
|
if( *pnt ) pnt++;
|
return pnt;
|
return pnt;
|
}
|
}
|
|
|
|
|
/*
|
/*
|
* Top level parse function. Input pointer is one complete line from config.in
|
* Top level parse function. Input pointer is one complete line from config.in
|
* and the result is that we create a token that describes this line
|
* and the result is that we create a token that describes this line
|
* and insert it into our linked list.
|
* and insert it into our linked list.
|
*/
|
*/
|
void parse(char * pnt) {
|
void parse(char * pnt) {
|
enum token tok;
|
enum token tok;
|
struct kconfig * kcfg;
|
struct kconfig * kcfg;
|
char tmpbuf[24],fake_if[1024];
|
char tmpbuf[24],fake_if[1024];
|
|
|
/*
|
/*
|
* Ignore comments and leading whitespace.
|
* Ignore comments and leading whitespace.
|
*/
|
*/
|
|
|
pnt = skip_whitespace(pnt);
|
pnt = skip_whitespace(pnt);
|
while( *pnt && (*pnt == ' ' || *pnt == '\t')) pnt++;
|
while( *pnt && (*pnt == ' ' || *pnt == '\t')) pnt++;
|
if(! *pnt ) return;
|
if(! *pnt ) return;
|
if( *pnt == '#' ) return;
|
if( *pnt == '#' ) return;
|
|
|
/*
|
/*
|
* Now categorize the next token.
|
* Now categorize the next token.
|
*/
|
*/
|
tok = tok_unknown;
|
tok = tok_unknown;
|
if (strncmp(pnt, "mainmenu_name", 13) == 0)
|
if (strncmp(pnt, "mainmenu_name", 13) == 0)
|
{
|
{
|
tok = tok_menuname;
|
tok = tok_menuname;
|
pnt += 13;
|
pnt += 13;
|
}
|
}
|
else if (strncmp(pnt, "source", 6) == 0)
|
else if (strncmp(pnt, "source", 6) == 0)
|
{
|
{
|
pnt += 7;
|
pnt += 7;
|
pnt = skip_whitespace(pnt);
|
pnt = skip_whitespace(pnt);
|
do_source(pnt);
|
do_source(pnt);
|
return;
|
return;
|
}
|
}
|
else if (strncmp(pnt, "mainmenu_option", 15) == 0)
|
else if (strncmp(pnt, "mainmenu_option", 15) == 0)
|
{
|
{
|
menus_seen++;
|
menus_seen++;
|
tok = tok_menuoption;
|
tok = tok_menuoption;
|
pnt += 15;
|
pnt += 15;
|
}
|
}
|
else if (strncmp(pnt, "$MAKE ", 6) == 0)
|
else if (strncmp(pnt, "$MAKE ", 6) == 0)
|
{
|
{
|
tok = tok_make;
|
tok = tok_make;
|
}
|
}
|
else if (strncmp(pnt, "comment", 7) == 0)
|
else if (strncmp(pnt, "comment", 7) == 0)
|
{
|
{
|
tok = tok_comment;
|
tok = tok_comment;
|
pnt += 7;
|
pnt += 7;
|
}
|
}
|
else if (strncmp(pnt, "choice", 6) == 0)
|
else if (strncmp(pnt, "choice", 6) == 0)
|
{
|
{
|
tok = tok_choose;
|
tok = tok_choose;
|
pnt += 6;
|
pnt += 6;
|
}
|
}
|
else if (strncmp(pnt, "define_bool", 11) == 0)
|
else if (strncmp(pnt, "define_bool", 11) == 0)
|
{
|
{
|
tok = tok_define;
|
tok = tok_define;
|
pnt += 11;
|
pnt += 11;
|
}
|
}
|
else if (strncmp(pnt, "define_int", 10) == 0)
|
else if (strncmp(pnt, "define_int", 10) == 0)
|
{
|
{
|
tok = tok_define_int;
|
tok = tok_define_int;
|
pnt += 10;
|
pnt += 10;
|
}
|
}
|
else if (strncmp(pnt, "bool", 4) == 0)
|
else if (strncmp(pnt, "bool", 4) == 0)
|
{
|
{
|
tok = tok_bool;
|
tok = tok_bool;
|
pnt += 4;
|
pnt += 4;
|
}
|
}
|
else if (strncmp(pnt, "tristate", 8) == 0)
|
else if (strncmp(pnt, "tristate", 8) == 0)
|
{
|
{
|
tok = tok_tristate;
|
tok = tok_tristate;
|
pnt += 8;
|
pnt += 8;
|
}
|
}
|
else if (strncmp(pnt, "dep_tristate", 12) == 0)
|
else if (strncmp(pnt, "dep_tristate", 12) == 0)
|
{
|
{
|
tok = tok_dep_tristate;
|
tok = tok_dep_tristate;
|
pnt += 12;
|
pnt += 12;
|
}
|
}
|
else if (strncmp(pnt, "int", 3) == 0)
|
else if (strncmp(pnt, "int", 3) == 0)
|
{
|
{
|
tok = tok_int;
|
tok = tok_int;
|
pnt += 3;
|
pnt += 3;
|
}
|
}
|
else if (strncmp(pnt, "hex", 3) == 0)
|
else if (strncmp(pnt, "hex", 3) == 0)
|
{
|
{
|
tok = tok_hex;
|
tok = tok_hex;
|
pnt += 3;
|
pnt += 3;
|
}
|
}
|
else if (strncmp(pnt, "if", 2) == 0)
|
else if (strncmp(pnt, "if", 2) == 0)
|
{
|
{
|
tok = tok_if;
|
tok = tok_if;
|
pnt += 2;
|
pnt += 2;
|
}
|
}
|
else if (strncmp(pnt, "else", 4) == 0)
|
else if (strncmp(pnt, "else", 4) == 0)
|
{
|
{
|
tok = tok_else;
|
tok = tok_else;
|
pnt += 4;
|
pnt += 4;
|
}
|
}
|
else if (strncmp(pnt, "fi", 2) == 0)
|
else if (strncmp(pnt, "fi", 2) == 0)
|
{
|
{
|
tok = tok_fi;
|
tok = tok_fi;
|
pnt += 2;
|
pnt += 2;
|
}
|
}
|
else if (strncmp(pnt, "endmenu", 7) == 0)
|
else if (strncmp(pnt, "endmenu", 7) == 0)
|
{
|
{
|
tok = tok_endmenu;
|
tok = tok_endmenu;
|
pnt += 7;
|
pnt += 7;
|
}
|
}
|
|
|
if( tok == tok_unknown)
|
if( tok == tok_unknown)
|
{
|
{
|
if( clast != NULL && clast->tok == tok_if
|
if( clast != NULL && clast->tok == tok_if
|
&& strcmp(pnt,"then") == 0) return;
|
&& strcmp(pnt,"then") == 0) return;
|
if( current_file != NULL )
|
if( current_file != NULL )
|
fprintf(stderr, "unknown command=%s(%s %d)\n", pnt,
|
fprintf(stderr, "unknown command=%s(%s %d)\n", pnt,
|
current_file, lineno);
|
current_file, lineno);
|
else
|
else
|
fprintf(stderr, "unknown command=%s(%d)\n", pnt,lineno);
|
fprintf(stderr, "unknown command=%s(%d)\n", pnt,lineno);
|
return;
|
return;
|
}
|
}
|
|
|
/*
|
/*
|
* Allocate memory for this item, and attach it to the end of the linked
|
* Allocate memory for this item, and attach it to the end of the linked
|
* list.
|
* list.
|
*/
|
*/
|
kcfg = (struct kconfig *) malloc(sizeof(struct kconfig));
|
kcfg = (struct kconfig *) malloc(sizeof(struct kconfig));
|
memset(kcfg, 0, sizeof(struct kconfig));
|
memset(kcfg, 0, sizeof(struct kconfig));
|
kcfg->tok = tok;
|
kcfg->tok = tok;
|
if( clast != NULL )
|
if( clast != NULL )
|
{
|
{
|
clast->next = kcfg;
|
clast->next = kcfg;
|
clast = kcfg;
|
clast = kcfg;
|
}
|
}
|
else
|
else
|
{
|
{
|
clast = config = kcfg;
|
clast = config = kcfg;
|
}
|
}
|
|
|
pnt = skip_whitespace(pnt);
|
pnt = skip_whitespace(pnt);
|
|
|
/*
|
/*
|
* Now parse the remaining parts of the option, and attach the results
|
* Now parse the remaining parts of the option, and attach the results
|
* to the structure.
|
* to the structure.
|
*/
|
*/
|
switch (tok)
|
switch (tok)
|
{
|
{
|
case tok_choose:
|
case tok_choose:
|
pnt = get_qstring(pnt, &kcfg->label);
|
pnt = get_qstring(pnt, &kcfg->label);
|
pnt = get_qstring(pnt, &kcfg->optionname);
|
pnt = get_qstring(pnt, &kcfg->optionname);
|
pnt = get_string(pnt, &kcfg->value);
|
pnt = get_string(pnt, &kcfg->value);
|
/*
|
/*
|
* Now we need to break apart the individual options into their
|
* Now we need to break apart the individual options into their
|
* own configuration structures.
|
* own configuration structures.
|
*/
|
*/
|
parse_choices(kcfg, kcfg->optionname);
|
parse_choices(kcfg, kcfg->optionname);
|
free(kcfg->optionname);
|
free(kcfg->optionname);
|
sprintf(tmpbuf, "tmpvar_%d", choose_number++);
|
sprintf(tmpbuf, "tmpvar_%d", choose_number++);
|
kcfg->optionname = strdup(tmpbuf);
|
kcfg->optionname = strdup(tmpbuf);
|
break;
|
break;
|
case tok_define:
|
case tok_define:
|
pnt = get_string(pnt, &kcfg->optionname);
|
pnt = get_string(pnt, &kcfg->optionname);
|
if(*pnt == 'y' || *pnt == 'Y' ) kcfg->value = "1";
|
if(*pnt == 'y' || *pnt == 'Y' ) kcfg->value = "1";
|
if(*pnt == 'n' || *pnt == 'N' ) kcfg->value = "0";
|
if(*pnt == 'n' || *pnt == 'N' ) kcfg->value = "0";
|
if(*pnt == 'm' || *pnt == 'M' ) kcfg->value = "2";
|
if(*pnt == 'm' || *pnt == 'M' ) kcfg->value = "2";
|
break;
|
break;
|
case tok_define_int:
|
case tok_define_int:
|
pnt = get_string(pnt, &kcfg->optionname);
|
pnt = get_string(pnt, &kcfg->optionname);
|
pnt = get_string(pnt, &kcfg->value);
|
pnt = get_string(pnt, &kcfg->value);
|
break;
|
break;
|
case tok_menuname:
|
case tok_menuname:
|
pnt = get_qstring(pnt, &kcfg->label);
|
pnt = get_qstring(pnt, &kcfg->label);
|
break;
|
break;
|
case tok_bool:
|
case tok_bool:
|
case tok_tristate:
|
case tok_tristate:
|
pnt = get_qstring(pnt, &kcfg->label);
|
pnt = get_qstring(pnt, &kcfg->label);
|
pnt = get_string(pnt, &kcfg->optionname);
|
pnt = get_string(pnt, &kcfg->optionname);
|
break;
|
break;
|
case tok_int:
|
case tok_int:
|
case tok_hex:
|
case tok_hex:
|
pnt = get_qstring(pnt, &kcfg->label);
|
pnt = get_qstring(pnt, &kcfg->label);
|
pnt = get_string(pnt, &kcfg->optionname);
|
pnt = get_string(pnt, &kcfg->optionname);
|
pnt = get_string(pnt, &kcfg->value);
|
pnt = get_string(pnt, &kcfg->value);
|
break;
|
break;
|
case tok_dep_tristate:
|
case tok_dep_tristate:
|
pnt = get_qstring(pnt, &kcfg->label);
|
pnt = get_qstring(pnt, &kcfg->label);
|
pnt = get_string(pnt, &kcfg->optionname);
|
pnt = get_string(pnt, &kcfg->optionname);
|
pnt = skip_whitespace(pnt);
|
pnt = skip_whitespace(pnt);
|
if( *pnt == '$') pnt++;
|
if( *pnt == '$') pnt++;
|
pnt = get_string(pnt, &kcfg->depend.str);
|
pnt = get_string(pnt, &kcfg->depend.str);
|
|
|
/*
|
/*
|
* Create a conditional for this object's dependency.
|
* Create a conditional for this object's dependency.
|
*
|
*
|
* We can't use "!= n" because this is internally converted to "!= 0"
|
* We can't use "!= n" because this is internally converted to "!= 0"
|
* and if UMSDOS depends on MSDOS which depends on FAT, then when FAT
|
* and if UMSDOS depends on MSDOS which depends on FAT, then when FAT
|
* is disabled MSDOS has 16 added to its value, making UMSDOS fully
|
* is disabled MSDOS has 16 added to its value, making UMSDOS fully
|
* available. Whew.
|
* available. Whew.
|
*
|
*
|
* This is more of a hack than a fix. Nested "if" conditionals are
|
* This is more of a hack than a fix. Nested "if" conditionals are
|
* probably affected too - that +/- 16 affects things in too many
|
* probably affected too - that +/- 16 affects things in too many
|
* places. But this should do for now.
|
* places. But this should do for now.
|
*/
|
*/
|
sprintf(fake_if,"[ \"$%s\" = \"y\" -o \"$%s\" = \"m\" ]; then",
|
sprintf(fake_if,"[ \"$%s\" = \"y\" -o \"$%s\" = \"m\" ]; then",
|
kcfg->depend.str,kcfg->depend.str);
|
kcfg->depend.str,kcfg->depend.str);
|
kcfg->cond = parse_if(fake_if);
|
kcfg->cond = parse_if(fake_if);
|
if(kcfg->cond == NULL )
|
if(kcfg->cond == NULL )
|
{
|
{
|
exit(1);
|
exit(1);
|
}
|
}
|
break;
|
break;
|
case tok_comment:
|
case tok_comment:
|
pnt = get_qstring(pnt, &kcfg->label);
|
pnt = get_qstring(pnt, &kcfg->label);
|
if( koption != NULL )
|
if( koption != NULL )
|
{
|
{
|
pnt = get_qstring(pnt, &kcfg->label);
|
pnt = get_qstring(pnt, &kcfg->label);
|
koption->label = kcfg->label;
|
koption->label = kcfg->label;
|
koption = NULL;
|
koption = NULL;
|
}
|
}
|
break;
|
break;
|
case tok_menuoption:
|
case tok_menuoption:
|
if( strncmp(pnt, "next_comment", 12) == 0)
|
if( strncmp(pnt, "next_comment", 12) == 0)
|
{
|
{
|
koption = kcfg;
|
koption = kcfg;
|
}
|
}
|
else
|
else
|
{
|
{
|
pnt = get_qstring(pnt, &kcfg->label);
|
pnt = get_qstring(pnt, &kcfg->label);
|
}
|
}
|
break;
|
break;
|
case tok_make:
|
case tok_make:
|
kcfg->value=strdup(pnt);
|
kcfg->value=strdup(pnt);
|
break;
|
break;
|
case tok_else:
|
case tok_else:
|
case tok_fi:
|
case tok_fi:
|
case tok_endmenu:
|
case tok_endmenu:
|
break;
|
break;
|
case tok_if:
|
case tok_if:
|
/*
|
/*
|
* Conditionals are different. For the first level parse, only
|
* Conditionals are different. For the first level parse, only
|
* tok_if and tok_dep_tristate items have a ->cond chain attached.
|
* tok_if and tok_dep_tristate items have a ->cond chain attached.
|
*/
|
*/
|
kcfg->cond = parse_if(pnt);
|
kcfg->cond = parse_if(pnt);
|
if(kcfg->cond == NULL )
|
if(kcfg->cond == NULL )
|
{
|
{
|
exit(1);
|
exit(1);
|
}
|
}
|
break;
|
break;
|
default:
|
default:
|
exit(0);
|
exit(0);
|
}
|
}
|
|
|
return;
|
return;
|
}
|
}
|
|
|
/*
|
/*
|
* Simple function to dump to the screen what the condition chain looks like.
|
* Simple function to dump to the screen what the condition chain looks like.
|
*/
|
*/
|
void dump_if(struct condition * cond)
|
void dump_if(struct condition * cond)
|
{
|
{
|
printf(" ");
|
printf(" ");
|
while(cond != NULL )
|
while(cond != NULL )
|
{
|
{
|
switch(cond->op){
|
switch(cond->op){
|
case op_eq:
|
case op_eq:
|
printf(" = ");
|
printf(" = ");
|
break;
|
break;
|
case op_bang:
|
case op_bang:
|
printf(" ! ");
|
printf(" ! ");
|
break;
|
break;
|
case op_neq:
|
case op_neq:
|
printf(" != ");
|
printf(" != ");
|
break;
|
break;
|
case op_and:
|
case op_and:
|
printf(" -a ");
|
printf(" -a ");
|
break;
|
break;
|
case op_lparen:
|
case op_lparen:
|
printf("(");
|
printf("(");
|
break;
|
break;
|
case op_rparen:
|
case op_rparen:
|
printf(")");
|
printf(")");
|
break;
|
break;
|
case op_variable:
|
case op_variable:
|
printf("$%s", cond->variable.str);
|
printf("$%s", cond->variable.str);
|
break;
|
break;
|
case op_constant:
|
case op_constant:
|
printf("'%s'", cond->variable.str);
|
printf("'%s'", cond->variable.str);
|
break;
|
break;
|
default:
|
default:
|
break;
|
break;
|
}
|
}
|
cond = cond->next;
|
cond = cond->next;
|
}
|
}
|
|
|
printf("\n");
|
printf("\n");
|
}
|
}
|
|
|
static int do_source(char * filename)
|
static int do_source(char * filename)
|
{
|
{
|
char buffer[1024];
|
char buffer[1024];
|
int offset;
|
int offset;
|
int old_lineno;
|
int old_lineno;
|
char * old_file;
|
char * old_file;
|
char * pnt;
|
char * pnt;
|
FILE * infile;
|
FILE * infile;
|
|
|
if( strcmp(filename, "-") == 0 )
|
if( strcmp(filename, "-") == 0 )
|
infile = stdin;
|
infile = stdin;
|
else
|
else
|
infile = fopen(filename,"r");
|
infile = fopen(filename,"r");
|
|
|
/*
|
/*
|
* If our cwd was in the scripts directory, we might have to go up one
|
* If our cwd was in the scripts directory, we might have to go up one
|
* to find the sourced file.
|
* to find the sourced file.
|
*/
|
*/
|
if(!infile) {
|
if(!infile) {
|
strcpy (buffer, "../");
|
strcpy (buffer, "../");
|
strcat (buffer, filename);
|
strcat (buffer, filename);
|
infile = fopen(buffer,"r");
|
infile = fopen(buffer,"r");
|
}
|
}
|
|
|
if(!infile) {
|
if(!infile) {
|
fprintf(stderr,"Unable to open file %s\n", filename);
|
fprintf(stderr,"Unable to open file %s\n", filename);
|
return 1;
|
return 1;
|
}
|
}
|
old_lineno = lineno;
|
old_lineno = lineno;
|
lineno = 0;
|
lineno = 0;
|
if( infile != stdin ) {
|
if( infile != stdin ) {
|
old_file = current_file;
|
old_file = current_file;
|
current_file = filename;
|
current_file = filename;
|
}
|
}
|
offset = 0;
|
offset = 0;
|
while(1)
|
while(1)
|
{
|
{
|
fgets(&buffer[offset], sizeof(buffer) - offset, infile);
|
fgets(&buffer[offset], sizeof(buffer) - offset, infile);
|
if(feof(infile)) break;
|
if(feof(infile)) break;
|
|
|
/*
|
/*
|
* Strip the trailing return character.
|
* Strip the trailing return character.
|
*/
|
*/
|
pnt = buffer + strlen(buffer) - 1;
|
pnt = buffer + strlen(buffer) - 1;
|
if( *pnt == '\n') *pnt-- = 0;
|
if( *pnt == '\n') *pnt-- = 0;
|
lineno++;
|
lineno++;
|
if( *pnt == '\\' )
|
if( *pnt == '\\' )
|
{
|
{
|
offset = pnt - buffer;
|
offset = pnt - buffer;
|
}
|
}
|
else
|
else
|
{
|
{
|
parse(buffer);
|
parse(buffer);
|
offset = 0;
|
offset = 0;
|
}
|
}
|
}
|
}
|
fclose(infile);
|
fclose(infile);
|
if( infile != stdin ) {
|
if( infile != stdin ) {
|
current_file = old_file;
|
current_file = old_file;
|
}
|
}
|
lineno = old_lineno;
|
lineno = old_lineno;
|
return 0;
|
return 0;
|
}
|
}
|
|
|
int main(int argc, char * argv[])
|
int main(int argc, char * argv[])
|
{
|
{
|
#if 0
|
#if 0
|
char buffer[1024];
|
char buffer[1024];
|
char * pnt;
|
char * pnt;
|
struct kconfig * cfg;
|
struct kconfig * cfg;
|
int i;
|
int i;
|
#endif
|
#endif
|
|
|
/*
|
/*
|
* Read stdin to get the top level script.
|
* Read stdin to get the top level script.
|
*/
|
*/
|
do_source("-");
|
do_source("-");
|
|
|
if( menus_seen == 0 )
|
if( menus_seen == 0 )
|
{
|
{
|
fprintf(stderr,"The config.in file for this platform does not support\n");
|
fprintf(stderr,"The config.in file for this platform does not support\n");
|
fprintf(stderr,"menus.\n");
|
fprintf(stderr,"menus.\n");
|
exit(1);
|
exit(1);
|
}
|
}
|
/*
|
/*
|
* Input file is now parsed. Next we need to go through and attach
|
* Input file is now parsed. Next we need to go through and attach
|
* the correct conditions to each of the actual menu items and kill
|
* the correct conditions to each of the actual menu items and kill
|
* the if/else/endif tokens from the list. We also flag the menu items
|
* the if/else/endif tokens from the list. We also flag the menu items
|
* that have other things that depend upon its setting.
|
* that have other things that depend upon its setting.
|
*/
|
*/
|
fix_conditionals(config);
|
fix_conditionals(config);
|
|
|
/*
|
/*
|
* Finally, we generate the wish script.
|
* Finally, we generate the wish script.
|
*/
|
*/
|
dump_tk_script(config);
|
dump_tk_script(config);
|
|
|
#if 0
|
#if 0
|
/*
|
/*
|
* Now dump what we have so far. This is only for debugging so that
|
* Now dump what we have so far. This is only for debugging so that
|
* we can display what we think we have in the list.
|
* we can display what we think we have in the list.
|
*/
|
*/
|
for(cfg = config; cfg; cfg = cfg->next)
|
for(cfg = config; cfg; cfg = cfg->next)
|
{
|
{
|
|
|
if(cfg->cond != NULL && cfg->tok != tok_if)
|
if(cfg->cond != NULL && cfg->tok != tok_if)
|
dump_if(cfg->cond);
|
dump_if(cfg->cond);
|
|
|
switch(cfg->tok)
|
switch(cfg->tok)
|
{
|
{
|
case tok_menuname:
|
case tok_menuname:
|
printf("main_menuname ");
|
printf("main_menuname ");
|
break;
|
break;
|
case tok_bool:
|
case tok_bool:
|
printf("bool ");
|
printf("bool ");
|
break;
|
break;
|
case tok_tristate:
|
case tok_tristate:
|
printf("tristate ");
|
printf("tristate ");
|
break;
|
break;
|
case tok_dep_tristate:
|
case tok_dep_tristate:
|
printf("dep_tristate ");
|
printf("dep_tristate ");
|
break;
|
break;
|
case tok_int:
|
case tok_int:
|
printf("int ");
|
printf("int ");
|
break;
|
break;
|
case tok_hex:
|
case tok_hex:
|
printf("hex ");
|
printf("hex ");
|
break;
|
break;
|
case tok_comment:
|
case tok_comment:
|
printf("comment ");
|
printf("comment ");
|
break;
|
break;
|
case tok_menuoption:
|
case tok_menuoption:
|
printf("menuoption ");
|
printf("menuoption ");
|
break;
|
break;
|
case tok_else:
|
case tok_else:
|
printf("else");
|
printf("else");
|
break;
|
break;
|
case tok_fi:
|
case tok_fi:
|
printf("fi");
|
printf("fi");
|
break;
|
break;
|
case tok_if:
|
case tok_if:
|
printf("if");
|
printf("if");
|
break;
|
break;
|
default:
|
default:
|
}
|
}
|
|
|
switch(cfg->tok)
|
switch(cfg->tok)
|
{
|
{
|
case tok_menuoption:
|
case tok_menuoption:
|
case tok_comment:
|
case tok_comment:
|
case tok_menuname:
|
case tok_menuname:
|
printf("%s\n", cfg->label);
|
printf("%s\n", cfg->label);
|
break;
|
break;
|
case tok_bool:
|
case tok_bool:
|
case tok_tristate:
|
case tok_tristate:
|
case tok_dep_tristate:
|
case tok_dep_tristate:
|
case tok_int:
|
case tok_int:
|
case tok_hex:
|
case tok_hex:
|
printf("%s %s\n", cfg->label, cfg->optionname);
|
printf("%s %s\n", cfg->label, cfg->optionname);
|
break;
|
break;
|
case tok_if:
|
case tok_if:
|
dump_if(cfg->cond);
|
dump_if(cfg->cond);
|
break;
|
break;
|
case tok_nop:
|
case tok_nop:
|
case tok_endmenu:
|
case tok_endmenu:
|
break;
|
break;
|
default:
|
default:
|
printf("\n");
|
printf("\n");
|
}
|
}
|
}
|
}
|
#endif
|
#endif
|
|
|
return 0;
|
return 0;
|
|
|
}
|
}
|
|
|