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

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