OpenCores
URL https://opencores.org/ocsvn/or1k_old/or1k_old/trunk

Subversion Repositories or1k_old

[/] [or1k_old/] [trunk/] [rc203soc/] [sw/] [uClinux/] [scripts/] [tkgen.c] - Blame information for rev 1782

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1629 jcastillo
/* Generate tk script based upon config.in
2
 *
3
 * Version 1.0
4
 * Eric Youngdale
5
 * 10/95
6
 *
7
 * 1996 01 04
8
 * Avery Pennarun - Aesthetic improvements.
9
 *
10
 * 1996 01 24
11
 * Avery Pennarun - Bugfixes and more aesthetics.
12
 *
13
 * 1996 03 08
14
 * Avery Pennarun - The int and hex config.in commands work right.
15
 *                - Choice buttons are more user-friendly.
16
 *                - Disabling a text entry line greys it out properly.
17
 *                - dep_tristate now works like in Configure. (not pretty)
18
 *                - No warnings in gcc -Wall. (Fixed some "interesting" bugs.)
19
 *                - Faster/prettier "Help" lookups.
20
 *
21
 * 1996 03 15
22
 * Avery Pennarun - Added new sed script from Axel Boldt to make help even
23
 *                  faster. (Actually awk is downright slow on some machines.)
24
 *                - Fixed a bug I introduced into Choice dependencies.  Thanks
25
 *                  to Robert Krawitz for pointing this out.
26
 *
27
 * 1996 03 16
28
 * Avery Pennarun - basic "do_make" support added to let sound config work.
29
 *
30
 * 1996 03 25
31
 *     Axel Boldt - Help now works on "choice" buttons.
32
 *
33
 * 1996 04 06
34
 * Avery Pennarun - Improved sound config stuff. (I think it actually works
35
 *                  now!)
36
 *                - Window-resize-limits don't use ugly /usr/lib/tk4.0 hack.
37
 *                - int/hex work with tk3 again. (The "cget" error.)
38
 *                - Next/Prev buttons switch between menus.  I can't take
39
 *                  much credit for this; the code was already there, but
40
 *                  ifdef'd out for some reason.  It flickers a lot, but
41
 *                  I suspect there's no "easy" fix for that.
42
 *                - Labels no longer highlight as you move the mouse over
43
 *                  them (although you can still press them... oh well.)
44
 *                - Got rid of the last of the literal color settings, to
45
 *                  help out people with mono X-Windows systems.
46
 *                  (Apparently there still are some out there!)
47
 *                - Tabstops seem sensible now.
48
 *
49
 * 1996 04 14
50
 * Avery Pennarun - Reduced flicker when creating windows, even with "update
51
 *                  idletasks" hack.
52
 *
53
 * TO DO:
54
 *   - clean up - there are useless ifdef's everywhere.
55
 *   - better comments throughout - C code generating tcl is really cryptic.
56
 *   - eliminate silly "update idletasks" hack to improve display speed and
57
 *     reduce flicker.  But how?
58
 *   - make canvas contents resize with the window (good luck).
59
 *   - some way to make submenus inside of submenus (ie. Main->Networking->IP)
60
 *           (perhaps a button where the description would be)
61
 *   - make the main menu use the same tcl code as the submenus.
62
 *   - make choice and int/hex input types line up vertically with
63
 *           bool/tristate.
64
 *   - general speedups - how?  The canvas seems to slow it down a lot.
65
 *   - choice buttons should default to the first menu option, rather than a
66
 *           blank.  Also look up the right variable when the help button
67
 *           is pressed.
68
 *   - clean up +/- 16 confusion for enabling/disabling variables; causes
69
 *           (theoretical, at the moment) problems with dependencies.
70
 *
71
 */
72
#include <stdio.h>
73
#include <unistd.h>
74
#include "tkparse.h"
75
 
76
#ifndef TRUE
77
#define TRUE (1)
78
#endif
79
 
80
#ifndef FALSE
81
#define FALSE (0)
82
#endif
83
 
84
/*
85
 * This is the total number of submenus that we have.
86
 */
87
static int tot_menu_num =0;
88
 
89
/*
90
 * Generate portion of wish script for the beginning of a submenu.
91
 * The guts get filled in with the various options.
92
 */
93
static void start_proc(char * label, int menu_num, int flag)
94
{
95
  if( flag )
96
    printf("menu_option menu%d %d \"%s\"\n", menu_num, menu_num, label);
97
  printf("proc menu%d {w title} {\n", menu_num);
98
  printf("\tcatch {destroy $w}\n");
99
  printf("\ttoplevel $w -class Dialog\n");
100
  printf("\twm withdraw $w\n");
101
  printf("\tmessage $w.m -width 400 -aspect 300 -text \\\n");
102
  printf("\t\t\"%s\"  -relief raised\n",label);
103
  printf("\tpack $w.m -pady 10 -side top -padx 10\n");
104
  printf("\twm title $w \"%s\" \n\n", label);
105
 
106
  /*
107
   * Attach the "Prev", "Next" and "OK" buttons at the end of the window.
108
   */
109
  printf("\tset oldFocus [focus]\n");
110
  printf("\tframe $w.f\n");
111
  printf("\tbutton $w.f.back -text \"Main Menu\" \\\n"
112
         "\t\t-width 15 -command \"destroy $w; focus $oldFocus; update_mainmenu $w\"\n");
113
  printf("\tbutton $w.f.next -text \"Next\" \\\n"
114
         "\t\t-width 15 -command \" destroy $w; focus $oldFocus;  menu%d .menu%d \\\"$title\\\"\"\n",
115
                menu_num+1, menu_num+1);
116
  if (menu_num == tot_menu_num)
117
        printf("\t$w.f.next configure -state disabled\n");
118
  printf("\tbutton $w.f.prev -text \"Prev\" \\\n"
119
         "\t\t-width 15 -command \" destroy $w; focus $oldFocus; menu%d .menu%d \\\"$title\\\"\"\n",
120
                menu_num-1, menu_num-1);
121
  if (1 == menu_num)
122
        printf("\t$w.f.prev configure -state disabled\n");
123
  printf("\tpack $w.f.back $w.f.next $w.f.prev -side left -expand on\n");
124
  printf("\tpack $w.f -pady 10 -side bottom -anchor w -fill x\n");
125
 
126
  /*
127
   * Lines between canvas and other areas of the window.
128
   */
129
  printf("\tframe $w.topline -relief ridge -borderwidth 2 -height 2\n");
130
  printf("\tpack $w.topline -side top -fill x\n\n");
131
  printf("\tframe $w.botline -relief ridge -borderwidth 2 -height 2\n");
132
  printf("\tpack $w.botline -side bottom -fill x\n\n");
133
 
134
  /*
135
   * The "config" frame contains the canvas and a scrollbar.
136
   */
137
  printf("\tframe $w.config\n");
138
  printf("\tpack $w.config -fill y -expand on\n\n");
139
  printf("\tscrollbar $w.config.vscroll -command \"$w.config.canvas yview\"\n");
140
  printf("\tpack $w.config.vscroll -side right -fill y\n\n");
141
 
142
  /*
143
   * The scrollable canvas itself, where the real work (and mess) gets done.
144
   */
145
  printf("\tcanvas $w.config.canvas -height 1\\\n"
146
         "\t\t-relief flat -borderwidth 0 -yscrollcommand \"$w.config.vscroll set\" \\\n"
147
         "\t\t-width [expr [winfo screenwidth .] * 1 / 2] \n");
148
  printf("\tframe $w.config.f\n");
149
  printf("\tpack $w.config.canvas -side right -fill y\n");
150
 
151
  printf("\n\n");
152
}
153
 
154
/*
155
 * Each proc we create needs a global declaration for any global variables we
156
 * use.  To minimize the size of the file, we set a flag each time we output
157
 * a global declaration so we know whether we need to insert one for a
158
 * given function or not.
159
 */
160
void clear_globalflags(struct kconfig * cfg)
161
{
162
  for(; cfg != NULL; cfg = cfg->next)
163
  {
164
    cfg->flags &= ~GLOBAL_WRITTEN;
165
  }
166
}
167
 
168
/*
169
 * Output a "global" line for a given variable.  Also include the
170
 * call to "vfix".  (If vfix is not needed, then it's fine to just printf
171
 * a "global" line).
172
 */
173
void inline global(char *var)
174
{
175
  printf("\tglobal %s; vfix %s\n", var, var);
176
}
177
 
178
/*
179
 * This function walks the chain of conditions that we got from cond.c,
180
 * and creates a wish conditional to enable/disable a given widget.
181
 */
182
void generate_if(struct kconfig * item,
183
            struct condition * cond,
184
            int menu_num,
185
            int line_num)
186
{
187
  struct condition * ocond;
188
 
189
  ocond = cond;
190
 
191
  /*
192
   * First write any global declarations we need for this conditional.
193
   */
194
  while(cond != NULL )
195
    {
196
      switch(cond->op){
197
      case op_variable:
198
        global(cond->variable.str);
199
        break;
200
      case op_kvariable:
201
        if(cond->variable.cfg->flags & GLOBAL_WRITTEN) break;
202
        cond->variable.cfg->flags |= GLOBAL_WRITTEN;
203
        global(cond->variable.cfg->optionname);
204
        break;
205
      default:
206
        break;
207
      }
208
      cond = cond->next;
209
    }
210
 
211
  /*
212
   * Now write this option.
213
   */
214
  if(   (item->flags & GLOBAL_WRITTEN) == 0
215
     && (item->optionname != NULL) )
216
    {
217
      global(item->optionname);
218
      item->flags |= GLOBAL_WRITTEN;
219
    }
220
  /*
221
   * Now generate the body of the conditional.
222
   */
223
  printf("\tif {");
224
  cond = ocond;
225
  while(cond != NULL )
226
    {
227
      switch(cond->op){
228
      case op_bang:
229
        printf(" ! ");
230
        break;
231
      case op_eq:
232
        printf(" == ");
233
        break;
234
      case op_neq:
235
        printf(" != ");
236
        break;
237
      case op_and:
238
      case op_and1:
239
        printf(" && ");
240
        break;
241
      case op_or:
242
        printf(" || ");
243
        break;
244
      case op_lparen:
245
        printf("(");
246
        break;
247
      case op_rparen:
248
        printf(")");
249
        break;
250
      case op_variable:
251
        printf("$%s", cond->variable.str);
252
        break;
253
      case op_kvariable:
254
        printf("$%s", cond->variable.cfg->optionname);
255
        break;
256
      case op_shellcmd:
257
        printf("[exec %s]", cond->variable.str);
258
        break;
259
      case op_constant:
260
        if( strcmp(cond->variable.str, "y") == 0 )
261
          printf("1");
262
        else if( strcmp(cond->variable.str, "n") == 0 )
263
          printf("0");
264
        else if( strcmp(cond->variable.str, "m") == 0 )
265
          printf("2");
266
        else
267
          printf("\"%s\"", cond->variable.str);
268
        break;
269
      default:
270
        break;
271
      }
272
      cond = cond->next;
273
    }
274
 
275
  /*
276
   * Now we generate what we do depending upon the value of the conditional.
277
   * Depending upon what the token type is, there are different things
278
   * we must do to enable/disable the given widget - this code needs to
279
   * be closely coordinated with the widget creation procedures in header.tk.
280
   */
281
  switch(item->tok)
282
    {
283
    case tok_define_int:
284
    case tok_define:
285
      printf("} then { set %s %s } \n",  item->optionname, item->value);
286
      break;
287
    case tok_menuoption:
288
      printf("} then { .f0.x%d configure -state normal } else { .f0.x%d configure -state disabled }\n",
289
             menu_num, menu_num);
290
      break;
291
    case tok_int:
292
    case tok_hex:
293
      printf("} then { ");
294
      printf(".menu%d.config.f.x%d.x configure -state normal -fore [ cget .ref -foreground ]; ", menu_num, line_num);
295
      printf(".menu%d.config.f.x%d.l configure -state normal; ", menu_num, line_num);
296
      printf("} else { ");
297
      printf(".menu%d.config.f.x%d.x configure -state disabled -fore [ cget .ref -disabledforeground ];", menu_num, line_num );
298
      printf(".menu%d.config.f.x%d.l configure -state disabled;", menu_num, line_num );
299
      printf("}\n");
300
      break;
301
    case tok_bool:
302
#ifdef BOOL_IS_BUTTON
303
      /*
304
       * If a bool is just a button, then use this definition.
305
       */
306
      printf("} then { .menu%d.config.f.x%d configure -state normal } else { .menu%d.config.f.x%d configure -state disabled }\n",
307
             menu_num, line_num,
308
             menu_num, line_num );
309
#else
310
      /*
311
       * If a bool is a radiobutton, then use this instead.
312
       */
313
      printf("} then { ");
314
      printf(".menu%d.config.f.x%d.y configure -state normal;",menu_num, line_num);
315
      printf(".menu%d.config.f.x%d.n configure -state normal;",menu_num, line_num);
316
      printf(".menu%d.config.f.x%d.l configure -state normal;",menu_num, line_num);
317
      printf("set %s [expr $%s&15];", item->optionname, item->optionname);
318
      printf("} else { ");
319
      printf(".menu%d.config.f.x%d.y configure -state disabled;",menu_num, line_num);
320
      printf(".menu%d.config.f.x%d.n configure -state disabled;",menu_num, line_num);
321
      printf(".menu%d.config.f.x%d.l configure -state disabled;",menu_num, line_num);
322
      printf("set %s [expr $%s|16];", item->optionname, item->optionname);
323
      printf("}\n");
324
#endif
325
      break;
326
    case tok_tristate:
327
    case tok_dep_tristate:
328
      printf("} then { ");
329
      if( item->tok == tok_dep_tristate )
330
        {
331
          global(item->depend.str);
332
          printf("if { $%s != 1 && $%s != 0 } then {",
333
                item->depend.str,item->depend.str);
334
          printf(".menu%d.config.f.x%d.y configure -state disabled;",menu_num, line_num);
335
          printf("} else {");
336
          printf(".menu%d.config.f.x%d.y configure -state normal;",menu_num, line_num);
337
          printf("}; ");
338
        }
339
      else
340
        {
341
          printf(".menu%d.config.f.x%d.y configure -state normal;",menu_num, line_num);
342
        }
343
 
344
      printf(".menu%d.config.f.x%d.n configure -state normal;",menu_num, line_num);
345
      printf(".menu%d.config.f.x%d.m configure -state normal;",menu_num, line_num);
346
      printf(".menu%d.config.f.x%d.l configure -state normal;",menu_num, line_num);
347
      /*
348
       * Or in a bit to the variable - this causes all of the radiobuttons
349
       * to be deselected (i.e. not be red).
350
       */
351
      printf("set %s [expr $%s&15];", item->optionname, item->optionname);
352
      printf("} else { ");
353
      printf(".menu%d.config.f.x%d.y configure -state disabled;",menu_num, line_num);
354
      printf(".menu%d.config.f.x%d.n configure -state disabled;",menu_num, line_num);
355
      printf(".menu%d.config.f.x%d.m configure -state disabled;",menu_num, line_num);
356
      printf(".menu%d.config.f.x%d.l configure -state disabled;",menu_num, line_num);
357
      /*
358
       * Clear the disable bit - this causes the correct radiobutton
359
       * to appear selected (i.e. turn red).
360
       */
361
      printf("set %s [expr $%s|16];", item->optionname, item->optionname);
362
      printf("}\n");
363
      break;
364
    case tok_choose:
365
    case tok_choice:
366
      fprintf(stderr,"Fixme\n");
367
      exit(0);
368
    default:
369
      break;
370
    }
371
}
372
 
373
/*
374
 * Similar to generate_if, except we come here when generating an
375
 * output file.  Thus instead of enabling/disabling a widget, we
376
 * need to decide whether to write out a given configuration variable
377
 * to the output file.
378
 */
379
void generate_if_for_outfile(struct kconfig * item,
380
            struct condition * cond)
381
{
382
  struct condition * ocond;
383
 
384
  /*
385
   * First write any global declarations we need for this conditional.
386
   */
387
  ocond = cond;
388
  for(; cond != NULL; cond = cond->next )
389
    {
390
      switch(cond->op){
391
      case op_variable:
392
        global(cond->variable.str);
393
        break;
394
      case op_kvariable:
395
        if(cond->variable.cfg->flags & GLOBAL_WRITTEN) break;
396
        cond->variable.cfg->flags |= GLOBAL_WRITTEN;
397
        global(cond->variable.cfg->optionname);
398
        break;
399
      default:
400
        break;
401
      }
402
    }
403
 
404
  /*
405
   * Now generate the body of the conditional.
406
   */
407
  printf("\tif {");
408
  cond = ocond;
409
  while(cond != NULL )
410
    {
411
      switch(cond->op){
412
      case op_bang:
413
        printf(" ! ");
414
        break;
415
      case op_eq:
416
        printf(" == ");
417
        break;
418
      case op_neq:
419
        printf(" != ");
420
        break;
421
      case op_and:
422
      case op_and1:
423
        printf(" && ");
424
        break;
425
      case op_or:
426
        printf(" || ");
427
        break;
428
      case op_lparen:
429
        printf("(");
430
        break;
431
      case op_rparen:
432
        printf(")");
433
        break;
434
      case op_variable:
435
        printf("$%s", cond->variable.str);
436
        break;
437
      case op_shellcmd:
438
        printf("[exec %s]", cond->variable.str);
439
        break;
440
      case op_kvariable:
441
        printf("$%s", cond->variable.cfg->optionname);
442
        break;
443
      case op_constant:
444
        if( strcmp(cond->variable.str, "y") == 0 )
445
          printf("1");
446
        else if( strcmp(cond->variable.str, "n") == 0 )
447
          printf("0");
448
        else if( strcmp(cond->variable.str, "m") == 0 )
449
          printf("2");
450
        else
451
          printf("\"%s\"", cond->variable.str);
452
        break;
453
      default:
454
        break;
455
      }
456
      cond = cond->next;
457
    }
458
 
459
  /*
460
   * Now we generate what we do depending upon the value of the
461
   * conditional.  Depending upon what the token type is, there are
462
   * different things we must do write the value the given widget -
463
   * this code needs to be closely coordinated with the widget
464
   * creation procedures in header.tk.
465
   */
466
  switch(item->tok)
467
    {
468
    case tok_define_int:
469
      printf("} then {write_int $cfg $autocfg %s %s $notmod }\n", item->optionname, item->value);
470
      break;
471
    case tok_define:
472
      printf("} then {write_tristate $cfg $autocfg %s %s $notmod }\n", item->optionname, item->value);
473
      break;
474
    case tok_comment:
475
      printf("} then {write_comment $cfg $autocfg \"%s\"}\n", item->label);
476
      break;
477
    case tok_dep_tristate:
478
      printf("} then { write_tristate $cfg $autocfg %s $%s $%s } \n",
479
             item->optionname, item->optionname, item->depend.str);
480
      break;
481
    case tok_tristate:
482
    case tok_bool:
483
      printf("} then { write_tristate $cfg $autocfg %s $%s $notmod }\n",
484
             item->optionname, item->optionname);
485
      break;
486
    case tok_int:
487
      printf("} then { write_int $cfg $autocfg %s $%s $notmod }\n",
488
             item->optionname, item->optionname);
489
      break;
490
    case tok_hex:
491
      printf("} then { write_hex $cfg $autocfg %s $%s $notmod }\n",
492
             item->optionname, item->optionname);
493
      break;
494
    case tok_make:
495
      printf("} then { do_make {%s} }\n",item->value);
496
      break;
497
    case tok_choose:
498
    case tok_choice:
499
      fprintf(stderr,"Fixme\n");
500
      exit(0);
501
    default:
502
      break;
503
    }
504
}
505
 
506
/*
507
 * Generates a fragment of wish script that closes out a submenu procedure.
508
 */
509
static void end_proc(int menu_num)
510
{
511
  struct kconfig * cfg;
512
 
513
  printf("\n\n\n");
514
  printf("\tfocus $w\n");
515
  printf("\tupdate_menu%d $w.config.f\n", menu_num);
516
  printf("\tglobal winx; global winy\n");
517
  printf("\tset winx [expr [winfo x .]+30]; set winy [expr [winfo y .]+30]\n");
518
  printf("\twm geometry $w +$winx+$winy\n");
519
 
520
  /*
521
   * Now that the whole window is in place, we need to wait for an "update"
522
   * so we can tell the canvas what its virtual size should be.
523
   *
524
   * Unfortunately, this causes some ugly screen-flashing because the whole
525
   * window is drawn, and then it is immediately resized.  It seems
526
   * unavoidable, though, since "frame" objects won't tell us their size
527
   * until after an update, and "canvas" objects can't automatically pack
528
   * around frames.  Sigh.
529
   */
530
  printf("\tupdate idletasks\n");
531
  printf("\t$w.config.canvas create window 0 0 -anchor nw -window $w.config.f\n\n");
532
  printf("\t$w.config.canvas configure \\\n"
533
         "\t\t-width [expr [winfo reqwidth $w.config.f] + 1]\\\n"
534
         "\t\t-scrollregion \"-1 -1 [expr [winfo reqwidth $w.config.f] + 1] \\\n"
535
         "\t\t\t [expr [winfo reqheight $w.config.f] + 1]\"\n\n");
536
 
537
  /*
538
   * If the whole canvas will fit in 3/4 of the screen height, do it;
539
   * otherwise, resize to around 1/2 the screen and let us scroll.
540
   */
541
  printf("\tset winy [expr [winfo reqh $w] - [winfo reqh $w.config.canvas]]\n");
542
  printf("\tset scry [expr [winfo screenh $w] / 2]\n");
543
  printf("\tset maxy [expr [winfo screenh $w] * 3 / 4]\n");
544
  printf("\tset canvtotal [expr [winfo reqh $w.config.f] + 2]\n");
545
  printf("\tif [expr $winy + $canvtotal < $maxy] {\n"
546
         "\t\t$w.config.canvas configure -height $canvtotal\n"
547
         "\t} else {\n"
548
         "\t\t$w.config.canvas configure -height [expr $scry - $winy]\n"
549
         "\t}\n");
550
 
551
  /*
552
   * Limit the min/max window size.  Height can vary, but not width,
553
   * because of the limitations of canvas and our laziness.
554
   */
555
  printf("\tupdate idletasks\n");
556
  printf("\twm maxsize $w [winfo width $w] [winfo screenheight $w]\n");
557
  printf("\twm minsize $w [winfo width $w] 100\n\n");
558
  printf("\twm deiconify $w\n");
559
 
560
  printf("}\n\n\n");
561
 
562
  /*
563
   * Now we generate the companion procedure for the menu we just
564
   * generated.  This procedure contains all of the code to
565
   * disable/enable widgets based upon the settings of the other
566
   * widgets, and will be called first when the window is mapped,
567
   * and each time one of the buttons in the window are clicked.
568
   */
569
  printf("proc update_menu%d {w}  {\n", menu_num);
570
 
571
  printf("\tupdate_define\n");
572
  clear_globalflags(config);
573
  for(cfg = config;cfg != NULL; cfg = cfg->next)
574
    {
575
      /*
576
       * Skip items not for this menu, or ones having no conditions.
577
       */
578
      if (cfg->menu_number != menu_num ) continue;
579
      if (cfg->tok != tok_define && cfg->tok != tok_define_int)
580
        continue;
581
      /*
582
       * Clear all of the booleans that are defined in this menu.
583
       */
584
      if(   (cfg->flags & GLOBAL_WRITTEN) == 0
585
         && (cfg->optionname != NULL) )
586
        {
587
          printf("\tglobal %s\n", cfg->optionname);
588
          cfg->flags |= GLOBAL_WRITTEN;
589
          printf("\tset %s 0\n", cfg->optionname);
590
        }
591
 
592
    }
593
  for(cfg = config;cfg != NULL; cfg = cfg->next)
594
    {
595
      /*
596
       * Skip items not for this menu, or ones having no conditions.
597
       */
598
      if (cfg->menu_number != menu_num ) continue;
599
      if (cfg->tok == tok_menuoption) continue;
600
      if (cfg->cond != NULL )
601
        generate_if(cfg, cfg->cond, menu_num, cfg->menu_line);
602
      else
603
        {
604
          /*
605
           * If this token has no conditionals, check to see whether
606
           * it is a tristate - if so, then generate the conditional
607
           * to enable/disable the "y" button based upon the setting
608
           * of the option it depends upon.
609
           */
610
          if(cfg->tok == tok_dep_tristate)
611
            {
612
              global(cfg->depend.str);
613
              printf("\tif {$%s != 1 && $%s != 0 } then { .menu%d.config.f.x%d.y configure -state disabled } else { .menu%d.config.f.x%d.y configure -state normal}\n",
614
                     cfg->depend.str,cfg->depend.str,
615
                     menu_num, cfg->menu_line,
616
                     menu_num, cfg->menu_line);
617
            }
618
        }
619
 
620
    }
621
 
622
 
623
  printf("}\n\n\n");
624
}
625
 
626
/*
627
 * This function goes through and counts up the number of items in
628
 * each submenu. If there are too many options, we need to split it
629
 * into submenus.  This function just calculates how many submenus,
630
 * and how many items go in each submenu.
631
 */
632
static void find_menu_size(struct kconfig *cfg,
633
                          int *menu_max,
634
                          int *menu_maxlines)
635
 
636
{
637
  struct kconfig * pnt;
638
  int tot;
639
 
640
  /*
641
   * First count up the number of options in this menu.
642
   */
643
  tot = 0;
644
  for(pnt = cfg->next; pnt; pnt = pnt->next)
645
  {
646
    if( pnt->tok == tok_menuoption) break;
647
    switch (pnt->tok)
648
      {
649
      case tok_bool:
650
      case tok_tristate:
651
      case tok_dep_tristate:
652
      case tok_int:
653
      case tok_hex:
654
      case tok_choose:
655
        tot++;
656
        break;
657
      case tok_choice:
658
      default:
659
        break;
660
      }
661
  }
662
 
663
  *menu_max = cfg->menu_number;
664
  *menu_maxlines = tot;
665
}
666
 
667
/*
668
 * This is the top level function for generating the tk script.
669
 */
670
void dump_tk_script(struct kconfig *scfg)
671
{
672
  int menu_num =0;
673
  int menu_max =0;
674
  int menu_min =0;
675
  int menu_line = 0;
676
  int menu_maxlines = 0;
677
  struct kconfig * cfg;
678
  struct kconfig * cfg1 = NULL;
679
  char * menulabel;
680
 
681
  /*
682
   * Start by assigning menu numbers, and submenu numbers.
683
   */
684
  for(cfg = scfg;cfg != NULL; cfg = cfg->next)
685
    {
686
      switch (cfg->tok)
687
        {
688
        case tok_menuname:
689
          break;
690
        case tok_menuoption:
691
          /*
692
           * At the start of a new menu, calculate the number of items
693
           * we will put into each submenu so we know when to bump the
694
           * menu number. The submenus are really no different from a
695
           * normal menu, but the top level buttons only access the first
696
           * of the chain of menus, and the prev/next buttons are used
697
           * access the submenus.
698
           */
699
          cfg->menu_number = ++menu_num;
700
          find_menu_size(cfg, &menu_max, &menu_maxlines);
701
          cfg->submenu_start = menu_num;
702
          cfg->submenu_end = menu_max;
703
          menu_line = 0;
704
          break;
705
        case tok_bool:
706
        case tok_tristate:
707
        case tok_dep_tristate:
708
        case tok_int:
709
        case tok_hex:
710
        case tok_choose:
711
          /*
712
           * If we have overfilled the menu, then go to the next one.
713
           */
714
          if( menu_line == menu_maxlines )
715
            {
716
              menu_line = 0;
717
              menu_num++;
718
            }
719
          cfg->menu_number = menu_num;
720
          cfg->submenu_start = menu_min;
721
          cfg->submenu_end = menu_max;
722
          cfg->menu_line = menu_line++;
723
          break;
724
        case tok_define:
725
        case tok_define_int:
726
          cfg->menu_number = -1;
727
        case tok_choice:
728
        default:
729
          break;
730
        };
731
    }
732
 
733
  /*
734
   * Record this so we can set up the prev/next buttons correctly.
735
   */
736
  tot_menu_num = menu_num;
737
 
738
  /*
739
   * Now start generating the actual wish script that we will use.
740
   * We need to keep track of the menu numbers of the min/max menu
741
   * for a range of submenus so that we can correctly limit the
742
   * prev and next buttons so that they don't go over into some other
743
   * category.
744
   */
745
  for(cfg = scfg; cfg != NULL; cfg = cfg->next)
746
    {
747
      switch (cfg->tok)
748
        {
749
        case tok_menuname:
750
          printf("mainmenu_name \"%s\"\n", cfg->label);
751
          break;
752
        case tok_menuoption:
753
          /*
754
           * We are at the start of a new menu. If we had one that
755
           * we were working on before, close it out, and then generate
756
           * the script to start the new one.
757
           */
758
          if( cfg->menu_number > 1 )
759
            {
760
              end_proc(menu_num);
761
            }
762
          menulabel = cfg->label;
763
          start_proc(cfg->label, cfg->menu_number, TRUE);
764
          menu_num = cfg->menu_number;
765
          menu_max = cfg->submenu_end;
766
          menu_min = cfg->submenu_start;
767
          break;
768
        case tok_bool:
769
          /*
770
           * If we reached the point where we need to switch over
771
           * to the next submenu, then bump the menu number and generate
772
           * the code to close out the old menu and start the new one.
773
           */
774
          if( cfg->menu_number != menu_num )
775
            {
776
              end_proc(menu_num);
777
              start_proc(menulabel, cfg->menu_number, FALSE);
778
              menu_num = cfg->menu_number;
779
            }
780
          printf("\tbool $w.config.f %d %d \"%s\" %s\n",
781
                 cfg->menu_number,
782
                 cfg->menu_line,
783
                 cfg->label,
784
                 cfg->optionname);
785
          break;
786
 
787
        case tok_choice:
788
          printf("\t$w.config.f.x%d.x.menu add radiobutton -label \"%s\" -variable %s -value \"%s\" -command \"update_menu%d .menu%d.config.f\"\n",
789
                 cfg1->menu_line,
790
                 cfg->label,
791
                 cfg1->optionname,
792
                 cfg->label,
793
                 cfg1->menu_number, cfg1->menu_number);
794
          break;
795
        case tok_choose:
796
          if( cfg->menu_number != menu_num )
797
            {
798
              end_proc(menu_num);
799
              start_proc(menulabel, cfg->menu_number, FALSE);
800
              menu_num = cfg->menu_number;
801
            }
802
          printf("\tglobal %s\n",cfg->optionname);
803
          printf("\tminimenu $w.config.f %d %d \"%s\" %s %s\n",
804
                cfg->menu_number,
805
                cfg->menu_line,
806
                cfg->label,
807
                cfg->optionname,
808
                /*
809
                 * We rely on the fact that the first tok_choice corresponding
810
                 * to the current tok_choose is cfg->next (compare parse() in
811
                 * tkparse.c).  We need its name to pick out the right help
812
                 * text from Configure.help.
813
                 */
814
                cfg->next->optionname);
815
          printf("\tmenu $w.config.f.x%d.x.menu\n", cfg->menu_line);
816
          cfg1 = cfg;
817
          break;
818
        case tok_tristate:
819
          if( cfg->menu_number != menu_num )
820
            {
821
              end_proc(menu_num);
822
              start_proc(menulabel, cfg->menu_number, FALSE);
823
              menu_num = cfg->menu_number;
824
            }
825
          printf("\ttristate $w.config.f %d %d \"%s\" %s\n",
826
                 cfg->menu_number,
827
                 cfg->menu_line,
828
                 cfg->label,
829
                 cfg->optionname);
830
          break;
831
        case tok_dep_tristate:
832
          if( cfg->menu_number != menu_num )
833
            {
834
              end_proc(menu_num);
835
              start_proc(menulabel, cfg->menu_number, FALSE);
836
              menu_num = cfg->menu_number;
837
            }
838
          printf("\tdep_tristate $w.config.f %d %d \"%s\" %s %s\n",
839
                 cfg->menu_number,
840
                 cfg->menu_line,
841
                 cfg->label,
842
                 cfg->optionname,
843
                 cfg->depend.str);
844
          break;
845
        case tok_int:
846
          if( cfg->menu_number != menu_num )
847
            {
848
              end_proc(menu_num);
849
              start_proc(menulabel, cfg->menu_number, FALSE);
850
              menu_num = cfg->menu_number;
851
            }
852
          printf("\tint $w.config.f %d %d \"%s\" %s\n",
853
                 cfg->menu_number,
854
                 cfg->menu_line,
855
                 cfg->label,
856
                 cfg->optionname);
857
          break;
858
        case tok_hex:
859
          if( cfg->menu_number != menu_num )
860
            {
861
              end_proc(menu_num);
862
              start_proc(menulabel, cfg->menu_number, FALSE);
863
              menu_num = cfg->menu_number;
864
            }
865
          printf("\thex $w.config.f %d %d \"%s\" %s\n",
866
                 cfg->menu_number,
867
                 cfg->menu_line,
868
                 cfg->label,
869
                 cfg->optionname);
870
          break;
871
        default:
872
          break;
873
        }
874
 
875
    }
876
 
877
  /*
878
   * Generate the code to close out the last menu.
879
   */
880
  end_proc(menu_num);
881
 
882
#ifdef ERIC_DONT_DEF
883
  /*
884
   * Generate the code for configuring the sound driver.  Right now this
885
   * cannot be done from the X script, but we insert the menu anyways.
886
   */
887
  start_proc("Configure sound driver", ++menu_num, TRUE);
888
#if 0
889
  printf("\tdo_make -C drivers/sound config\n");
890
  printf("\techo check_sound_config %d\n",menu_num);
891
#endif
892
  printf("\tlabel $w.config.f.m0 -bitmap error\n");
893
  printf("\tmessage $w.config.f.m1 -width 400 -aspect 300 -text \"The sound drivers cannot as of yet be configured via the X-based interface\" -relief raised\n");
894
  printf("\tpack $w.config.f.m0 $w.config.f.m1 -side top -pady 10 -expand on\n");
895
  /*
896
   * Close out the last menu.
897
   */
898
  end_proc(menu_num);
899
#endif
900
 
901
  /*
902
   * The top level menu also needs an update function.  When we exit a
903
   * submenu, we may need to disable one or more of the submenus on
904
   * the top level menu, and this procedure will ensure that things are
905
   * correct.
906
   */
907
  printf("proc update_mainmenu {w}  {\n");
908
  for(cfg = scfg; cfg != NULL; cfg = cfg->next)
909
    {
910
      switch (cfg->tok)
911
        {
912
        case tok_menuoption:
913
          if (cfg->cond != NULL )
914
            generate_if(cfg, cfg->cond, cfg->menu_number, cfg->menu_line);
915
          break;
916
        default:
917
          break;
918
        }
919
    }
920
 
921
  printf("}\n\n\n");
922
 
923
#if 0
924
  /*
925
   * Generate some code to set the variables that are "defined".
926
   */
927
  for(cfg = config;cfg != NULL; cfg = cfg->next)
928
    {
929
      /*
930
       * Skip items not for this menu, or ones having no conditions.
931
       */
932
      if( cfg->tok != tok_define && cfg->tok != tok_define_int) continue;
933
      if (cfg->cond != NULL )
934
        generate_if(cfg, cfg->cond, menu_num, cfg->menu_line);
935
      else
936
        {
937
          printf("\twrite_define %s %s\n", cfg->optionname, cfg->value);
938
        }
939
 
940
    }
941
#endif
942
 
943
  /*
944
   * Now generate code to load the default settings into the variables.
945
   * Note that the script in tail.tk will attempt to load .config,
946
   * which may override these settings, but that's OK.
947
   */
948
  for(cfg = scfg; cfg != NULL; cfg = cfg->next)
949
    {
950
      switch (cfg->tok)
951
        {
952
        case tok_bool:
953
        case tok_tristate:
954
        case tok_dep_tristate:
955
        case tok_choice:
956
          printf("set %s 0\n", cfg->optionname);
957
          break;
958
        case tok_int:
959
        case tok_hex:
960
          printf("set %s %s\n", cfg->optionname, cfg->value);
961
          break;
962
        case tok_choose:
963
          printf("set %s \"(not set)\"\n",cfg->optionname);
964
        default:
965
          break;
966
        }
967
    }
968
 
969
  /*
970
   * Next generate a function that can be called from the main menu that will
971
   * write all of the variables out.  This also serves double duty - we can
972
   * save configuration to a file using this.
973
   */
974
  printf("proc writeconfig {file1 file2} {\n");
975
  printf("\tset cfg [open $file1 w]\n");
976
  printf("\tset autocfg [open $file2 w]\n");
977
  printf("\tset notmod 1\n");
978
  printf("\tset notset 0\n");
979
  clear_globalflags(config);
980
  printf("\tputs $cfg \"#\"\n");
981
  printf("\tputs $cfg \"# Automatically generated make config: don't edit\"\n");
982
  printf("\tputs $cfg \"#\"\n");
983
 
984
  printf("\tputs $autocfg \"/*\"\n");
985
  printf("\tputs $autocfg \" * Automatically generated C config: don't edit\"\n");
986
  printf("\tputs $autocfg \" */\"\n");
987
  for(cfg = scfg; cfg != NULL; cfg = cfg->next)
988
    {
989
      switch (cfg->tok)
990
        {
991
        case tok_int:
992
        case tok_hex:
993
        case tok_bool:
994
        case tok_tristate:
995
        case tok_dep_tristate:
996
        case tok_define:
997
        case tok_define_int:
998
        case tok_choose:
999
          if(!(cfg->flags & GLOBAL_WRITTEN))
1000
            {
1001
              cfg->flags |= GLOBAL_WRITTEN;
1002
              printf("\tglobal %s\n", cfg->optionname);
1003
            }
1004
          /* fall through */
1005
        case tok_make:
1006
        case tok_comment:
1007
          if (cfg->cond != NULL )
1008
            generate_if_for_outfile(cfg, cfg->cond);
1009
          else
1010
            {
1011
              if(cfg->tok == tok_dep_tristate)
1012
                {
1013
                  printf("\tif {$%s == 0 } then {\n"
1014
                         "\t\twrite_tristate $cfg $autocfg %s $notset $notmod\n"
1015
                         "\t} else {\n"
1016
                         "\t\twrite_tristate $cfg $autocfg %s $%s $%s\n"
1017
                         "\t}\n",
1018
                         cfg->depend.str,
1019
                         cfg->optionname,
1020
                         cfg->optionname,
1021
                         cfg->optionname,
1022
                         cfg->depend.str);
1023
                }
1024
              else if(cfg->tok == tok_comment)
1025
                {
1026
                  printf("\twrite_comment $cfg $autocfg \"%s\"\n", cfg->label);
1027
                }
1028
#if 0
1029
              else if(cfg->tok == tok_define || cfg->tok == tok_define_int)
1030
                {
1031
                  printf("\twrite_define %s %s\n", cfg->optionname,
1032
                         cfg->value);
1033
                }
1034
#endif
1035
              else if (cfg->tok == tok_choose )
1036
                {
1037
                  for(cfg1 = cfg->next;
1038
                      cfg1 != NULL && cfg1->tok == tok_choice;
1039
                      cfg1 = cfg1->next)
1040
                    {
1041
                      printf("\tif { $%s == \"%s\" } then { write_tristate $cfg $autocfg %s 1 $notmod }\n",
1042
                             cfg->optionname,
1043
                             cfg1->label,
1044
                             cfg1->optionname);
1045
                    }
1046
                }
1047
              else if (cfg->tok == tok_int )
1048
                {
1049
                  printf("\twrite_int $cfg $autocfg %s $%s $notmod\n",
1050
                         cfg->optionname,
1051
                         cfg->optionname);
1052
                }
1053
              else if (cfg->tok == tok_define_int )
1054
                {
1055
                  printf("\twrite_int $cfg $autocfg %s $%s $notmod\n",
1056
                         cfg->optionname,
1057
                         cfg->optionname);
1058
                }
1059
              else if (cfg->tok == tok_hex )
1060
                {
1061
                  printf("\twrite_hex $cfg $autocfg %s $%s $notmod\n",
1062
                         cfg->optionname,
1063
                         cfg->optionname);
1064
                }
1065
              else if (cfg->tok == tok_make )
1066
                {
1067
                  printf("\tdo_make {%s}\n",cfg->value);
1068
                }
1069
              else
1070
                {
1071
                  printf("\twrite_tristate $cfg $autocfg %s $%s $notmod\n",
1072
                         cfg->optionname,
1073
                         cfg->optionname);
1074
                }
1075
            }
1076
          break;
1077
        default:
1078
          break;
1079
        }
1080
    }
1081
  printf("\tclose $cfg\n");
1082
  printf("\tclose $autocfg\n");
1083
  printf("}\n\n\n");
1084
 
1085
  /*
1086
   * Finally write a simple function that updates the master choice
1087
   * variable depending upon what values were loaded from a .config
1088
   * file.
1089
   */
1090
  printf("proc clear_choices { } {\n");
1091
  for(cfg = scfg; cfg != NULL; cfg = cfg->next)
1092
    {
1093
      if( cfg->tok != tok_choose ) continue;
1094
      for(cfg1 = cfg->next;
1095
          cfg1 != NULL && cfg1->tok == tok_choice;
1096
          cfg1 = cfg1->next)
1097
        {
1098
          printf("\tglobal %s; set %s 0\n",cfg1->optionname,cfg1->optionname);
1099
        }
1100
    }
1101
  printf("}\n\n\n");
1102
 
1103
  printf("proc update_choices { } {\n");
1104
  for(cfg = scfg; cfg != NULL; cfg = cfg->next)
1105
    {
1106
      if( cfg->tok != tok_choose ) continue;
1107
      printf("\tglobal %s\n", cfg->optionname);
1108
      for(cfg1 = cfg->next;
1109
          cfg1 != NULL && cfg1->tok == tok_choice;
1110
          cfg1 = cfg1->next)
1111
        {
1112
          printf("\tglobal %s\n", cfg1->optionname);
1113
          printf("\tif { $%s == 1 } then { set %s \"%s\" }\n",
1114
                 cfg1->optionname,
1115
                 cfg->optionname,
1116
                 cfg1->label);
1117
        }
1118
    }
1119
  printf("}\n\n\n");
1120
 
1121
  printf("proc update_define { } {\n");
1122
  clear_globalflags(config);
1123
  for(cfg = scfg; cfg != NULL; cfg = cfg->next)
1124
    {
1125
      if( cfg->tok != tok_define && cfg->tok != tok_define_int )
1126
        continue;
1127
      printf("\tglobal %s; set %s 0\n",  cfg->optionname,  cfg->optionname);
1128
      cfg->flags |= GLOBAL_WRITTEN;
1129
    }
1130
  for(cfg = scfg; cfg != NULL; cfg = cfg->next)
1131
    {
1132
      if( cfg->tok != tok_define && cfg->tok != tok_define_int ) continue;
1133
      if (cfg->cond != NULL )
1134
        generate_if(cfg, cfg->cond, -1, 0);
1135
      else
1136
        {
1137
          printf("\tset %s %s\n",
1138
                 cfg->optionname, cfg->value);
1139
        }
1140
    }
1141
  printf("}\n\n\n");
1142
  /*
1143
   * That's it.  We are done.  The output of this file will have header.tk
1144
   * prepended and tail.tk appended to create an executable wish script.
1145
   */
1146
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.