/* * Tokenize a choice list. Choices appear as pairs of strings; * note that I am parsing *inside* the double quotes. Ugh. */ static const char * tokenize_choices( struct kconfig * cfg_choose, const char * pnt ) { int default_checked = 0; for ( ; ; ) { struct kconfig * cfg; char * buffer = malloc( 64 ); /* skip whitespace */ while ( *pnt == ' ' || *pnt == '\t' ) pnt++; if ( *pnt == '\0' ) return pnt; /* allocate a new kconfig line */ cfg = malloc( sizeof(*cfg) ); memset( cfg, 0, sizeof(*cfg) ); if ( config_last == NULL ) { config_last = config_list = cfg; } else { config_last->next = cfg; config_last = cfg; } /* fill out the line */ cfg->token = token_choice_item; cfg->cfg_parent = cfg_choose; pnt = get_string( pnt, &cfg->label ); if ( ! default_checked && ! strncmp( cfg->label, cfg_choose->value, strlen( cfg_choose->value ) ) ) { default_checked = 1; free( cfg_choose->value ); cfg_choose->value = cfg->label; } while ( *pnt == ' ' || *pnt == '\t' ) pnt++; pnt = get_string( pnt, &buffer ); cfg->nameindex = get_varnum( buffer ); } if ( ! default_checked ) syntax_error( "bad 'choice' default value" ); return pnt; }
/* * Tokenize one line. */ static void tokenize_line( const char * pnt ) { static struct kconfig * last_menuoption = NULL; enum e_token token; struct kconfig * cfg; struct dependency ** dep_ptr; char * buffer = malloc( 64 ); /* skip white space */ while ( *pnt == ' ' || *pnt == '\t' ) pnt++; /* * categorize the next token */ #define match_token(t, s) \ if (strncmp(pnt, s, strlen(s)) == 0) { token = t; pnt += strlen(s); break; } token = token_UNKNOWN; switch ( *pnt ) { default: break; case '#': case '\0': return; case 'b': match_token( token_bool, "bool" ); break; case 'c': match_token( token_choice_header, "choice" ); match_token( token_comment, "comment" ); break; case 'd': match_token( token_define_bool, "define_bool" ); match_token( token_define_hex, "define_hex" ); match_token( token_define_int, "define_int" ); match_token( token_define_string, "define_string" ); match_token( token_define_tristate, "define_tristate" ); match_token( token_dep_bool, "dep_bool" ); match_token( token_dep_mbool, "dep_mbool" ); match_token( token_dep_tristate, "dep_tristate" ); break; case 'e': match_token( token_else, "else" ); match_token( token_endmenu, "endmenu" ); break; case 'f': match_token( token_fi, "fi" ); break; case 'h': match_token( token_hex, "hex" ); break; case 'i': match_token( token_if, "if" ); match_token( token_int, "int" ); break; case 'm': match_token( token_mainmenu_name, "mainmenu_name" ); match_token( token_mainmenu_option, "mainmenu_option" ); break; case 's': match_token( token_source, "source" ); match_token( token_string, "string" ); break; case 't': match_token( token_then, "then" ); match_token( token_tristate, "tristate" ); break; case 'u': match_token( token_unset, "unset" ); break; } #undef match_token if ( token == token_source ) { while ( *pnt == ' ' || *pnt == '\t' ) pnt++; do_source( pnt ); return; } if ( token == token_then ) { if ( config_last != NULL && config_last->token == token_if ) return; syntax_error( "bogus 'then'" ); } #if 0 if ( token == token_unset ) { fprintf( stderr, "Ignoring 'unset' command\n" ); return; } #endif if ( token == token_UNKNOWN ) syntax_error( "unknown command" ); /* * Allocate an item. */ cfg = malloc( sizeof(*cfg) ); memset( cfg, 0, sizeof(*cfg) ); if ( config_last == NULL ) { config_last = config_list = cfg; } else { config_last->next = cfg; config_last = cfg; } /* * Tokenize the arguments. */ while ( *pnt == ' ' || *pnt == '\t' ) pnt++; cfg->token = token; switch ( token ) { default: syntax_error( "unknown token" ); case token_bool: case token_tristate: pnt = get_qstring ( pnt, &cfg->label ); pnt = get_string ( pnt, &buffer ); cfg->nameindex = get_varnum( buffer ); break; case token_choice_header: { static int choose_number = 0; char * choice_list; pnt = get_qstring ( pnt, &cfg->label ); pnt = get_qstring ( pnt, &choice_list ); pnt = get_string ( pnt, &cfg->value ); cfg->nameindex = -(choose_number++); tokenize_choices( cfg, choice_list ); free( choice_list ); } break; case token_comment: pnt = get_qstring(pnt, &cfg->label); if ( last_menuoption != NULL ) { pnt = get_qstring(pnt, &cfg->label); if (cfg->label == NULL) syntax_error( "missing comment text" ); last_menuoption->label = cfg->label; last_menuoption = NULL; } break; case token_define_bool: case token_define_tristate: pnt = get_string( pnt, &buffer ); cfg->nameindex = get_varnum( buffer ); while ( *pnt == ' ' || *pnt == '\t' ) pnt++; if ( ( pnt[0] == 'Y' || pnt[0] == 'M' || pnt[0] == 'N' || pnt[0] == 'y' || pnt[0] == 'm' || pnt[0] == 'n' ) && ( pnt[1] == '\0' || pnt[1] == ' ' || pnt[1] == '\t' ) ) { if ( *pnt == 'n' || *pnt == 'N' ) cfg->value = strdup( "CONSTANT_N" ); else if ( *pnt == 'y' || *pnt == 'Y' ) cfg->value = strdup( "CONSTANT_Y" ); else if ( *pnt == 'm' || *pnt == 'M' ) cfg->value = strdup( "CONSTANT_M" ); } else if ( *pnt == '$' ) { pnt++; pnt = get_string( pnt, &cfg->value ); } else { syntax_error( "unknown define_bool value" ); } get_varnum( cfg->value ); break; case token_define_hex: case token_define_int: pnt = get_string( pnt, &buffer ); cfg->nameindex = get_varnum( buffer ); pnt = get_string( pnt, &cfg->value ); break; case token_define_string: pnt = get_string( pnt, &buffer ); cfg->nameindex = get_varnum( buffer ); pnt = get_qnqstring( pnt, &cfg->value ); if (cfg->value == NULL) syntax_error( "missing value" ); break; case token_dep_bool: case token_dep_mbool: case token_dep_tristate: pnt = get_qstring ( pnt, &cfg->label ); pnt = get_string ( pnt, &buffer ); cfg->nameindex = get_varnum( buffer ); while ( *pnt == ' ' || *pnt == '\t' ) pnt++; dep_ptr = &(cfg->depend); do { *dep_ptr = (struct dependency *) malloc( sizeof( struct dependency ) ); (*dep_ptr)->next = NULL; if ( ( pnt[0] == 'Y' || pnt[0] == 'M' || pnt[0] == 'N' || pnt[0] == 'y' || pnt[0] == 'm' || pnt[0] == 'n' ) && ( pnt[1] == '\0' || pnt[1] == ' ' || pnt[1] == '\t' ) ) { /* dep_tristate 'foo' CONFIG_FOO m */ if ( pnt[0] == 'Y' || pnt[0] == 'y' ) (*dep_ptr)->name = strdup( "CONSTANT_Y" ); else if ( pnt[0] == 'N' || pnt[0] == 'n' ) (*dep_ptr)->name = strdup( "CONSTANT_N" ); else (*dep_ptr)->name = strdup( "CONSTANT_M" ); pnt++; get_varnum( (*dep_ptr)->name ); } else if ( *pnt == '$' ) { pnt++; pnt = get_string( pnt, &(*dep_ptr)->name ); get_varnum( (*dep_ptr)->name ); } else { syntax_error( "can't handle dep_bool/dep_mbool/dep_tristate condition" ); } dep_ptr = &(*dep_ptr)->next; while ( *pnt == ' ' || *pnt == '\t' ) pnt++; } while ( *pnt ); /* * Create a conditional for this object's dependencies. */ { char fake_if [1024]; struct dependency * dep; struct condition ** cond_ptr; int first = 1; cond_ptr = &(cfg->cond); for ( dep = cfg->depend; dep; dep = dep->next ) { if ( token == token_dep_tristate && ! strcmp( dep->name, "CONSTANT_M" ) ) { continue; } if ( first ) { first = 0; } else { *cond_ptr = malloc( sizeof(struct condition) ); memset( *cond_ptr, 0, sizeof(struct condition) ); (*cond_ptr)->op = op_and; cond_ptr = &(*cond_ptr)->next; } *cond_ptr = malloc( sizeof(struct condition) ); memset( *cond_ptr, 0, sizeof(struct condition) ); (*cond_ptr)->op = op_lparen; if ( token == token_dep_bool ) sprintf( fake_if, "[ \"$%s\" = \"y\" -o \"$%s\" = \"\" ]; then", dep->name, dep->name ); else sprintf( fake_if, "[ \"$%s\" = \"y\" -o \"$%s\" = \"m\" -o \"$%s\" = \"\" ]; then", dep->name, dep->name, dep->name ); (*cond_ptr)->next = tokenize_if( fake_if ); while ( *cond_ptr ) cond_ptr = &(*cond_ptr)->next; *cond_ptr = malloc( sizeof(struct condition) ); memset( *cond_ptr, 0, sizeof(struct condition) ); (*cond_ptr)->op = op_rparen; cond_ptr = &(*cond_ptr)->next; } } break; case token_else: case token_endmenu: case token_fi: break; case token_hex: case token_int: pnt = get_qstring ( pnt, &cfg->label ); pnt = get_string ( pnt, &buffer ); cfg->nameindex = get_varnum( buffer ); pnt = get_string ( pnt, &cfg->value ); break; case token_string: pnt = get_qstring ( pnt, &cfg->label ); pnt = get_string ( pnt, &buffer ); cfg->nameindex = get_varnum( buffer ); pnt = get_qnqstring ( pnt, &cfg->value ); if (cfg->value == NULL) syntax_error( "missing initial value" ); break; case token_if: cfg->cond = tokenize_if( pnt ); break; case token_mainmenu_name: pnt = get_qstring( pnt, &cfg->label ); break; case token_mainmenu_option: if ( strncmp( pnt, "next_comment", 12 ) == 0 ) last_menuoption = cfg; else pnt = get_qstring( pnt, &cfg->label ); break; case token_unset: pnt = get_string( pnt, &buffer ); cfg->nameindex = get_varnum( buffer ); while ( *pnt == ' ' || *pnt == '\t' ) pnt++; while (*pnt) { cfg->next = (struct kconfig *) malloc( sizeof(struct kconfig) ); memset( cfg->next, 0, sizeof(struct kconfig) ); cfg = cfg->next; cfg->token = token_unset; pnt = get_string( pnt, &buffer ); cfg->nameindex = get_varnum( buffer ); while ( *pnt == ' ' || *pnt == '\t' ) pnt++; } break; } return; }
/* * Tokenize an 'if' statement condition. */ static struct condition * tokenize_if( const char * pnt ) { struct condition * list; struct condition * last; struct condition * prev; /* eat the open bracket */ while ( *pnt == ' ' || *pnt == '\t' ) pnt++; if ( *pnt != '[' ) syntax_error( "bad 'if' condition" ); pnt++; list = last = NULL; for ( ; ; ) { struct condition * cond; /* advance to the next token */ while ( *pnt == ' ' || *pnt == '\t' ) pnt++; if ( *pnt == '\0' ) syntax_error( "unterminated 'if' condition" ); if ( *pnt == ']' ) return list; /* allocate a new token */ cond = malloc( sizeof(*cond) ); memset( cond, 0, sizeof(*cond) ); if ( last == NULL ) { list = last = cond; prev = NULL; } else { prev = last; last->next = cond; last = cond; } /* determine the token value */ if ( *pnt == '-' && pnt[1] == 'a' ) { if ( ! prev || ( prev->op != op_variable && prev->op != op_constant ) ) syntax_error( "incorrect argument" ); cond->op = op_and; pnt += 2; continue; } if ( *pnt == '-' && pnt[1] == 'o' ) { if ( ! prev || ( prev->op != op_variable && prev->op != op_constant ) ) syntax_error( "incorrect argument" ); cond->op = op_or; pnt += 2; continue; } if ( *pnt == '!' && pnt[1] == '=' ) { if ( ! prev || ( prev->op != op_variable && prev->op != op_constant ) ) syntax_error( "incorrect argument" ); cond->op = op_neq; pnt += 2; continue; } if ( *pnt == '=' ) { if ( ! prev || ( prev->op != op_variable && prev->op != op_constant ) ) syntax_error( "incorrect argument" ); cond->op = op_eq; pnt += 1; continue; } if ( *pnt == '!' ) { if ( prev && ( prev->op != op_and && prev->op != op_or && prev->op != op_bang ) ) syntax_error( "incorrect argument" ); cond->op = op_bang; pnt += 1; continue; } if ( *pnt == '"' ) { const char * word; if ( prev && ( prev->op == op_variable || prev->op == op_constant ) ) syntax_error( "incorrect argument" ); /* advance to the word */ pnt++; if ( *pnt == '$' ) { cond->op = op_variable; pnt++; } else { cond->op = op_constant; } /* find the end of the word */ word = pnt; for ( ; ; ) { if ( *pnt == '\0' ) syntax_error( "unterminated double quote" ); if ( *pnt == '"' ) break; pnt++; } /* store a copy of this word */ { char * str = malloc( pnt - word + 1 ); memcpy( str, word, pnt - word ); str [pnt - word] = '\0'; if ( cond->op == op_variable ) { cond->nameindex = get_varnum( str ); free( str ); } else /* op_constant */ { cond->str = str; } } pnt++; continue; } /* unknown token */ syntax_error( "bad if condition" ); } }
static void generate_update_var( struct kconfig * scfg, int menu_num ) { struct kconfig * cfg; if ( menu_num>0 ) { printf( "proc update_define_menu%d {} {\n", menu_num ); printf( "\tupdate_define_mainmenu\n" ); } else printf( "proc update_define_mainmenu {} {\n" ); clear_globalflags(); global( "CONFIG_MODULES" ); vartable[ get_varnum( "CONFIG_MODULES" ) ].global_written = 1; for ( cfg = scfg; cfg != NULL; cfg = cfg->next ) { if ( cfg->menu_number == menu_num && (cfg->token == token_define_bool || cfg->token == token_define_tristate || cfg->token == token_define_hex || cfg->token == token_define_int || cfg->token == token_define_string || cfg->token == token_unset || cfg->token == token_tristate) ) { if ( ! vartable[cfg->nameindex].global_written ) { vartable[cfg->nameindex].global_written = 1; global( vartable[cfg->nameindex].name ); } } } /* * set all conditional bool/tristates to off unless changed later */ for ( cfg = scfg; cfg != NULL; cfg = cfg->next ) { if (cfg->menu_number != menu_num) continue; if (!cfg->cond) continue; switch (cfg->token) { case token_bool: case token_tristate: if (! vartable[cfg->nameindex].global_written) { vartable[cfg->nameindex].global_written = 1; global(vartable[cfg->nameindex].name); } printf("set %s [expr $%s|16]\n", vartable[cfg->nameindex].name, vartable[cfg->nameindex].name); break; default: break; } } for ( cfg = scfg; cfg != NULL; cfg = cfg->next ) { char tmp[20]; struct kconfig * cfg1; if ( cfg->menu_number == menu_num ) { switch ( cfg->token ) { default: case token_choice_item: break; case token_choice_header: sprintf( tmp, "tmpvar_%d", -(cfg->nameindex) ); global( tmp ); for ( cfg1 = cfg->next; cfg1 != NULL && cfg1->token == token_choice_item; cfg1 = cfg1->next ) { vartable[cfg1->nameindex].global_written = 1; global( vartable[cfg1->nameindex].name ); printf( "\tif {$tmpvar_%d == \"%s\"} then {set %s 1} else {set %s 0}\n", -(cfg->nameindex), cfg1->label, vartable[cfg1->nameindex].name, vartable[cfg1->nameindex].name ); } break; case token_bool: case token_define_bool: case token_define_tristate: case token_define_hex: case token_define_int: case token_define_string: case token_dep_bool: case token_dep_tristate: case token_dep_mbool: case token_int: case token_hex: case token_mainmenu_option: case token_tristate: case token_unset: if ( cfg->cond != NULL ) generate_if( cfg, cfg->cond, menu_num, -2 ); else switch ( cfg->token ) { case token_tristate: printf( "\n\tif {($CONFIG_MODULES == 0)} then {if {($%s == 2)} then {set %s 1}}\n", vartable[cfg->nameindex].name, vartable[cfg->nameindex].name ); break; case token_define_bool: case token_define_tristate: if ( ! vartable[get_varnum( cfg->value )].global_written ) { vartable[get_varnum( cfg->value )].global_written = 1; global( cfg->value ); } printf( "\tset %s $%s\n", vartable[cfg->nameindex].name, cfg->value ); break; case token_define_hex: case token_define_int: printf( "\tset %s %s\n", vartable[cfg->nameindex].name, cfg->value ); break; case token_define_string: printf( "\tset %s \"%s\"\n", vartable[cfg->nameindex].name, cfg->value ); break; case token_unset: printf( "\tset %s 4\n", vartable[cfg->nameindex].name ); default: break; } } } } printf( "}\n\n\n" ); }
/* * Generate a line that writes a variable to the output file. */ void generate_writeconfig( struct kconfig * cfg ) { struct condition * cond; struct dependency * tmp; int depmod = 2; /* * Generate global declaration for this symbol. */ if ( cfg->token != token_comment ) { if ( cfg->nameindex > 0 && ! vartable[cfg->nameindex].global_written ) { vartable[cfg->nameindex].global_written = 1; global( vartable[cfg->nameindex].name ); } if ( cfg->token == token_define_tristate || cfg->token == token_define_bool ) { if ( ! vartable[get_varnum( cfg->value )].global_written ) { vartable[get_varnum( cfg->value )].global_written = 1; global( cfg->value ); } } else if ( cfg->nameindex <= 0 && cfg->token == token_choice_header ) { printf( "\tglobal tmpvar_%d\n", -(cfg->nameindex) ); } } /* * Generate global declarations for the condition chain. */ for ( cond = cfg->cond; cond != NULL; cond = cond->next ) { switch( cond->op ) { default: break; case op_variable: if ( ! vartable[cond->nameindex].global_written ) { vartable[cond->nameindex].global_written = 1; global( vartable[cond->nameindex].name ); } break; } } /* * Generate indentation. */ printf( "\t" ); /* * Generate the conditional. */ if ( cfg->cond != NULL ) { printf( "if {" ); for ( cond = cfg->cond; cond != NULL; cond = cond->next ) { switch ( cond->op ) { default: break; case op_bang: printf( " ! " ); break; case op_eq: printf( " == " ); break; case op_neq: printf( " != " ); break; case op_and: printf( " && " ); break; case op_and1: printf( " && " ); break; case op_or: printf( " || " ); break; case op_lparen: printf( "(" ); break; case op_rparen: printf( ")" ); break; case op_variable: printf( "$%s", vartable[cond->nameindex].name ); break; case op_constant: if ( strcmp( cond->str, "n" ) == 0 ) printf( "0" ); else if ( strcmp( cond->str, "y" ) == 0 ) printf( "1" ); else if ( strcmp( cond->str, "m" ) == 0 ) printf( "2" ); else if ( strcmp( cond->str, "" ) == 0 ) printf( "4" ); else printf( "\"%s\"", cond->str ); break; } } printf( "} then {" ); } /* * Generate a procedure call to write the value. * This code depends on the write_* procedures in header.tk. */ switch ( cfg->token ) { default: if ( cfg->cond != NULL ) printf( " }" ); printf( "\n" ); break; case token_bool: case token_tristate: printf( "write_tristate $cfg $autocfg %s $%s [list $notmod] 2", vartable[cfg->nameindex].name, vartable[cfg->nameindex].name ); if ( cfg->cond != NULL ) printf( " }" ); printf( "\n" ); break; case token_choice_header: /* * This is funky code -- it fails if there were any conditionals. * Fortunately all the conditionals got stripped off somewhere * else. */ { struct kconfig * cfg1; for ( cfg1 = cfg->next; cfg1 != NULL && cfg1->token == token_choice_item; cfg1 = cfg1->next ) { printf("\n\tif { $tmpvar_%d == \"%s\" } then { write_tristate $cfg $autocfg %s 1 [list $notmod] 2 } else { write_tristate $cfg $autocfg %s 0 [list $notmod] 2 }", -(cfg->nameindex), cfg1->label, vartable[cfg1->nameindex].name, vartable[cfg1->nameindex].name ); } } if ( cfg->cond != NULL ) printf( "}" ); printf( "\n" ); break; case token_choice_item: fprintf( stderr, "Internal error on token_choice_item\n" ); exit( 1 ); case token_comment: printf( "write_comment $cfg $autocfg \"%s\"", cfg->label ); if ( cfg->cond != NULL ) printf( "}" ); printf( "\n" ); break; case token_define_bool: case token_define_tristate: if ( cfg->cond == NULL ) { printf( "write_tristate $cfg $autocfg %s $%s [list $notmod] 2\n", vartable[cfg->nameindex].name, vartable[cfg->nameindex].name ); } else { printf( "write_tristate $cfg $autocfg %s $%s [list $notmod] 2 }\n", vartable[cfg->nameindex].name, cfg->value ); } break; case token_dep_mbool: depmod = 1; case token_dep_bool: case token_dep_tristate: printf( "write_tristate $cfg $autocfg %s $%s [list", vartable[cfg->nameindex].name, vartable[cfg->nameindex].name ); for ( tmp = cfg->depend; tmp; tmp = tmp->next ) printf( " $%s", tmp->name ); printf( "] %d", depmod ); if ( cfg->cond != NULL ) printf( " }" ); printf( "\n" ); break; case token_define_hex: printf( "write_hex $cfg $autocfg %s %s $notmod", vartable[cfg->nameindex].name, cfg->value ); if ( cfg->cond != NULL ) printf( " }" ); printf( "\n" ); break; case token_define_int: printf( "write_int $cfg $autocfg %s %s $notmod", vartable[cfg->nameindex].name, cfg->value ); if ( cfg->cond != NULL ) printf( " }" ); printf( "\n" ); break; case token_define_string: printf( "write_string $cfg $autocfg %s \"%s\" $notmod", vartable[cfg->nameindex].name, cfg->value ); if ( cfg->cond != NULL ) printf( " }" ); printf( "\n" ); break; case token_hex: printf( "write_hex $cfg $autocfg %s $%s $notmod", vartable[cfg->nameindex].name, vartable[cfg->nameindex].name ); if ( cfg->cond != NULL ) printf( " }" ); printf( "\n" ); break; case token_int: printf( "write_int $cfg $autocfg %s $%s $notmod", vartable[cfg->nameindex].name, vartable[cfg->nameindex].name ); if ( cfg->cond != NULL ) printf( " }" ); printf( "\n" ); break; case token_string: printf( "write_string $cfg $autocfg %s \"$%s\" $notmod", vartable[cfg->nameindex].name, vartable[cfg->nameindex].name ); if ( cfg->cond != NULL ) printf( " }" ); printf( "\n" ); break; } }
/* * This function walks the chain of conditions that we got from cond.c * and creates a TCL conditional to enable/disable a given widget. */ void generate_if( struct kconfig * cfg, struct condition * ocond, int menu_num, int line_num ) { struct condition * cond; struct dependency * tmp; struct kconfig * cfg1; if ( line_num >= -1 ) { if ( cfg->token == token_define_bool || cfg->token == token_define_hex || cfg->token == token_define_int || cfg->token == token_define_string || cfg->token == token_define_tristate || cfg->token == token_unset ) return; if ( cfg->token == token_comment && line_num == -1 ) return; } else { if ( cfg->token == token_string || cfg->token == token_mainmenu_option ) return; } /* * First write any global declarations we need for this conditional. */ for ( cond = ocond; cond != NULL; cond = cond->next ) { switch ( cond->op ) { default: break; case op_variable: if ( ! vartable[cond->nameindex].global_written ) { vartable[cond->nameindex].global_written = 1; global( vartable[cond->nameindex].name ); } break; } } /* * Now write this option. */ if ( cfg->nameindex > 0 && ! vartable[cfg->nameindex].global_written ) { vartable[cfg->nameindex].global_written = 1; global( vartable[cfg->nameindex].name ); } /* * Generate the body of the conditional. */ printf( "\tif {" ); for ( cond = ocond; cond != NULL; cond = cond->next ) { switch ( cond->op ) { default: break; case op_bang: printf( " ! " ); break; case op_eq: printf( " == " ); break; case op_neq: printf( " != " ); break; case op_and: printf( " && " ); break; case op_and1: printf( " && " ); break; case op_or: printf( " || " ); break; case op_lparen: printf( "(" ); break; case op_rparen: printf( ")" ); break; case op_variable: printf( "$%s", vartable[cond->nameindex].name ); break; case op_constant: if ( strcmp( cond->str, "y" ) == 0 ) printf( "1" ); else if ( strcmp( cond->str, "n" ) == 0 ) printf( "0" ); else if ( strcmp( cond->str, "m" ) == 0 ) printf( "2" ); else if ( strcmp( cond->str, "" ) == 0 ) printf( "4" ); else printf( "\"%s\"", cond->str ); break; } } printf( "} then {" ); /* * Generate a procedure call to write the value. * This code depends on procedures in header.tk. */ if ( line_num >= -1 ) { int modtoyes = 0; switch ( cfg->token ) { default: printf( " }\n" ); break; case token_dep_mbool: modtoyes = 1; case token_dep_bool: printf( "\n" ); for ( tmp = cfg->depend; tmp; tmp = tmp->next ) if ( ! vartable[get_varnum( tmp->name )].global_written ) { global( tmp->name ); } printf( "\tset tmpvar_dep [effective_dep [list" ); for ( tmp = cfg->depend; tmp; tmp = tmp->next ) printf( " $%s", tmp->name ); printf( "]];set %s [sync_bool $%s $tmpvar_dep %d];", vartable[cfg->nameindex].name, vartable[cfg->nameindex].name, modtoyes ); printf( "if {$tmpvar_dep != 1" ); if (modtoyes) printf( " && $tmpvar_dep != 2" ); printf( "} then {configure_entry .menu%d.config.f.x%d disabled {y};", menu_num, line_num ); printf( "} else {" ); printf( "configure_entry .menu%d.config.f.x%d normal {y};", menu_num, line_num ); printf( "}; " ); case token_bool: if ( cfg->token == token_bool ) printf( "\n\t" ); printf( "configure_entry .menu%d.config.f.x%d normal {n l", menu_num, line_num ); if ( cfg->token == token_bool ) printf( " y" ); printf( "}" ); printf( "} else {"); printf( "configure_entry .menu%d.config.f.x%d disabled {y n l}}\n", menu_num, line_num ); break; case token_choice_header: printf( "configure_entry .menu%d.config.f.x%d normal {x l}", menu_num, line_num ); printf( "} else {" ); printf( "configure_entry .menu%d.config.f.x%d disabled {x l}", menu_num, line_num ); printf( "}\n" ); break; case token_choice_item: fprintf( stderr, "Internal error on token_choice_item\n" ); exit( 1 ); case token_dep_tristate: printf( "\n" ); for ( tmp = cfg->depend; tmp; tmp = tmp->next ) if ( ! vartable[get_varnum( tmp->name )].global_written ) { global( tmp->name ); } printf( "\tset tmpvar_dep [effective_dep [list" ); for ( tmp = cfg->depend; tmp; tmp = tmp->next ) printf( " $%s", tmp->name ); printf( "]];set %s [sync_tristate $%s $tmpvar_dep];", vartable[cfg->nameindex].name, vartable[cfg->nameindex].name ); printf( "\tif {$tmpvar_dep != 1} then {" ); printf( "configure_entry .menu%d.config.f.x%d disabled {y}", menu_num, line_num ); printf( "} else {" ); printf( "configure_entry .menu%d.config.f.x%d normal {y}", menu_num, line_num ); printf( "}; " ); printf( "if {$tmpvar_dep == 0} then {" ); printf( "configure_entry .menu%d.config.f.x%d disabled {m}", menu_num, line_num ); printf( "} else {" ); printf( "configure_entry .menu%d.config.f.x%d normal {m}", menu_num, line_num ); printf( "}; " ); case token_tristate: if ( cfg->token == token_tristate ) { printf( "\n\tconfigure_entry .menu%d.config.f.x%d normal {y}; ", menu_num, line_num ); } printf( "if {($CONFIG_MODULES == 1)} then {" ); printf( "configure_entry .menu%d.config.f.x%d normal {m}} else {", menu_num, line_num ); printf( "configure_entry .menu%d.config.f.x%d disabled {m}}; ", menu_num, line_num ); printf( "configure_entry .menu%d.config.f.x%d normal {n l}", menu_num, line_num ); /* * Or in a bit to the variable - this causes all of the radiobuttons * to be deselected (i.e. not be red). */ printf( "} else {" ); printf( "configure_entry .menu%d.config.f.x%d disabled {y n m l}}\n", menu_num, line_num ); break; case token_hex: case token_int: case token_string: printf( ".menu%d.config.f.x%d.x configure -state normal -foreground [ cget .ref -foreground ]; ", menu_num, line_num ); printf( ".menu%d.config.f.x%d.l configure -state normal; ", menu_num, line_num ); printf( "} else {" ); printf( ".menu%d.config.f.x%d.x configure -state disabled -foreground [ cget .ref -disabledforeground ]; ", menu_num, line_num ); printf( ".menu%d.config.f.x%d.l configure -state disabled}\n", menu_num, line_num ); break; case token_comment: case token_mainmenu_option: if ( line_num >= 0 ) { printf( "configure_entry .menu%d.config.f.x%d normal {m}", menu_num, line_num ); printf( "} else {" ); printf( "configure_entry .menu%d.config.f.x%d disabled {m}}\n", menu_num, line_num ); } else printf( ".f0.x%d configure -state normal } else { .f0.x%d configure -state disabled }\n", menu_num, menu_num ); break; } } else { int modtoyes = 0; switch ( cfg->token ) { default: printf( " }\n" ); break; case token_dep_mbool: modtoyes = 1; case token_dep_bool: printf( "\n" ); for ( tmp = cfg->depend; tmp; tmp = tmp->next ) if ( ! vartable[get_varnum( tmp->name )].global_written ) { global( tmp->name ); } printf( "\tset tmpvar_dep [effective_dep [list" ); for ( tmp = cfg->depend; tmp; tmp = tmp->next ) printf( " $%s", tmp->name ); printf( "]];set %s [sync_bool $%s $tmpvar_dep %d];", vartable[cfg->nameindex].name, vartable[cfg->nameindex].name, modtoyes ); case token_bool: if ( cfg->token == token_bool ) printf( "\n\t" ); printf( "set %s [expr $%s&15]", vartable[cfg->nameindex].name, vartable[cfg->nameindex].name ); printf( "}\n"); break; case token_choice_header: printf( "} else {" ); for ( cfg1 = cfg->next; cfg1 != NULL && cfg1->token == token_choice_item; cfg1 = cfg1->next ) printf( "set %s 4;", vartable[cfg1->nameindex].name ); printf( "}\n" ); break; case token_choice_item: fprintf( stderr, "Internal error on token_choice_item\n" ); exit( 1 ); case token_define_bool: case token_define_tristate: if ( ! vartable[get_varnum( cfg->value )].global_written ) { global( cfg->value ); } printf( "set %s $%s }\n", vartable[cfg->nameindex].name, cfg->value ); break; case token_define_hex: case token_define_int: printf( "set %s %s }\n", vartable[cfg->nameindex].name, cfg->value ); break; case token_define_string: printf( "set %s \"%s\" }\n", vartable[cfg->nameindex].name, cfg->value ); break; case token_dep_tristate: printf( "\n" ); for ( tmp = cfg->depend; tmp; tmp = tmp->next ) if ( ! vartable[get_varnum( tmp->name )].global_written ) { global( tmp->name ); } printf( "\tset tmpvar_dep [effective_dep [list" ); for ( tmp = cfg->depend; tmp; tmp = tmp->next ) printf( " $%s", tmp->name ); printf( "]]; set %s [sync_tristate $%s $tmpvar_dep]; ", vartable[cfg->nameindex].name, vartable[cfg->nameindex].name ); case token_tristate: if ( cfg->token == token_tristate ) printf( "if {($CONFIG_MODULES == 0) && ($%s == 2)} then {set %s 1}; ", vartable[cfg->nameindex].name, vartable[cfg->nameindex].name ); /* * Or in a bit to the variable - this causes all of the radiobuttons * to be deselected (i.e. not be red). */ printf( "set %s [expr $%s&15]", vartable[cfg->nameindex].name, vartable[cfg->nameindex].name ); printf( "}\n" ); break; case token_hex: case token_int: if ( cfg->value && *cfg->value == '$' ) { int i = get_varnum( cfg->value+1 ); printf( "\n" ); if ( ! vartable[i].global_written ) { global( vartable[i].name ); } printf( "\t" ); } if ( cfg->token == token_hex ) printf( "validate_hex " ); else if ( cfg->token == token_int ) printf( "validate_int " ); printf( "%s \"$%s\" %s}\n", vartable[cfg->nameindex].name, vartable[cfg->nameindex].name, cfg->value ); break; case token_unset: printf( "set %s 4}\n", vartable[cfg->nameindex].name ); break; } } }
/* * Generates the end of a menu procedure. */ static void end_proc( struct kconfig * scfg, int menu_num ) { struct kconfig * cfg; printf( "\n\n\n" ); printf( "\tfocus $w\n" ); printf( "\tupdate_active\n" ); printf( "\tglobal winx; global winy\n" ); if ( menu_first[menu_num]->menu_number != 0 ) { printf( "\tif {[winfo exists .menu%d] == 0} then ", menu_first[menu_num]->menu_number ); printf( "{menu%d .menu%d \"%s\"}\n", menu_first[menu_num]->menu_number, menu_first[menu_num]->menu_number, menu_first[menu_first[menu_num]->menu_number]->label ); printf( "\tset winx [expr [winfo x .menu%d]+30]; set winy [expr [winfo y .menu%d]+30]\n", menu_first[menu_num]->menu_number, menu_first[menu_num]->menu_number ); } else printf( "\tset winx [expr [winfo x .]+30]; set winy [expr [winfo y .]+30]\n" ); printf( "\tif {[winfo exists $w]} then {wm geometry $w +$winx+$winy}\n" ); /* * Now that the whole window is in place, we need to wait for an "update" * so we can tell the canvas what its virtual size should be. * * Unfortunately, this causes some ugly screen-flashing because the whole * window is drawn, and then it is immediately resized. It seems * unavoidable, though, since "frame" objects won't tell us their size * until after an update, and "canvas" objects can't automatically pack * around frames. Sigh. */ printf( "\tupdate idletasks\n" ); printf( "\tif {[winfo exists $w]} then {$w.config.canvas create window 0 0 -anchor nw -window $w.config.f\n\n" ); printf( "\t$w.config.canvas configure \\\n" ); printf( "\t\t-width [expr [winfo reqwidth $w.config.f] + 1]\\\n" ); printf( "\t\t-scrollregion \"-1 -1 [expr [winfo reqwidth $w.config.f] + 1] \\\n" ); printf( "\t\t\t [expr [winfo reqheight $w.config.f] + 1]\"\n\n" ); /* * If the whole canvas will fit in 3/4 of the screen height, do it; * otherwise, resize to around 1/2 the screen and let us scroll. */ printf( "\tset winy [expr [winfo reqh $w] - [winfo reqh $w.config.canvas]]\n" ); printf( "\tset scry [expr [winfo screenh $w] / 2]\n" ); printf( "\tset maxy [expr [winfo screenh $w] * 3 / 4]\n" ); printf( "\tset canvtotal [expr [winfo reqh $w.config.f] + 2]\n" ); printf( "\tif [expr $winy + $canvtotal < $maxy] {\n" ); printf( "\t\t$w.config.canvas configure -height $canvtotal\n" ); printf( "\t} else {\n" ); printf( "\t\t$w.config.canvas configure -height [expr $scry - $winy]\n" ); printf( "\t\t}\n\t}\n" ); /* * Limit the min/max window size. Height can vary, but not width, * because of the limitations of canvas and our laziness. */ printf( "\tupdate idletasks\n" ); printf( "\tif {[winfo exists $w]} then {\n\twm maxsize $w [winfo width $w] [winfo screenheight $w]\n" ); printf( "\twm minsize $w [winfo width $w] 100\n\n" ); printf( "\twm deiconify $w\n" ); printf( "}\n}\n\n" ); /* * Now we generate the companion procedure for the menu we just * generated. This procedure contains all of the code to * disable/enable widgets based upon the settings of the other * widgets, and will be called first when the window is mapped, * and each time one of the buttons in the window are clicked. */ printf( "proc update_menu%d {} {\n", menu_num ); /* * Clear all of the booleans that are defined in this menu. */ clear_globalflags(); for ( cfg = scfg; cfg != NULL; cfg = cfg->next ) { if ( cfg->menu_number == menu_num && cfg->token != token_mainmenu_option && cfg->token != token_choice_item ) { if ( cfg->cond != NULL ) { int i; if ( (cfg->token == token_tristate || cfg->token == token_dep_tristate) && ! vartable[i = get_varnum( "CONFIG_MODULES" )].global_written ) { global( "CONFIG_MODULES" ); vartable[i].global_written = 1; } generate_if( cfg, cfg->cond, cfg->menu_number, cfg->menu_line ); } else { if ( cfg->token == token_tristate ) { int i; if ( ! vartable[cfg->nameindex].global_written ) { vartable[cfg->nameindex].global_written = 1; printf( "\tglobal %s\n", vartable[cfg->nameindex].name ); } if ( ! vartable[i = get_varnum( "CONFIG_MODULES" )].global_written ) { global( "CONFIG_MODULES" ); vartable[i].global_written = 1; } printf( "\n\tif {($CONFIG_MODULES == 1)} then {configure_entry .menu%d.config.f.x%d normal {m}} else {configure_entry .menu%d.config.f.x%d disabled {m}}\n", menu_num, cfg->menu_line, menu_num, cfg->menu_line ); } } } else if ( cfg->token == token_mainmenu_option && cfg->menu_number == menu_num && cfg->cond != NULL ) { generate_if( cfg, cfg->cond, menu_num, cfg->menu_line ); } } printf("}\n\n\n"); generate_update_var( scfg, menu_num ); }