root/scripts/tkgen.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. start_proc
  2. clear_globalflags
  3. generate_if
  4. generate_if_for_outfile
  5. end_proc
  6. find_menu_size
  7. dump_tk_script

   1 /* Generate tk script based upon config.in
   2  *
   3  * Version 1.0
   4  * Eric Youngdale
   5  * 10/95
   6  */
   7 #include <stdio.h>
   8 #include "tkparse.h"
   9 
  10 #ifndef TRUE
  11 #define TRUE (1)
  12 #endif
  13 
  14 #ifndef FALSE
  15 #define FALSE (0)
  16 #endif
  17 
  18 /*
  19  * This prevents the Prev/Next buttons from going through the entire sequence
  20  * of submenus.  I need to fix the window titles before it would really be
  21  * appropriate to enable this.
  22  */
  23 #define PREVLAST_LIMITED_RANGE
  24 
  25 /*
  26  * This is the total number of submenus that we have.
  27  */
  28 static int tot_menu_num =0;
  29 
  30 /*
  31  * Generate portion of wish script for the beginning of a submenu.
  32  * The guts get filled in with the various options.
  33  */
  34 static start_proc(char * label, int menu_num, int flag)
     /* [previous][next][first][last][top][bottom][index][help] */
  35 {
  36   if( flag )
  37     printf("menu_option menu%d %d \"%s\"\n", menu_num, menu_num, label);
  38   printf("proc menu%d {w title} {\n", menu_num);
  39   printf("\tcatch {destroy $w}\n");
  40   printf("\ttoplevel $w -class Dialog\n");
  41   printf("\tmessage $w.m -width 400 -aspect 300 -background grey -text \\\n");
  42   printf("\t\t\"%s\"  -relief raised -bg grey\n",label);
  43   printf("\tpack $w.m -pady 10 -side top -padx 10\n");
  44   printf("\twm title $w \"%s\" \n\n\n", label);
  45 }
  46 
  47 /*
  48  * Each proc we create needs a global declaration for any global variables we
  49  * use.  To minimize the size of the file, we set a flag each time we output
  50  * a global declaration so we know whether we need to insert one for a
  51  * given function or not.
  52  */
  53 clear_globalflags(struct kconfig * cfg)
     /* [previous][next][first][last][top][bottom][index][help] */
  54 {
  55   for(; cfg != NULL; cfg = cfg->next)
  56   {
  57     cfg->flags &= ~GLOBAL_WRITTEN;
  58   }
  59 }
  60 
  61 /*
  62  * This function walks the chain of conditions that we got from cond.c,
  63  * and creates a wish conditional to enable/disable a given widget.
  64  */
  65 generate_if(struct kconfig * item,
     /* [previous][next][first][last][top][bottom][index][help] */
  66             struct condition * cond,
  67             int menu_num,
  68             int line_num)
  69 {
  70   int i;
  71   struct condition * ocond;
  72 
  73   ocond = cond;
  74 
  75   /*
  76    * First write any global declarations we need for this conditional.
  77    */
  78   while(cond != NULL )
  79     {
  80       switch(cond->op){
  81       case op_variable:
  82         printf("\tglobal %s\n", cond->variable.str);
  83         break;
  84       case op_kvariable:
  85         if(cond->variable.cfg->flags & GLOBAL_WRITTEN) break;
  86         cond->variable.cfg->flags |= GLOBAL_WRITTEN;
  87         printf("\tglobal %s\n", cond->variable.cfg->optionname);
  88         break;
  89       default:
  90         break;
  91       }
  92       cond = cond->next;
  93     }
  94   
  95   /*
  96    * Now write this option.
  97    */
  98   if(   (item->flags & GLOBAL_WRITTEN) == 0
  99      && (item->optionname != NULL) )
 100     {
 101       printf("\tglobal %s\n", item->optionname);
 102       item->flags |= GLOBAL_WRITTEN;
 103     }
 104   /*
 105    * Now generate the body of the conditional.
 106    */
 107   printf("\tif {");
 108   cond = ocond;
 109   while(cond != NULL )
 110     {
 111       switch(cond->op){
 112       case op_bang:
 113         printf(" ! ");
 114         break;
 115       case op_eq:
 116         printf(" == ");
 117         break;
 118       case op_neq:
 119         printf(" != ");
 120         break;
 121       case op_and:
 122       case op_and1:
 123         printf(" && ");
 124         break;
 125       case op_or:
 126         printf(" || ");
 127         break;
 128       case op_lparen:
 129         printf("(");
 130         break;
 131       case op_rparen:
 132         printf(")");
 133         break;
 134       case op_variable:
 135         printf("$%s", cond->variable.str);
 136         break;
 137       case op_kvariable:
 138         printf("$%s", cond->variable.cfg->optionname);
 139         break;
 140       case op_shellcmd:
 141         printf("[exec %s]", cond->variable.str);
 142         break;
 143       case op_constant:
 144         if( strcmp(cond->variable.str, "y") == 0 )
 145           printf("1");
 146         else if( strcmp(cond->variable.str, "n") == 0 )
 147           printf("0");
 148         else if( strcmp(cond->variable.str, "m") == 0 )
 149           printf("2");
 150         else
 151           printf("\"%s\"", cond->variable);
 152         break;
 153       }
 154       cond = cond->next;
 155     }
 156 
 157   /*
 158    * Now we generate what we do depending upon the value of the conditional.
 159    * Depending upon what the token type is, there are different things
 160    * we must do to enable/disable the given widget - this code needs to
 161    * be closely coordinated with the widget creation procedures in header.tk.
 162    */
 163   switch(item->tok)
 164     {
 165     case tok_define:
 166       printf("} then { set %s %s } \n",  item->optionname, item->value);
 167       break;
 168     case tok_menuoption:
 169       printf("} then { .f0.x%d configure -state normal } else { .f0.x%d configure -state disabled }\n",
 170              menu_num, menu_num);
 171       break;
 172     case tok_int:
 173       printf("} then { ");
 174       printf(".menu%d.x%d.x configure -state normal; ", menu_num, line_num);
 175       printf(".menu%d.x%d.l configure -state normal; ", menu_num, line_num);
 176       printf("} else { ");
 177       printf(".menu%d.x%d.x configure -state disabled;", menu_num, line_num );
 178       printf(".menu%d.x%d.l configure -state disabled;", menu_num, line_num );
 179       printf("}\n");
 180       break;
 181     case tok_bool:
 182 #ifdef BOOL_IS_BUTTON
 183       /*
 184        * If a bool is just a button, then use this definition.
 185        */
 186       printf("} then { .menu%d.x%d configure -state normal } else { .menu%d.x%d configure -state disabled }\n",
 187              menu_num, line_num,
 188              menu_num, line_num );
 189 #else
 190       /*
 191        * If a bool is a radiobutton, then use this instead.
 192        */
 193       printf("} then { ");
 194       printf(".menu%d.x%d.y configure -state normal;",menu_num, line_num);
 195       printf(".menu%d.x%d.n configure -state normal;",menu_num, line_num);
 196       printf(".menu%d.x%d.l configure -state normal;",menu_num, line_num);
 197       printf("set %s [expr $%s&15];", item->optionname, item->optionname);
 198       printf("} else { ");
 199       printf(".menu%d.x%d.y configure -state disabled;",menu_num, line_num);
 200       printf(".menu%d.x%d.n configure -state disabled;",menu_num, line_num);
 201       printf(".menu%d.x%d.l configure -state disabled;",menu_num, line_num);
 202       printf("set %s [expr $%s|16];", item->optionname, item->optionname);
 203       printf("}\n");
 204 #endif
 205       break;
 206     case tok_tristate:
 207     case tok_dep_tristate:
 208       printf("} then { ");
 209       if( item->tok == tok_dep_tristate )
 210         {
 211           printf("if { $%s == 2 } then {", item->depend.str);
 212           printf(".menu%d.x%d.y configure -state disabled;",menu_num, line_num);
 213           printf("} else {");
 214           printf(".menu%d.x%d.y configure -state normal;",menu_num, line_num);
 215           printf("}; ");
 216         }
 217       else
 218         {
 219           printf(".menu%d.x%d.y configure -state normal;",menu_num, line_num);
 220         }
 221       
 222       printf(".menu%d.x%d.n configure -state normal;",menu_num, line_num);
 223       printf(".menu%d.x%d.m configure -state normal;",menu_num, line_num);
 224       printf(".menu%d.x%d.l configure -state normal;",menu_num, line_num);
 225       /*
 226        * Or in a bit to the variable - this causes all of the radiobuttons
 227        * to be deselected (i.e. not be red).
 228        */
 229       printf("set %s [expr $%s&15];", item->optionname, item->optionname);
 230       printf("} else { ");
 231       printf(".menu%d.x%d.y configure -state disabled;",menu_num, line_num);
 232       printf(".menu%d.x%d.n configure -state disabled;",menu_num, line_num);
 233       printf(".menu%d.x%d.m configure -state disabled;",menu_num, line_num);
 234       printf(".menu%d.x%d.l configure -state disabled;",menu_num, line_num);
 235       /*
 236        * Clear the disable bit - this causes the correct radiobutton
 237        * to appear selected (i.e. turn red).
 238        */
 239       printf("set %s [expr $%s|16];", item->optionname, item->optionname);
 240       printf("}\n");
 241       break;
 242     case tok_choose:
 243     case tok_choice:
 244       fprintf(stderr,"Fixme\n");
 245       exit(0);
 246     default:
 247       break;
 248     }
 249 }
 250 
 251 /*
 252  * Similar to generate_if, except we come here when generating an
 253  * output file.  Thus instead of enabling/disabling a widget, we
 254  * need to decide whether to write out a given configuration variable
 255  * to the output file.
 256  */
 257 generate_if_for_outfile(struct kconfig * item,
     /* [previous][next][first][last][top][bottom][index][help] */
 258             struct condition * cond)
 259 {
 260   struct condition * ocond;
 261 
 262   /*
 263    * First write any global declarations we need for this conditional.
 264    */
 265   ocond = cond;
 266   for(; cond != NULL; cond = cond->next )
 267     {
 268       switch(cond->op){
 269       case op_variable:
 270         printf("\tglobal %s\n", cond->variable.str);
 271         break;
 272       case op_kvariable:
 273         if(cond->variable.cfg->flags & GLOBAL_WRITTEN) break;
 274         cond->variable.cfg->flags |= GLOBAL_WRITTEN;
 275         printf("\tglobal %s\n", cond->variable.cfg->optionname);
 276         break;
 277       default:
 278         break;
 279       }
 280     }
 281 
 282   /*
 283    * Now generate the body of the conditional.
 284    */
 285   printf("\tif {");
 286   cond = ocond;
 287   while(cond != NULL )
 288     {
 289       switch(cond->op){
 290       case op_bang:
 291         printf(" ! ");
 292         break;
 293       case op_eq:
 294         printf(" == ");
 295         break;
 296       case op_neq:
 297         printf(" != ");
 298         break;
 299       case op_and:
 300       case op_and1:
 301         printf(" && ");
 302         break;
 303       case op_or:
 304         printf(" || ");
 305         break;
 306       case op_lparen:
 307         printf("(");
 308         break;
 309       case op_rparen:
 310         printf(")");
 311         break;
 312       case op_variable:
 313         printf("$%s", cond->variable.str);
 314         break;
 315       case op_shellcmd:
 316         printf("[exec %s]", cond->variable.str);
 317         break;
 318       case op_kvariable:
 319         printf("$%s", cond->variable.cfg->optionname);
 320         break;
 321       case op_constant:
 322         if( strcmp(cond->variable.str, "y") == 0 )
 323           printf("1");
 324         else if( strcmp(cond->variable.str, "n") == 0 )
 325           printf("0");
 326         else if( strcmp(cond->variable.str, "m") == 0 )
 327           printf("2");
 328         else
 329           printf("\"%s\"", cond->variable);
 330         break;
 331       }
 332       cond = cond->next;
 333     }
 334 
 335   /*
 336    * Now we generate what we do depending upon the value of the
 337    * conditional.  Depending upon what the token type is, there are
 338    * different things we must do write the value the given widget -
 339    * this code needs to be closely coordinated with the widget
 340    * creation procedures in header.tk.  
 341    */
 342   switch(item->tok)
 343     {
 344     case tok_define:
 345       printf("} then {write_variable $cfg $autocfg %s %s $notmod }\n", item->optionname, item->value);
 346       break;
 347     case tok_comment:
 348       printf("} then {write_comment $cfg $autocfg \"%s\"}\n", item->label);
 349       break;
 350     case tok_dep_tristate:
 351       printf("} then { write_variable $cfg $autocfg %s $%s $%s } \n", 
 352              item->optionname, item->optionname, item->depend.str);
 353       break;
 354     case tok_tristate:
 355     case tok_bool:
 356     case tok_int:
 357       printf("} then { write_variable $cfg $autocfg %s $%s $notmod }\n", 
 358              item->optionname, item->optionname);
 359       break;
 360     case tok_choose:
 361     case tok_choice:
 362       fprintf(stderr,"Fixme\n");
 363       exit(0);
 364     default:
 365       break;
 366     }
 367 }
 368 
 369 /*
 370  * Generates a fragment of wish script that closes out a submenu procedure.
 371  */
 372 static end_proc(int menu_num, int first, int last)
     /* [previous][next][first][last][top][bottom][index][help] */
 373 {
 374   struct kconfig * cfg;
 375 
 376   printf("\n\n\n");
 377   printf("\tset oldFocus [focus]\n");
 378   printf("\tframe $w.f\n");
 379 
 380   /*
 381    * Attach the "Prev", "Next" and "OK" buttons at the end of the window.
 382    */
 383   printf("\tbutton $w.f.prev -text \"Prev\" -activebackground green \\\n");
 384       printf("\t\t-width 15 -command \" destroy $w; focus $oldFocus; menu%d .menu%d \\\"$title\\\"\"\n", menu_num-1, menu_num-1);
 385 #ifdef PREVLAST_LIMITED_RANGE
 386   if(first == menu_num ) printf("\t$w.f.prev configure -state disabled\n");
 387 #else
 388   if( 1 == menu_num ) printf("\t$w.f.prev configure -state disabled\n");
 389 #endif
 390 
 391   printf("\tbutton $w.f.next -text \"Next\" -activebackground green \\\n");
 392   printf("\t\t-width 15 -command \" destroy $w; focus $oldFocus;  menu%d .menu%d \\\"$title\\\"\"\n", menu_num+1, menu_num+1);
 393 #ifdef PREVLAST_LIMITED_RANGE
 394   if(last == menu_num ) printf("\t$w.f.next configure -state disabled\n");
 395 #else
 396   if(last == tot_menu_num ) printf("\t$w.f.next configure -state disabled\n");
 397 #endif
 398 
 399   printf("\tbutton $w.f.back -text \"Main Menu\" -activebackground green \\\n");
 400   printf("\t\t-width 15 -command \"destroy $w; focus $oldFocus; update_mainmenu $w\"\n");
 401 
 402   printf("\tpack $w.f.back $w.f.next $w.f.prev -side left -pady 10 -padx 45\n");
 403   printf("\tpack $w.f -pady 10 -side top -padx 10 -anchor w\n");
 404   printf("\tfocus $w\n");
 405   printf("\tupdate_menu%d $w\n", menu_num);
 406   printf("\tglobal winx; global winy\n");
 407   printf("\tset winx [expr [winfo x .]+30]; set winy [expr [winfo y .]+30]\n");
 408   printf("\twm geometry $w +$winx+$winy\n");
 409   printf("}\n\n\n");
 410 
 411   /*
 412    * Now we generate the companion procedure for the menu we just
 413    * generated.  This procedure contains all of the code to
 414    * disable/enable widgets based upon the settings of the other
 415    * widgets, and will be called first when the window is mapped,
 416    * and each time one of the buttons in the window are clicked.
 417    */
 418   printf("proc update_menu%d {w}  {\n", menu_num);
 419 
 420   printf("\tupdate_define\n");
 421   clear_globalflags(config);
 422   for(cfg = config;cfg != NULL; cfg = cfg->next)
 423     {
 424       /*
 425        * Skip items not for this menu, or ones having no conditions.
 426        */
 427       if (cfg->menu_number != menu_num ) continue;
 428       if (cfg->tok != tok_define) continue;
 429       /*
 430        * Clear all of the booleans that are defined in this menu.
 431        */
 432       if(   (cfg->flags & GLOBAL_WRITTEN) == 0
 433          && (cfg->optionname != NULL) )
 434         {
 435           printf("\tglobal %s\n", cfg->optionname);
 436           cfg->flags |= GLOBAL_WRITTEN;
 437           printf("\tset %s 0\n", cfg->optionname);
 438         }
 439 
 440     }
 441   for(cfg = config;cfg != NULL; cfg = cfg->next)
 442     {
 443       /*
 444        * Skip items not for this menu, or ones having no conditions.
 445        */
 446       if (cfg->menu_number != menu_num ) continue;
 447       if (cfg->tok == tok_menuoption) continue;
 448       if (cfg->cond != NULL ) 
 449         generate_if(cfg, cfg->cond, menu_num, cfg->menu_line);
 450       else
 451         {
 452           /*
 453            * If this token has no conditionals, check to see whether
 454            * it is a tristate - if so, then generate the conditional
 455            * to enable/disable the "y" button based upon the setting
 456            * of the option it depends upon.
 457            */
 458           if(cfg->tok == tok_dep_tristate)
 459             {
 460               printf("\tif {$%s == 2 } then { .menu3.x5.y configure -state normal} else { .menu3.x5.y configure -state disabled}\n",cfg->depend.str,
 461                      menu_num, cfg->menu_line,
 462                      menu_num, cfg->menu_line);
 463               
 464             }
 465         }
 466 
 467     }
 468 
 469 
 470   printf("}\n\n\n");
 471 }
 472 
 473 /*
 474  * This function goes through and counts up the number of items in
 475  * each submenu. If there are too many options, we need to split it
 476  * into submenus.  This function just calculates how many submenus,
 477  * and how many items go in each submenu.
 478  */
 479 static int find_menu_size(struct kconfig *cfg,
     /* [previous][next][first][last][top][bottom][index][help] */
 480                           int *menu_max, 
 481                           int *menu_maxlines)
 482 
 483 {
 484   struct kconfig * pnt;
 485   int tot;
 486   int div;
 487   
 488   /*
 489    * First count up the number of options in this menu.
 490    */
 491   tot = 0;
 492   for(pnt = cfg->next; pnt; pnt = pnt->next)
 493   {
 494     if( pnt->tok == tok_menuoption) break;
 495     switch (pnt->tok)
 496       {
 497       case tok_bool:
 498       case tok_tristate:
 499       case tok_dep_tristate:
 500       case tok_int:
 501       case tok_choose:
 502       case tok_choice:
 503       case tok_sound:
 504         tot++;
 505         break;
 506       default:
 507         break;
 508       }
 509   }
 510 
 511   /*
 512    * Now figure out how many items go on each page.
 513    */
 514   div = 1;
 515   while(tot / div > 15) div++;
 516   *menu_max = cfg->menu_number + div - 1;
 517   *menu_maxlines = (tot + div -1) / div;
 518 }
 519 
 520 /*
 521  * This is the top level function for generating the tk script.
 522  */
 523 dump_tk_script(struct kconfig *scfg)
     /* [previous][next][first][last][top][bottom][index][help] */
 524 {
 525   int i;
 526   int menu_num =0;
 527   int menu_max =0;
 528   int menu_min =0;
 529   int menu_line = 0;
 530   int menu_maxlines = 0;
 531   struct kconfig * cfg;
 532   struct kconfig * cfg1 = NULL;
 533   char * menulabel;
 534 
 535   /*
 536    * Start by assigning menu numbers, and submenu numbers.
 537    */
 538   for(cfg = scfg;cfg != NULL; cfg = cfg->next)
 539     {
 540       switch (cfg->tok)
 541         {
 542         case tok_menuname:
 543           break;
 544         case tok_menuoption:
 545           /*
 546            * At the start of a new menu, calculate the number of items
 547            * we will put into each submenu so we know when to bump the
 548            * menu number. The submenus are really no different from a
 549            * normal menu, but the top level buttons only access the first
 550            * of the chain of menus, and the prev/next buttons are used
 551            * access the submenus.
 552            */
 553           cfg->menu_number = ++menu_num;
 554           find_menu_size(cfg, &menu_max, &menu_maxlines);
 555           cfg->submenu_start = menu_num;
 556           cfg->submenu_end = menu_max;
 557           menu_line = 0;
 558           break;
 559         case tok_bool:
 560         case tok_tristate:
 561         case tok_dep_tristate:
 562         case tok_int:
 563         case tok_choose:
 564         case tok_choice:
 565         case tok_sound:
 566           /*
 567            * If we have overfilled the menu, then go to the next one.
 568            */
 569           if( menu_line == menu_maxlines )
 570             {
 571               menu_line = 0;
 572               menu_num++;
 573             }
 574           cfg->menu_number = menu_num;
 575           cfg->submenu_start = menu_min;
 576           cfg->submenu_end = menu_max;
 577           cfg->menu_line = menu_line++;
 578           break;
 579         case tok_define:
 580           cfg->menu_number = -1;
 581         default:
 582           break;
 583         };
 584     }
 585 
 586   /*
 587    * Record this so we can set up the prev/next buttons correctly.
 588    */
 589   tot_menu_num = menu_num;
 590 
 591   /*
 592    * Now start generating the actual wish script that we will use.
 593    * We need to keep track of the menu numbers of the min/max menu
 594    * for a range of submenus so that we can correctly limit the
 595    * prev and next buttons so that they don't go over into some other
 596    * category.
 597    */
 598   for(cfg = scfg; cfg != NULL; cfg = cfg->next)
 599     {
 600       switch (cfg->tok)
 601         {
 602         case tok_menuname:
 603           printf("mainmenu_name \"%s\"\n", cfg->label);
 604           break;
 605         case tok_menuoption:
 606           /*
 607            * We are at the start of a new menu. If we had one that
 608            * we were working on before, close it out, and then generate
 609            * the script to start the new one.
 610            */
 611           if( cfg->menu_number > 1 )
 612             {
 613               end_proc(menu_num, menu_min, menu_max);
 614             }
 615           menulabel = cfg->label;
 616           start_proc(cfg->label, cfg->menu_number, TRUE);
 617           menu_num = cfg->menu_number;
 618           menu_max = cfg->submenu_end;
 619           menu_min = cfg->submenu_start;
 620           break;
 621         case tok_bool:
 622           /*
 623            * If we reached the point where we need to switch over
 624            * to the next submenu, then bump the menu number and generate
 625            * the code to close out the old menu and start the new one.
 626            */
 627           if( cfg->menu_number != menu_num )
 628             {
 629               end_proc(menu_num, menu_min, menu_max);
 630               start_proc(menulabel, cfg->menu_number, FALSE);
 631               menu_num = cfg->menu_number;
 632             }
 633           printf("\tbool $w %d %d \"%s\" %s\n",
 634                  cfg->menu_number,
 635                  cfg->menu_line,
 636                  cfg->label,
 637                  cfg->optionname);
 638           break;
 639 
 640         case tok_choice:
 641           printf("\t$w.line%d.menu add radiobutton -label \"%s\" -variable %s -value %d -command \"update_menu%d .menu%d\"\n",
 642                  cfg1->menu_line,
 643                  cfg->label,
 644                  cfg1->optionname,
 645                  cfg->choice_value,
 646                  cfg->menu_number, cfg->menu_number);
 647           break;
 648         case tok_choose:
 649           if( cfg->menu_number != menu_num )
 650             {
 651               end_proc(menu_num, menu_min, menu_max);
 652               start_proc(menulabel, cfg->menu_number, FALSE);
 653               menu_num = cfg->menu_number;
 654             }
 655           printf("\tmenubutton $w.line%d -text \"%s\" -menu $w.line%d.menu \\\n",
 656                  cfg->menu_line, cfg->label, cfg->menu_line);
 657           printf("\t    -relief raised -width 35\n");
 658           printf("\tpack $w.line%d -anchor w\n", cfg->menu_line);
 659           printf("\tmenu $w.line%d.menu\n", cfg->menu_line);
 660           cfg1 = cfg;
 661           break;
 662         case tok_tristate:
 663           if( cfg->menu_number != menu_num )
 664             {
 665               end_proc(menu_num, menu_min, menu_max);
 666               start_proc(menulabel, cfg->menu_number, FALSE);
 667               menu_num = cfg->menu_number;
 668             }
 669           printf("\ttristate $w %d %d \"%s\" %s\n",
 670                  cfg->menu_number,
 671                  cfg->menu_line,
 672                  cfg->label,
 673                  cfg->optionname);
 674           break;
 675         case tok_dep_tristate:
 676           if( cfg->menu_number != menu_num )
 677             {
 678               end_proc(menu_num, menu_min, menu_max);
 679               start_proc(menulabel, cfg->menu_number, FALSE);
 680               menu_num = cfg->menu_number;
 681             }
 682           printf("\tdep_tristate $w %d %d \"%s\" %s\n",
 683                  cfg->menu_number,
 684                  cfg->menu_line,
 685                  cfg->label,
 686                  cfg->optionname,
 687                  cfg->depend);
 688           break;
 689         case tok_int:
 690           if( cfg->menu_number != menu_num )
 691             {
 692               end_proc(menu_num, menu_min, menu_max);
 693               start_proc(menulabel, cfg->menu_number, FALSE);
 694               menu_num = cfg->menu_number;
 695             }
 696           printf("\tint $w %d %d \"%s\" %s\n",
 697                  cfg->menu_number,
 698                  cfg->menu_line,
 699                  cfg->label,
 700                  cfg->optionname);
 701           break;
 702         case tok_sound:
 703           if( cfg->menu_number != menu_num )
 704             {
 705               end_proc(menu_num, menu_min, menu_max);
 706               start_proc(menulabel, cfg->menu_number, FALSE);
 707               menu_num = cfg->menu_number;
 708             }
 709           printf("\tdo_sound $w %d %d\n",
 710                  cfg->menu_number,
 711                  cfg->menu_line);
 712           break;
 713         default:
 714           break;
 715         }
 716 
 717     }
 718 
 719   /*
 720    * Generate the code to close out the last menu.
 721    */
 722   end_proc(menu_num, menu_min, menu_max);
 723 
 724 #ifdef ERIC_DONT_DEF
 725   /*
 726    * Generate the code for configuring the sound driver.  Right now this
 727    * cannot be done from the X script, but we insert the menu anyways.
 728    */
 729   start_proc("Configure sound driver", ++menu_num, TRUE);
 730 #if 0
 731   printf("\tdo_make -C drivers/sound config\n");
 732   printf("\techo check_sound_config %d\n",menu_num);
 733 #endif
 734   printf("\tlabel $w.m0 -bitmap error\n");
 735   printf("\tmessage $w.m1 -width 400 -aspect 300 -text \"The sound drivers cannot as of yet be configured via the X-based interface\" -relief raised\n");
 736   printf("\tpack $w.m0 $w.m1 -side top -pady 10\n");
 737   /*
 738    * Close out the last menu.
 739    */
 740   end_proc(menu_num, menu_num, menu_num);
 741 #endif
 742 
 743   /*
 744    * The top level menu also needs an update function.  When we exit a
 745    * submenu, we may need to disable one or more of the submenus on
 746    * the top level menu, and this procedure will ensure that things are
 747    * correct.
 748    */
 749   printf("proc update_mainmenu {w}  {\n");
 750   for(cfg = scfg; cfg != NULL; cfg = cfg->next)
 751     {
 752       switch (cfg->tok)
 753         {
 754         case tok_menuoption:
 755           if (cfg->cond != NULL ) 
 756             generate_if(cfg, cfg->cond, cfg->menu_number, cfg->menu_line);
 757           break;
 758         default:
 759           break;
 760         }
 761     }
 762 
 763   printf("}\n\n\n");
 764 
 765 #if 0
 766   /*
 767    * Generate some code to set the variables that are "defined".
 768    */
 769   for(cfg = config;cfg != NULL; cfg = cfg->next)
 770     {
 771       /*
 772        * Skip items not for this menu, or ones having no conditions.
 773        */
 774       if( cfg->tok != tok_define) continue;
 775       if (cfg->cond != NULL ) 
 776         generate_if(cfg, cfg->cond, menu_num, cfg->menu_line);
 777       else
 778         {
 779           printf("\twrite_define %s %s\n", cfg->optionname, cfg->value);
 780         }
 781 
 782     }
 783 #endif
 784 
 785   /*
 786    * Now generate code to load the default settings into the variables.
 787    * Note that the script in tail.tk will attempt to load .config,
 788    * which may override these settings, but that's OK.
 789    */
 790   for(cfg = scfg; cfg != NULL; cfg = cfg->next)
 791     {
 792       switch (cfg->tok)
 793         {
 794         case tok_int:
 795         case tok_bool:
 796         case tok_tristate:
 797         case tok_dep_tristate:
 798         case tok_choice:
 799           printf("set %s 0\n", cfg->optionname);
 800           break;
 801         case tok_choose:
 802           printf("set %s %d\n", cfg->optionname, cfg->choice_value);
 803         default:
 804           break;
 805         }
 806     }
 807 
 808   /*
 809    * Next generate a function that can be called from the main menu that will
 810    * write all of the variables out.  This also serves double duty - we can
 811    * save configuration to a file using this.
 812    */
 813   printf("proc writeconfig {file1 file2} {\n");
 814   printf("\tset cfg [open $file1 w]\n");
 815   printf("\tset autocfg [open $file2 w]\n");
 816   printf("\tset notmod 1\n");
 817   printf("\tset notset 0\n");
 818   clear_globalflags(config);
 819   printf("\tputs $cfg \"#\"\n");
 820   printf("\tputs $cfg \"# Automatically generated make config: don't edit\"\n");
 821   printf("\tputs $cfg \"#\"\n");
 822 
 823   printf("\tputs $autocfg \"/*\"\n");
 824   printf("\tputs $autocfg \" * Automatically generated C config: don't edit\"\n");
 825   printf("\tputs $autocfg \" */\"\n");
 826   for(cfg = scfg; cfg != NULL; cfg = cfg->next)
 827     {
 828       switch (cfg->tok)
 829         {
 830         case tok_int:
 831         case tok_bool:
 832         case tok_tristate:
 833         case tok_dep_tristate:
 834         case tok_define:
 835         case tok_choose:
 836           if(cfg->flags & GLOBAL_WRITTEN) break;
 837           cfg->flags |= GLOBAL_WRITTEN;
 838           printf("\tglobal %s\n", cfg->optionname);
 839 
 840         case tok_comment:
 841           if (cfg->cond != NULL ) 
 842             generate_if_for_outfile(cfg, cfg->cond);
 843           else
 844             {
 845               if(cfg->tok == tok_dep_tristate)
 846                 {
 847                   printf("\tif {$%s == 2 } then { write_variable $cfg $autocfg %s $%s %s } else { write_variable $cfg $autocfg %s $notset $notmod }\n",
 848                          cfg->optionname,
 849                          cfg->optionname,
 850                          cfg->depend.str,
 851                          cfg->optionname);
 852                 }
 853               else if(cfg->tok == tok_comment)
 854                 {
 855                   printf("\twrite_comment $cfg $autocfg \"%s\"\n", cfg->label);
 856                 }
 857 #if 0
 858               else if(cfg->tok == tok_define)
 859                 {
 860                   printf("\twrite_define %s %s\n", cfg->optionname,
 861                          cfg->value);
 862                 }
 863 #endif
 864               else if (cfg->tok == tok_choose )
 865                 {
 866                   for(cfg1 = cfg->next; 
 867                       cfg1 != NULL && cfg1->tok == tok_choice;
 868                       cfg1 = cfg1->next)
 869                     {
 870                       printf("\tif { $%s == %d } then { write_variable $cfg $autocfg %s 1 $notmod }\n",
 871                              cfg->optionname,
 872                              cfg1->choice_value,
 873                              cfg1->optionname);
 874                     }
 875                 }
 876               else
 877                 {
 878                   printf("\twrite_variable $cfg $autocfg %s $%s $notmod\n",
 879                          cfg->optionname,
 880                          cfg->optionname);
 881                          
 882                 }
 883             }
 884           break;
 885         default:
 886           break;
 887         }
 888     }
 889   printf("\tclose $cfg\n");
 890   printf("\tclose $autocfg\n");
 891   printf("}\n\n\n");
 892 
 893   /*
 894    * Finally write a simple function that updates the master choice
 895    * variable depending upon what values were loaded from a .config
 896    * file.  
 897    */
 898   printf("proc clear_choices { } {\n");
 899   for(cfg = scfg; cfg != NULL; cfg = cfg->next)
 900     {
 901       if( cfg->tok != tok_choose ) continue;
 902       for(cfg1 = cfg->next; 
 903           cfg1 != NULL && cfg1->tok == tok_choice;
 904           cfg1 = cfg1->next)
 905         {
 906           printf("\tglobal %s; set %s 0\n",  cfg1->optionname, cfg1->optionname);
 907         }
 908     }
 909   printf("}\n\n\n");
 910 
 911   printf("proc update_choices { } {\n");
 912   for(cfg = scfg; cfg != NULL; cfg = cfg->next)
 913     {
 914       if( cfg->tok != tok_choose ) continue;
 915       printf("\tglobal %s\n", cfg->optionname);
 916       for(cfg1 = cfg->next; 
 917           cfg1 != NULL && cfg1->tok == tok_choice;
 918           cfg1 = cfg1->next)
 919         {
 920           printf("\tglobal %s\n", cfg1->optionname);
 921           printf("\tif { $%s == 1 } then { set %s %d }\n",
 922                  cfg1->optionname,
 923                  cfg->optionname,
 924                  cfg1->choice_value);
 925         }
 926     }
 927   printf("}\n\n\n");
 928 
 929   printf("proc update_define { } {\n");
 930   clear_globalflags(config);
 931   for(cfg = scfg; cfg != NULL; cfg = cfg->next)
 932     {
 933       if( cfg->tok != tok_define ) continue;
 934       printf("\tglobal %s; set %s 0\n",  cfg->optionname,  cfg->optionname);
 935       cfg->flags |= GLOBAL_WRITTEN;
 936     }
 937   for(cfg = scfg; cfg != NULL; cfg = cfg->next)
 938     {
 939       if( cfg->tok != tok_define ) continue;
 940       if (cfg->cond != NULL ) 
 941         generate_if(cfg, cfg->cond, -1, 0);
 942       else
 943         {
 944           printf("\tset %s %s\n",
 945                  cfg->optionname, cfg->value);
 946         }
 947     }
 948   printf("}\n\n\n");
 949   /*
 950    * That's it.  We are done.  The output of this file will have header.tk
 951    * prepended and tail.tk appended to create an executable wish script.
 952    */
 953 }

/* [previous][next][first][last][top][bottom][index][help] */