1
2 /***************************************************************************
3 * __ __ _ ___________ *
4 * \ \ / /| |____ ____| *
5 * \ \ / / | | | | *
6 * \ \ /\ / / | | | | *
7 * \ \/ \/ / | | | | *
8 * \ /\ / | | | | *
9 * \/ \/ |_| |_| *
10 * *
11 * Wiimms ISO Tools *
12 * http://wit.wiimm.de/ *
13 * *
14 ***************************************************************************
15 * *
16 * This file is part of the WIT project. *
17 * Visit http://wit.wiimm.de/ for project details and sources. *
18 * *
19 * Copyright (c) 2009-2013 by Dirk Clemens <wiimm@wiimm.de> *
20 * *
21 ***************************************************************************
22 * *
23 * This program is free software; you can redistribute it and/or modify *
24 * it under the terms of the GNU General Public License as published by *
25 * the Free Software Foundation; either version 2 of the License, or *
26 * (at your option) any later version. *
27 * *
28 * This program is distributed in the hope that it will be useful, *
29 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
31 * GNU General Public License for more details. *
32 * *
33 * See file gpl-2.0.txt or http://www.gnu.org/licenses/gpl-2.0.txt *
34 * *
35 ***************************************************************************/
36
37 #define _GNU_SOURCE 1
38
39 #include <sys/types.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <ctype.h>
44
45 #include "types.h"
46 #include "lib-std.h"
47 #include "iso-interface.h"
48 #include "ui.h"
49
50 #include "tab-ui.c"
51 #include "ui-head.inc"
52
53 //
54 ///////////////////////////////////////////////////////////////////////////////
55 /////////////// struct control_t ///////////////
56 ///////////////////////////////////////////////////////////////////////////////
57
58 typedef struct control_t
59 {
60 FILE * cf; // output c file
61 FILE * hf; // output h file
62 FILE * df; // output def file
63
64 const info_t * info; // pointer to first info_t
65 const info_t * end; // pointer to end of info_t
66
67 int n_cmd; // number of commands
68 int n_grp; // number of helper groups
69 int n_opt_specific; // number of cmd specific options (=OPT__N_SPECIFIC)
70 int n_opt; // number of options (=OPT__N_TOTAL)
71 int n_cmd_opt; // number of options of current command
72 bool need_sep; // separator needed
73 ccp cmd_name; // name of current command
74 ccp opt_prefix; // prefix for option variables, never NULL
75
76 u8 *opt_allow_grp; // grp allowed options: field[n_grp][n_opt_specific]
77 u8 *opt_allow_cmd; // cmd allowed options: field[n_cmd][n_opt_specific]
78
79 StringField_t gopt; // global options
80 StringField_t copt; // command specfic options
81 StringField_t opt_done; // option handled
82
83 } control_t;
84
85 //
86 ///////////////////////////////////////////////////////////////////////////////
87 /////////////// helpers ///////////////
88 ///////////////////////////////////////////////////////////////////////////////
89
90 static char tabs[] = "\t\t\t\t";
91
92 static char sep1[] =
93 "////////////////////////////////////////"
94 "///////////////////////////////////////";
95
96 static char sep2[] =
97 "########################################"
98 "#######################################";
99
100 //-----------------------------------------------------------------------------
101
DumpText(FILE * f,char * pbuf,char * pbuf_end,ccp text,bool is_uidef,ccp end)102 static void DumpText
103 ( FILE * f, char * pbuf, char * pbuf_end, ccp text, bool is_uidef, ccp end )
104 {
105 ASSERT(f||pbuf);
106
107 ccp tie = is_uidef ? " \\" : "";
108 char buf[100], *buf_end = buf + 70, *dest = buf;
109
110 bool apos = false;
111
112 if (!text)
113 text = "";
114 while (*text)
115 {
116 char * dest_break = 0;
117 ccp text_break = 0;
118
119 bool eol = false;
120 while ( !eol && *text && dest < buf_end )
121 {
122 if ( *text >= 1 && *text <= 3 )
123 {
124 // \1 : Text only for built in help
125 // \2 : Text only for ui.def
126 // \3 : Text for all (default)
127
128 const bool skip = *text == ( is_uidef ? 1 : 2 );
129 //PRINT("CH=%d, SKIP=%d\n",*text,skip);
130 text++;
131 if (skip)
132 while ( (u8)*text > 3 )
133 text++;
134 continue;
135 }
136
137 switch (*text)
138 {
139 case ' ':
140 if ( dest > buf )
141 {
142 dest_break = dest;
143 text_break = text;
144 }
145 *dest++ = *text++;
146 break;
147
148 case '\n':
149 eol = true;
150 *dest++ = '\\';
151 *dest++ = 'n';
152 text++;
153 dest_break = 0;
154 text_break = 0;
155 break;
156
157 case '\\':
158 case '"':
159 *dest++ = '\\';
160 *dest++ = *text++;
161 break;
162
163 case '{':
164 if (is_uidef)
165 *dest++ = *text++;
166 else if ( *++text == '{' )
167 *dest++ = *text++;
168 else
169 {
170 ccp ptr = text;
171 while ( *ptr > ' ' && *ptr != '}' )
172 ptr++;
173 apos = *ptr != '}';
174 if (apos)
175 *dest++ = '\'';
176 }
177 break;
178
179
180 case '}':
181 if (is_uidef)
182 *dest++ = *text++;
183 else if ( *++text == '}' )
184 *dest++ = *text++;
185 else if (apos)
186 {
187 apos = false;
188 *dest++ = '\'';
189 }
190 break;
191
192 case '@':
193 case '$':
194 case '�':
195 if (!is_uidef)
196 {
197 if ( text[1] == *text )
198 *dest++ = *text++;
199 text++;
200 break;
201 }
202 // fall through
203
204 default:
205 *dest++ = *text++;
206 }
207 DASSERT( dest < buf_end + 10 );
208 }
209
210 if ( dest >= buf_end && dest_break )
211 {
212 dest = dest_break;
213 text = text_break;
214 }
215
216 if ( dest > buf && *text )
217 {
218 *dest = 0;
219 if (f)
220 fprintf(f,"\t\"%s\"%s\n",buf,tie);
221 else
222 pbuf += snprintf(pbuf,pbuf_end-pbuf,"\t\"%s\"%s\n",buf,tie);
223 dest = buf;
224 }
225 }
226
227 *dest = 0;
228 if (f)
229 fprintf(f,"\t\"%s\"%s",buf,end);
230 else
231 pbuf += snprintf(pbuf,pbuf_end-pbuf,"\t\"%s\"%s",buf,end);
232 }
233
234 //-----------------------------------------------------------------------------
235
print_section(FILE * f,ccp sep,ccp name)236 static void print_section ( FILE *f, ccp sep, ccp name )
237 {
238 const size_t namelen = strlen(name);
239 const int fill = ( 49 - namelen ) /2;
240 const int fw = 49 - fill;
241 fprintf(f,"\n%.2s\f\n%s\n%.15s%*s%*s%.15s\n%s\n\n",
242 sep, sep, sep, fill, "", -fw, name, sep, sep );
243 }
244
245 //-----------------------------------------------------------------------------
246
print_info_opt(control_t * ctrl,const info_t * info,const info_t * default_info,ccp cmd_name)247 static void print_info_opt
248 (
249 control_t * ctrl,
250 const info_t * info,
251 const info_t * default_info,
252 ccp cmd_name
253 )
254 {
255 ASSERT(ctrl);
256 ASSERT(info);
257
258 FILE * cf = ctrl->cf;
259 ASSERT(cf);
260
261 if (cmd_name)
262 fprintf(cf,"const InfoOption_t option_%s_%s_%s =\n",
263 ctrl->opt_prefix, cmd_name, info->c_name );
264
265 fprintf(cf," {\tOPT_%s, ",info->c_name);
266 ccp start = ( default_info ? default_info : info ) -> namelist;
267 if ( *start && start[1] == '|' )
268 {
269 fprintf(cf,"'%c', ",*start);
270 start += 2;
271 }
272 else
273 fprintf(cf,"0, ");
274
275 ccp end = start;
276 while ( *end && *end != '|' )
277 end++;
278 fprintf(cf,"\"%.*s\",\n", (int)(end-start), start );
279
280 ccp param = info->param;
281 ccp help = info->help;
282 if (default_info)
283 {
284 if (!help)
285 help = default_info->help;
286 if (!param)
287 param = default_info->param;
288 }
289
290 if ( info->type & F_OPT_XPARAM || default_info && default_info->type & F_OPT_XPARAM )
291 fprintf(cf,"\t\"%s\",\n", param && *param ? param : "param" );
292 else
293 fprintf(cf,"\t0,\n");
294
295 DumpText(cf,0,0,help,0,"");
296 fprintf(cf,"\n }%c\n\n",cmd_name ? ';' : ',' );
297 }
298
299 //-----------------------------------------------------------------------------
300
print_opt(control_t * ctrl,const info_t * info)301 static void print_opt ( control_t * ctrl, const info_t * info )
302 {
303 ASSERT(ctrl);
304 ASSERT(info);
305
306 ctrl->n_opt++;
307 print_info_opt(ctrl,info,0,0);
308 fprintf( ctrl->hf, "\tOPT_%s,\n", info->c_name );
309 };
310
311 //-----------------------------------------------------------------------------
312
print_opt_link(control_t * ctrl,const info_t * info)313 static void print_opt_link ( control_t * ctrl, const info_t * info )
314 {
315 ASSERT(ctrl);
316 ASSERT(ctrl->cf);
317 ASSERT(ctrl->opt_prefix);
318 ASSERT(info);
319
320 if (!InsertStringField(&ctrl->opt_done,info->c_name,false))
321 return;
322
323 if ( ctrl->need_sep )
324 {
325 ctrl->need_sep = false;
326 if ( ctrl->n_cmd_opt )
327 fprintf(ctrl->cf,"\n\tOptionInfo + OPT_NONE, // separator\n\n" );
328 }
329
330 if ( !info->help || info->type & T_DEF_OPT )
331 fprintf(ctrl->cf,"\tOptionInfo + OPT_%s,\n", info->c_name );
332 else
333 fprintf(ctrl->cf,"\t&option_%s_%s,\n", ctrl->opt_prefix, info->c_name );
334
335 if (ctrl->cmd_name)
336 {
337 fprintf(ctrl->df,"#:def_cmd_opt( \"%s\", \"%s\", \\\n",
338 ctrl->cmd_name, info->c_name );
339 DumpText(ctrl->df,0,0,info->param,1,", \\\n");
340 DumpText(ctrl->df,0,0,info->help,1," )\n\n");
341 }
342
343 ctrl->n_cmd_opt++;
344 }
345
346 //-----------------------------------------------------------------------------
347
348 static const info_t * print_links_iterator
349 ( control_t * ctrl, const info_t * info, ccp prefix );
350
351 //-----------------------------------------------------------------------------
352
print_cmd_links(control_t * ctrl,const info_t * ref)353 static void print_cmd_links ( control_t * ctrl, const info_t * ref )
354 {
355 ASSERT(ctrl);
356 ASSERT(ref);
357
358 const info_t * info;
359 for ( info = ctrl->info; info < ctrl->end; info++ )
360 if ( info->type & T_CMD_BEG && !strcmp(info->c_name,ref->c_name) )
361 {
362 print_links_iterator(ctrl,info,"cmd");
363 break;
364 }
365 }
366
367 //-----------------------------------------------------------------------------
368
print_grp_links(control_t * ctrl,const info_t * ref)369 static void print_grp_links ( control_t * ctrl, const info_t * ref )
370 {
371 ASSERT(ctrl);
372 ASSERT(ref);
373
374 const info_t * info;
375 for ( info = ctrl->info; info < ctrl->end; info++ )
376 if ( info->type & T_GRP_BEG && !strcmp(info->c_name,ref->c_name) )
377 {
378 print_links_iterator(ctrl,info,"grp");
379 break;
380 }
381 }
382
383 //-----------------------------------------------------------------------------
384
print_links_iterator(control_t * ctrl,const info_t * info,ccp prefix)385 static const info_t * print_links_iterator
386 ( control_t * ctrl, const info_t * info, ccp prefix )
387 {
388 ASSERT(ctrl);
389 ASSERT(info);
390
391 ccp saved_prefix = ctrl->opt_prefix;
392 char buf[100];
393 if (prefix)
394 {
395 snprintf(buf,sizeof(buf),"%s_%s",prefix,info->c_name);
396 ctrl->opt_prefix = buf;
397 };
398
399 for ( info++; info < ctrl->end && !(info->type & (T_CMD_BEG|T_GRP_BEG) ); info++ )
400 {
401 if ( info->type & F_HIDDEN )
402 {
403 // ignored -> do nothing
404 }
405 else if ( info->type & T_SEP_OPT )
406 ctrl->need_sep = true;
407 else if ( info->type & (F_OPT_GLOBAL|T_CMD_OPT) )
408 print_opt_link(ctrl,info);
409 else if ( info->type & T_COPY_CMD )
410 print_cmd_links(ctrl,info);
411 else if ( info->type & T_COPY_GRP )
412 print_grp_links(ctrl,info);
413 }
414
415 ctrl->opt_prefix = saved_prefix;
416 return info;
417 }
418
419 //-----------------------------------------------------------------------------
420
print_links(control_t * ctrl)421 static void print_links ( control_t * ctrl )
422 {
423 ASSERT(ctrl);
424 FILE * cf = ctrl->cf;
425 ASSERT(cf);
426
427 print_section(cf,sep1,"InfoOption tabs");
428
429 char * temp_param = iobuf;
430 char * temp_help = iobuf + sizeof(iobuf)/8;
431 char * sum_beg = iobuf + sizeof(iobuf)/2;
432 char * sum_end = iobuf + sizeof(iobuf);
433 char * sum = sum_beg;
434
435 const info_t * info_cmd = ctrl->info;
436 ASSERT ( info_cmd->type & T_DEF_TOOL );
437 fprintf(cf,"const InfoOption_t * option_tab_tool[] =\n{\n");
438
439 ctrl->n_cmd_opt = 0;
440 ctrl->need_sep = false;
441
442 print_links_iterator(ctrl,info_cmd,"def");
443 fprintf(cf,"\n\t0\n};\n\n");
444
445 DumpText(0,temp_param,iobuf+sizeof(iobuf),info_cmd->param,0,"");
446 DumpText(0,temp_help,iobuf+sizeof(iobuf),info_cmd->help,0,"");
447 sum += snprintf(sum,sum_end-sum,
448 " {\t0,\n" // id
449 "\tfalse,\n" // hidden
450 "\tfalse,\n" // separator
451 "\t\"%s\",\n" // name1
452 "\t0,\n" // name2
453 "%s,\n" // param
454 "%s,\n" // help
455 "\t%u,\n" // n_opt
456 "\toption_tab_tool,\n" // opt
457 "\t0\n" // opt_allowed
458 " },\n\n"
459 ,info_cmd->c_name
460 ,temp_param
461 ,temp_help
462 ,ctrl->n_cmd_opt
463 );
464
465 bool separator = false;
466 for ( info_cmd++; info_cmd < ctrl->end; info_cmd++ )
467 {
468 if ( info_cmd->type & T_SEP_CMD )
469 separator = true;
470 //if ( !( info_cmd->type & T_DEF_CMD ) || info_cmd->type & F_HIDDEN )
471 if ( !( info_cmd->type & T_DEF_CMD ) )
472 continue;
473
474 fprintf(cf,"static const InfoOption_t * option_tab_cmd_%s[] =\n{\n",
475 info_cmd->c_name);
476
477 ctrl->n_cmd_opt = 0;
478 ctrl->need_sep = false;
479 ctrl->cmd_name = info_cmd->c_name;
480 ResetStringField(&ctrl->opt_done);
481
482 const info_t * info;
483 for ( info = info_cmd; info < ctrl->end; info++ )
484 if ( info->type & T_CMD_BEG && !strcmp(info->c_name,info_cmd->c_name) )
485 {
486 print_links_iterator(ctrl,info,"cmd");
487 break;
488 }
489 fprintf(cf,"\n\t0\n};\n\n");
490
491 ccp name1 = info_cmd->namelist, ptr = name1;
492 while ( *ptr && *ptr != '|' )
493 ptr++;
494 const int len1 = ptr - name1;
495 char name2[100] = "0";
496 if ( *ptr == '|' )
497 {
498 ccp n2 = ++ptr;
499 while ( *ptr && *ptr != '|' )
500 ptr++;
501 if ( ptr > n2 )
502 snprintf(name2,sizeof(name2),"\"%.*s\"",(int)(ptr-n2),n2);
503 }
504
505 DumpText(0,temp_param,iobuf+sizeof(iobuf),info_cmd->param,0,"");
506 DumpText(0,temp_help,iobuf+sizeof(iobuf),info_cmd->help,0,"");
507 sum += snprintf(sum,sum_end-sum,
508 " {\tCMD_%s,\n" // id
509 "\t%s,\n" // hidden
510 "\t%s,\n" // separator
511 "\t\"%.*s\",\n" // name1
512 "\t%s,\n" // name2
513 "%s,\n" // param
514 "%s,\n" // help
515 "\t%u,\n" // n_opt
516 "\toption_tab_cmd_%s,\n" // opt
517 "\toption_allowed_cmd_%s\n" // opt_allowed
518 " },\n\n"
519 ,info_cmd->c_name
520 ,info_cmd->type & F_HIDDEN ? "true" : "false"
521 ,separator ? "true" : "false"
522 ,len1 ,name1
523 ,name2
524 ,temp_param
525 ,temp_help
526 ,ctrl->n_cmd_opt
527 ,info_cmd->c_name
528 ,info_cmd->c_name
529 );
530 separator = false;
531 }
532
533 print_section(cf,sep1,"InfoCommand");
534 fprintf(cf,"const InfoCommand_t CommandInfo[CMD__N+1] =\n{\n");
535 fputs(sum_beg,cf);
536 fprintf(cf," {0,0,0,0,0,0,0,0,0}\n};\n");
537 }
538
539 //
540 ///////////////////////////////////////////////////////////////////////////////
541 /////////////// Generate() ///////////////
542 ///////////////////////////////////////////////////////////////////////////////
543
544 static char var_buf[10000];
545
546 //-----------------------------------------------------------------------------
547
Generate(control_t * ctrl)548 static enumError Generate ( control_t * ctrl )
549 {
550 ASSERT(ctrl);
551 ASSERT(ctrl->info);
552
553 FILE * cf = ctrl->cf;
554 FILE * hf = ctrl->hf;
555 ASSERT(cf);
556 ASSERT(hf);
557
558 FREE(ctrl->opt_allow_grp);
559 FREE(ctrl->opt_allow_cmd);
560 ctrl->opt_allow_grp = ctrl->opt_allow_cmd = 0;
561
562 const info_t *info;
563
564
565 //----- ui header
566
567 fprintf(cf,text_ui_head);
568 fprintf(hf,text_ui_head);
569
570
571 //----- setup guard
572
573 char guard[100];
574 snprintf(guard,sizeof(guard),"WIT_UI_%s_h",ctrl->info->c_name);
575 char * ptr;
576 for ( ptr = guard; *ptr; ptr++ )
577 *ptr = *ptr == '-' ? '_' : toupper((int)*ptr);
578 fprintf(hf,"\n#ifndef %s\n#define %s\n",guard,guard);
579
580
581 //----- header
582
583 ASSERT( ctrl->info->type & T_DEF_TOOL );
584 ccp tool_name = ctrl->info->c_name;
585
586 fprintf(cf,"#include <getopt.h>\n");
587 fprintf(cf,"#include \"ui-%s.h\"\n",tool_name);
588
589 fprintf(hf,"#include \"lib-std.h\"\n");
590 fprintf(hf,"#include \"ui.h\"\n");
591
592
593 //----- print enum enumOptions & OptionInfo[]
594
595 print_section(cf,sep1,"OptionInfo[]");
596 print_section(hf,sep1,"enum enumOptions");
597
598 char * var_ptr = var_buf;
599 char * var_end = var_buf + sizeof(var_buf);
600 var_ptr += snprintf(var_ptr,var_end-var_ptr,
601 "extern const InfoOption_t OptionInfo[OPT__N_TOTAL+1];\n");
602
603 fprintf(cf,
604 "const InfoOption_t OptionInfo[OPT__N_TOTAL+1] =\n"
605 "{\n"
606 " {0,0,0,0,0}, // OPT_NONE,\n"
607 "\n"
608 );
609
610 fprintf(hf,
611 "typedef enum enumOptions\n"
612 "{\n"
613 "\tOPT_NONE,\n"
614 "\n"
615 );
616
617 ctrl->n_opt = 1;
618 ctrl->n_opt_specific = 0;
619 if ( ctrl->n_cmd )
620 {
621 fprintf(cf," //----- command specific options -----\n\n");
622 fprintf(hf,"\t//----- command specific options -----\n\n");
623
624 for ( info = ctrl->info; info < ctrl->end; info++ )
625 if ( info->type & F_OPT_COMMAND )
626 print_opt(ctrl,info);
627
628 ctrl->n_opt_specific = ctrl->n_opt;
629
630 fprintf(cf,
631 " {0,0,0,0,0}, // OPT__N_SPECIFIC == %d\n\n"
632 " //----- global options -----\n\n",
633 ctrl->n_opt_specific );
634
635 fprintf(hf,
636 "\n\tOPT__N_SPECIFIC, // == %d \n\n"
637 "\t//----- global options -----\n\n",
638 ctrl->n_opt_specific );
639 }
640
641 for ( info = ctrl->info; info < ctrl->end; info++ )
642 if ( info->type & F_OPT_GLOBAL )
643 print_opt(ctrl,info);
644
645 fprintf(cf,
646 " {0,0,0,0,0} // OPT__N_TOTAL == %d\n\n"
647 "};\n"
648 ,ctrl->n_opt );
649
650 fprintf(hf,
651 "\n\tOPT__N_TOTAL // == %d\n\n"
652 "} enumOptions;\n"
653 ,ctrl->n_opt );
654
655 if (ctrl->n_opt_specific)
656 {
657 noTRACE("opt_allowed = ( %2u + %2u ) * %2u\n",
658 ctrl->n_grp, ctrl->n_cmd, ctrl->n_opt_specific );
659 if (ctrl->n_grp)
660 ctrl->opt_allow_grp = CALLOC(ctrl->n_grp,ctrl->n_opt_specific);
661 ctrl->opt_allow_cmd = CALLOC(ctrl->n_cmd,ctrl->n_opt_specific);
662 }
663
664
665 //----- print alternate option infos
666
667 bool done = false;
668 const info_t * last_cmd = ctrl->info;
669 ctrl->opt_prefix = "def";
670 for ( info = ctrl->info; info < ctrl->end; info++ )
671 {
672 if ( info->type & T_CMD_BEG )
673 {
674 ctrl->opt_prefix = "cmd";
675 last_cmd = info;
676 }
677 else if ( info->type & T_GRP_BEG )
678 {
679 ctrl->opt_prefix = "grp";
680 last_cmd = info;
681 }
682 else if ( info->type & T_CMD_OPT && info->help && *info->help )
683 {
684 if (!done)
685 {
686 print_section(cf,sep1,"alternate option infos");
687 done = true;
688 }
689
690 const info_t * info0;
691 for ( info0 = ctrl->info; info0 < info; info0++ )
692 if ( info0->type & T_DEF_OPT && !strcmp(info->c_name,info0->c_name) )
693 {
694 print_info_opt(ctrl,info,info0,last_cmd->c_name);
695 break;
696 }
697 }
698 }
699
700 //----- print enum enumOptionsBit
701
702 if ( ctrl->n_cmd )
703 {
704 print_section(hf,sep1,"enum enumOptionsBit");
705
706 fprintf(hf,
707 "//\t***** only for verification *****\n"
708 "\n"
709 "//typedef enum enumOptionsBit\n"
710 "//{\n"
711 "//\t//----- command specific options -----\n"
712 "//\n"
713 );
714
715 for ( info = ctrl->info; info < ctrl->end; info++ )
716 if ( info->type & F_OPT_COMMAND )
717 fprintf(hf,"//\tOB_%s%.*s= 1llu << OPT_%s,\n",
718 info->c_name,
719 ( 28 - (int)strlen(info->c_name) ) / 8, tabs,
720 info->c_name );
721
722 fprintf(hf,"//\n//\t//----- group & command options -----\n");
723
724 for ( info = ctrl->info; info < ctrl->end; )
725 {
726 ccp cmd_name;
727 u8 * opt_allow = 0;
728 if ( info->type & T_CMD_BEG )
729 {
730 cmd_name = info->c_name;
731 fprintf(hf,"//\n//\tOB_CMD_%s%.*s=",
732 info->c_name,
733 ( 24 - (int)strlen(info->c_name) ) / 8, tabs );
734 if (ctrl->opt_allow_cmd)
735 {
736 //PRINT("SELECT ALLOW CMD %u/%s\n",info->index,info->c_name);
737 opt_allow = ctrl->opt_allow_cmd + info->index * ctrl->n_opt_specific;
738 }
739 }
740 else if ( info->type & T_GRP_BEG )
741 {
742 cmd_name = info->c_name;
743 fprintf(hf,"//\n//\tOB_GRP_%s%.*s=",
744 info->c_name,
745 ( 24 - (int)strlen(info->c_name) ) / 8, tabs );
746 if (ctrl->opt_allow_grp)
747 {
748 //PRINT("SELECT ALLOW GRP %u/%s\n",info->index,info->c_name);
749 opt_allow = ctrl->opt_allow_grp + info->index * ctrl->n_opt_specific;
750 }
751 }
752 else
753 {
754 info++;
755 continue;
756 }
757
758 info++;
759 char * dest = iobuf;
760 while ( info < ctrl->end )
761 {
762 if ( info->type & T_ALL_OPT )
763 {
764 dest += sprintf(dest,"\n//\t\t\t\t| ~(u64)0");
765 if (opt_allow)
766 {
767 //PRINT("ALLOW ALL\n");
768 memset(opt_allow,1,ctrl->n_opt_specific);
769 }
770 }
771 else if ( info->type & T_COPY_CMD )
772 {
773 dest += sprintf(dest,"\n//\t\t\t\t| OB_CMD_%s",info->c_name);
774 if (opt_allow)
775 {
776 //PRINT("OR CMD %u/%s\n",info->index,info->c_name);
777 DASSERT(ctrl->opt_allow_cmd);
778 u8 * src = ctrl->opt_allow_cmd + info->index * ctrl->n_opt_specific;
779 u8 * dest = opt_allow;
780 int count = ctrl->n_opt_specific;
781 while ( count-- > 0 )
782 *dest++ |= *src++;
783 }
784 }
785 else if ( info->type & T_COPY_GRP )
786 {
787 dest += sprintf(dest,"\n//\t\t\t\t| OB_GRP_%s",info->c_name);
788 if ( opt_allow && ctrl->opt_allow_grp )
789 {
790 //PRINT("OR GRP %u/%s\n",info->index,info->c_name);
791 u8 * src = ctrl->opt_allow_grp + info->index * ctrl->n_opt_specific;
792 u8 * dest = opt_allow;
793 int count = ctrl->n_opt_specific;
794 while ( count-- > 0 )
795 *dest++ |= *src++;
796 }
797 }
798 else if ( info->type & T_CMD_OPT )
799 {
800 if (FindStringField(&ctrl->copt,info->c_name))
801 {
802 dest += sprintf(dest,"\n//\t\t\t\t| OB_%s",info->c_name);
803 if ( opt_allow && info->index )
804 {
805 //PRINT("ALLOW OPT %u/%s\n",info->index,info->c_name);
806 opt_allow[info->index] = 1;
807 }
808 }
809 else if (!FindStringField(&ctrl->gopt,info->c_name))
810 ERROR0(ERR_SEMANTIC,"Option not defined: %s %s --%s",
811 tool_name, cmd_name, info->c_name );
812 }
813 else if ( info->type & (T_CMD_BEG|T_GRP_BEG) )
814 break;
815 ASSERT( dest < iobuf + sizeof(iobuf) );
816 info++;
817 }
818 if ( dest == iobuf )
819 fprintf(hf," 0,\n");
820 else
821 fprintf(hf,"%s,\n",iobuf+8);
822 }
823
824 fprintf(hf,"//\n//} enumOptionsBit;\n");
825 }
826
827
828 //----- print enum enumCommands & CommandTab[]
829
830 print_section(hf,sep1,"enum enumCommands");
831 fprintf(hf,
832 "typedef enum enumCommands\n"
833 "{\n"
834 "\tCMD__NONE,"
835 );
836
837 if ( ctrl->n_cmd )
838 {
839 print_section(cf,sep1,"CommandTab[]");
840 fputs("\n\n",hf);
841
842 var_ptr += snprintf(var_ptr,var_end-var_ptr,
843 "extern const CommandTab_t CommandTab[];\n");
844
845 fprintf(cf,
846 "const CommandTab_t CommandTab[] =\n"
847 "{\n"
848 );
849
850 for ( info = ctrl->info; info < ctrl->end; info++ )
851 if ( info->type & T_DEF_CMD )
852 {
853 fprintf( hf, "\tCMD_%s,\n",info->c_name);
854 ccp ptr = info->namelist;
855 while (*ptr)
856 {
857 ccp n1 = ptr;
858 while ( *ptr && *ptr != '|' )
859 ptr++;
860 const int l1 = ptr - n1;
861 while ( *ptr == '|' )
862 ptr++;
863 if (*ptr)
864 {
865 ccp n2 = ptr;
866 while ( *ptr && *ptr != '|' )
867 ptr++;
868 const int l2 = ptr - n2;
869
870 fprintf(cf,
871 " { CMD_%s,%.*s\"%.*s\",%.*s\"%.*s\",%.*s0 },\n",
872 info->c_name, (20-(int)strlen(info->c_name))/8, tabs,
873 l1, n1, (20-l1)/8, tabs,
874 l2, n2, (20-l2)/8, tabs );
875
876 while ( *ptr == '|' )
877 ptr++;
878 }
879 else
880 fprintf(cf, " { CMD_%s,%.*s\"%.*s\",%.*s0,\t\t0 },\n",
881 info->c_name, (20-(int)strlen(info->c_name))/8, tabs,
882 l1, n1, (20-l1)/8, tabs );
883 }
884 }
885 else if ( info->type == T_SEP_CMD )
886 fprintf(hf,"\n");
887
888 fprintf(cf,
889 "\n { CMD__N,0,0,0 }\n"
890 "};\n"
891 );
892 }
893
894 fprintf(hf,
895 "\n\tCMD__N // == %u\n\n"
896 "} enumCommands;\n"
897 , ctrl->n_cmd );
898
899
900 //----- print options
901
902 print_section(cf,sep1,"OptionShort & OptionLong");
903
904 char * dest = iobuf;
905 for ( info = ctrl->info; info < ctrl->end; info++ )
906 if ( info->type & T_DEF_OPT && info->namelist[1] == '|' )
907 {
908 *dest++ = info->namelist[0];
909 if ( info->type & F_OPT_OPTPARAM )
910 *dest++ = ':';
911 if ( info->type & (F_OPT_OPTPARAM|F_OPT_PARAM) )
912 *dest++ = ':';
913 }
914 *dest = 0;
915 fprintf(cf,"const char OptionShort[] = \"%s\";\n\n",iobuf);
916 var_ptr += snprintf(var_ptr,var_end-var_ptr,
917 "extern const char OptionShort[];\n");
918
919 ccp opt_buf[OPT_INDEX_SIZE];
920 memset(opt_buf,0,sizeof(opt_buf));
921 int getopt_idx = OPT_LONG_BASE;
922
923 fprintf(cf,"const struct option OptionLong[] =\n{\n");
924 var_ptr += snprintf(var_ptr,var_end-var_ptr,
925 "extern const struct option OptionLong[];\n");
926
927 for ( info = ctrl->info; info < ctrl->end; info++ )
928 if ( info->type & T_DEF_OPT )
929 {
930 ccp ptr = info->namelist;
931 const int pmode = (info->type & F_OPT_OPTPARAM)
932 ? 2
933 : (info->type & F_OPT_PARAM)
934 ? 1
935 : 0;
936
937 if ( info->namelist[1] == '|' )
938 {
939 snprintf(iobuf,sizeof(iobuf),"%d, 0, '%c'",
940 pmode, info->namelist[0] );
941 ptr += 2;
942 opt_buf[(u8)(info->namelist[0])] = info->c_name;
943 }
944 else
945 {
946 snprintf(iobuf,sizeof(iobuf),"%d, 0, GO_%s",
947 pmode, info->c_name );
948 ASSERT_MSG( getopt_idx < OPT_INDEX_SIZE,
949 "getopt_idx[%x] >= OPT_INDEX_SIZE[%x]\n",
950 getopt_idx, OPT_INDEX_SIZE );
951 opt_buf[(u8)(getopt_idx++)] = info->c_name;
952 }
953
954 int indent = 0;
955 while (*ptr)
956 {
957 ccp start = ptr;
958 while ( *ptr && *ptr != '|' )
959 ptr++;
960 const int len = ptr - start;
961 fprintf(cf,"\t%s{ \"%.*s\",%.*s%s },\n",
962 indent ? " " : "", len, start, (26-len-indent)/8, tabs, iobuf );
963 if (*ptr)
964 ptr++;
965 indent = 1;
966 }
967 }
968 fprintf(cf,"\n\t{0,0,0,0}\n};\n");
969
970
971 //----- print enumGetOpt
972
973 print_section(hf,sep1,"enumGetOpt");
974 fprintf(hf,"typedef enum enumGetOpt\n{");
975
976 // add '?' temporary;
977 ASSERT(!opt_buf['?']);
978 opt_buf['?'] = "_ERR";
979
980 static const int septab[] = { 0, '0', '9'+1, '?', '?'+1,
981 'A', 'Z'+1, 'a', 'z'+1,
982 OPT_LONG_BASE, OPT_INDEX_SIZE };
983 const int * sepptr = septab;
984 int i;
985 for ( i = 0; i < OPT_INDEX_SIZE; i++ )
986 if ( opt_buf[i] )
987 {
988 if ( i >= *sepptr )
989 {
990 fputc('\n',hf);
991 while ( i >= *sepptr )
992 sepptr++;
993 }
994 if ( i < OPT_LONG_BASE )
995 fprintf(hf,"\tGO_%s%.*s= '%c',\n",
996 opt_buf[i], (28-(int)strlen(opt_buf[i]))/8, tabs, i );
997 else if ( i == OPT_LONG_BASE )
998 fprintf(hf,"\tGO_%s%.*s= 0x%02x,\n",
999 opt_buf[i], (28-(int)strlen(opt_buf[i]))/8, tabs, i );
1000 else
1001 fprintf(hf,"\tGO_%s,\n",opt_buf[i]);
1002 }
1003
1004 fprintf(hf,"\n} enumGetOpt;\n");
1005 opt_buf['?'] = 0;
1006
1007
1008 //----- print option index
1009
1010 print_section(cf,sep1,"OptionUsed & OptionIndex");
1011
1012 fprintf(cf,"u8 OptionUsed[OPT__N_TOTAL+1] = {0};\n\n");
1013 var_ptr += snprintf(var_ptr,var_end-var_ptr,
1014 "extern u8 OptionUsed[OPT__N_TOTAL+1];\n");
1015
1016 fprintf(cf,"const u8 OptionIndex[OPT_INDEX_SIZE] = \n{\n");
1017 var_ptr += snprintf(var_ptr,var_end-var_ptr,
1018 "extern const u8 OptionIndex[OPT_INDEX_SIZE];\n");
1019
1020 for ( i = 0; i < OPT_INDEX_SIZE; )
1021 {
1022 int start = i;
1023 while ( i < OPT_INDEX_SIZE && !opt_buf[i] )
1024 i++;
1025 int len = i - start;
1026 while ( len > 0 )
1027 {
1028 const int now_len = len < 16 ? len : 16 - start % 16;
1029 fprintf(cf,"\t/* 0x%02x */\t %.*s\n",
1030 start,
1031 2*now_len + now_len/4,
1032 "0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0," );
1033 start += now_len;
1034 len -= now_len;
1035 }
1036
1037 while ( i < OPT_INDEX_SIZE && opt_buf[i] )
1038 {
1039 fprintf(cf,"\t/* 0x%02x %c */\tOPT_%s,\n",
1040 i, i > ' ' && i < 0x7f ? i : ' ', opt_buf[i]);
1041 i++;
1042 }
1043 }
1044 fprintf(cf,"};\n");
1045
1046
1047 //----- option allowed
1048
1049 if (ctrl->opt_allow_cmd)
1050 {
1051 print_section(cf,sep1,"opt_allowed_cmd_*");
1052 for ( info = ctrl->info; info < ctrl->end; info++ )
1053 {
1054 if ( !( info->type & T_DEF_CMD ) )
1055 continue;
1056
1057 fprintf(cf,"static u8 option_allowed_cmd_%s[%u] = // cmd #%u\n{",
1058 info->c_name, ctrl->n_opt_specific, info->index );
1059
1060 int i;
1061 u8 * ptr = ctrl->opt_allow_cmd + info->index * ctrl->n_opt_specific;
1062 for ( i = 0; i < ctrl->n_opt_specific; i++ )
1063 fprintf(cf, "%s%u%s",
1064 !(i%30) ? "\n " : !(i%10) ? " " : !(i%5) ? " " : "",
1065 ptr[i],
1066 i < ctrl->n_opt_specific-1 ? "," : "" );
1067
1068 fprintf(cf,"\n};\n\n");
1069 }
1070 }
1071
1072 //----- InfoCommand
1073
1074 print_links(ctrl);
1075 var_ptr += snprintf(var_ptr,var_end-var_ptr,
1076 "extern const InfoCommand_t CommandInfo[CMD__N+1];\n");
1077
1078 //----- InfoUI
1079
1080 print_section(cf,sep1,"InfoUI");
1081
1082 var_ptr += snprintf(var_ptr,var_end-var_ptr,
1083 "extern const InfoUI_t InfoUI;\n");
1084
1085 fprintf(cf,
1086 "const InfoUI_t InfoUI =\n"
1087 "{\n"
1088 "\t\"%s\",\n" // tool_name
1089 "\t%s\n" // n_cmd
1090 "\t%s\n" // cmd_tab
1091 "\tCommandInfo,\n" // cmd_info
1092 "\t%s\n" // n_opt_specific
1093 "\tOPT__N_TOTAL,\n" // n_opt_total
1094 "\tOptionInfo,\n" // opt_info
1095 "\tOptionUsed,\n" // opt_used
1096 "\tOptionIndex,\n" // opt_index
1097 "\tOptionShort,\n" // opt_short
1098 "\tOptionLong\n" // opt_long
1099 "};\n",
1100 ctrl->info->c_name,
1101 ctrl->n_cmd ? "CMD__N," : "0, // n_cmd",
1102 ctrl->n_cmd ? "CommandTab," : "0, // cmd_tab",
1103 ctrl->n_cmd ? "OPT__N_SPECIFIC," : "0, // n_opt_specific" );
1104
1105
1106 //----- external vars
1107
1108 print_section(hf,sep1,"external vars");
1109 fputs(var_buf,hf);
1110
1111
1112 //----- terminate
1113
1114 print_section(cf,sep1,"END");
1115 print_section(hf,sep1,"END");
1116 fprintf(hf,"#endif // %s\n\n",guard);
1117
1118 return ERR_OK;
1119 };
1120
1121 //
1122 ///////////////////////////////////////////////////////////////////////////////
1123 /////////////// AddTables() ///////////////
1124 ///////////////////////////////////////////////////////////////////////////////
1125
AddTables(FILE * df)1126 static void AddTables ( FILE * df )
1127 {
1128 ASSERT(df);
1129
1130 //--------------------------------------------------
1131
1132 #if 0 // [[2do]] not needed yet
1133
1134 print_section(df,sep2,"Region Info");
1135
1136 char ch;
1137 for ( ch = 'A'; ch <= 'Z'; ch++ )
1138 {
1139 const RegionInfo_t * reg = GetRegionInfo(ch);
1140 fprintf(df,"#:def_tab(\"region\",'%c',%u,%u,\"%s\",\"%s\")\n",
1141 ch, reg->reg, reg->mandatory, reg->name4, reg->name );
1142 }
1143 const RegionInfo_t * reg = GetRegionInfo(0);
1144 fprintf(df,"#:def_tab(\"region\",'',%2u,%u,\"%s\",\"%s\")\n",
1145 reg->reg, reg->mandatory, reg->name4, reg->name );
1146
1147 #endif
1148
1149 //--------------------------------------------------
1150 }
1151
1152 //
1153 ///////////////////////////////////////////////////////////////////////////////
1154 /////////////// main() ///////////////
1155 ///////////////////////////////////////////////////////////////////////////////
1156
main(int argc,char ** argv)1157 int main ( int argc, char ** argv )
1158 {
1159 SetupLib(argc,argv,"gen-ui",PROG_UNKNOWN);
1160
1161 static ccp def_null_name = "/dev/null";
1162 FILE * nf = fopen(def_null_name,"wb");
1163 if (!nf)
1164 {
1165 fprintf(stderr,"!!! Can't create file: %s\n",def_null_name);
1166 return ERR_CANT_CREATE;
1167 }
1168
1169 static ccp def_fname = "src/ui/ui.def";
1170 FILE * df = fopen(def_fname,"wb");
1171 if (!df)
1172 {
1173 fprintf(stderr,"!!! Can't create file: %s\n",def_fname);
1174 return ERR_CANT_CREATE;
1175 }
1176
1177 char fname[200];
1178 info_t * info = info_tab;
1179
1180 while ( info->type != T_END )
1181 {
1182 if ( ! ( info->type & T_DEF_TOOL ) )
1183 {
1184 fprintf(stderr,"!!! Missing T_DEF_TOOL entry.\n");
1185 return ERR_SYNTAX;
1186 }
1187
1188 control_t ctrl;
1189 memset(&ctrl,0,sizeof(ctrl));
1190 ctrl.df = nf;
1191 ctrl.opt_prefix = "";
1192 InitializeStringField(&ctrl.gopt);
1193 InitializeStringField(&ctrl.copt);
1194 InitializeStringField(&ctrl.opt_done);
1195
1196 if ( !( info->type & F_HIDDEN ) )
1197 {
1198 ctrl.df = df;
1199 snprintf(iobuf,sizeof(iobuf),"Tool '%s'",info->c_name);
1200 print_section(df,sep2,iobuf);
1201 fprintf(df,"#:def_tool( \"%s\", \\\n",info->c_name);
1202 DumpText(df,0,0,info->param,1,", \\\n");
1203 DumpText(df,0,0,info->help,1," )\n\n");
1204 }
1205
1206 snprintf(fname,sizeof(fname),"src/ui/ui-%s.c",info->c_name);
1207 ctrl.cf = fopen(fname,"wb");
1208 if (!ctrl.cf)
1209 {
1210 fprintf(stderr,"!!! Can't create file: %s\n",fname);
1211 return ERR_CANT_CREATE;
1212 }
1213
1214 snprintf(fname,sizeof(fname),"src/ui/ui-%s.h",info->c_name);
1215 ctrl.hf = fopen(fname,"wb");
1216 if (!ctrl.hf)
1217 {
1218 fprintf(stderr,"!!! Can't create file: %s\n",fname);
1219 return ERR_CANT_CREATE;
1220 }
1221
1222 ctrl.info = info++;
1223 while ( ! ( info->type & (T_END|T_DEF_TOOL)) )
1224 {
1225 if ( info->type & T_DEF_OPT )
1226 {
1227 if ( info->type & F_OPT_GLOBAL )
1228 {
1229 InsertStringField(&ctrl.gopt,info->c_name,false);
1230 ++ctrl.n_opt;
1231 //opt_index = 0 for global options
1232 }
1233 else
1234 {
1235 InsertStringField(&ctrl.copt,info->c_name,false);
1236 info->index = ++ctrl.n_opt_specific;
1237 }
1238
1239 if ( !info->help )
1240 {
1241 // copy 'param' and 'help' info from previous tool
1242 const info_t * search;
1243 for ( search = info; search >= info_tab; search-- )
1244 if ( search->type & T_DEF_OPT
1245 && search->help
1246 && !strcmp(search->c_name,info->c_name) )
1247 {
1248 info->help = search->help;
1249 if (!info->param)
1250 info->param = search->param;
1251 break;
1252 }
1253 }
1254
1255 if ( !( info->type & F_HIDDEN ) )
1256 {
1257 fprintf(ctrl.df,"#:def_opt( \"%s\", \"%s\", \"%s%s%s%s%s\", \\\n",
1258 info->c_name, info->namelist,
1259 info->type & F_OPT_COMMAND ? "C" : "",
1260 info->type & F_OPT_GLOBAL ? "G" : "",
1261 info->type & F_OPT_MULTIUSE ? "M" : "",
1262 info->type & F_OPT_PARAM ? "P" : "",
1263 info->type & F_OPT_OPTPARAM ? "O" : "" );
1264 DumpText(ctrl.df,0,0,info->param,1,", \\\n");
1265 DumpText(ctrl.df,0,0,info->help,1," )\n\n");
1266 }
1267 }
1268 else if ( info->type & T_DEF_CMD )
1269 {
1270 info->index = ++ctrl.n_cmd;
1271
1272 if ( !info->help )
1273 {
1274 // copy 'param' and 'help' info from previous tool
1275 const info_t * search = info-1;
1276 for ( search = info; search >= info_tab; search-- )
1277 if ( search->type & T_DEF_CMD
1278 && search->help
1279 && !strcmp(search->c_name,info->c_name) )
1280 {
1281 info->help = search->help;
1282 if (!info->param)
1283 info->param = search->param;
1284 break;
1285 }
1286 }
1287
1288 if ( !( info->type & F_HIDDEN ) )
1289 {
1290 fprintf(ctrl.df,"#:def_cmd( \"%s\", \"%s\", \\\n",
1291 info->c_name, info->namelist );
1292 DumpText(ctrl.df,0,0,info->param,1,", \\\n");
1293 DumpText(ctrl.df,0,0,info->help,1," )\n\n");
1294 }
1295 }
1296 else if ( info->type & T_GRP_BEG )
1297 info->index = ctrl.n_grp++; // NULL based
1298 else if ( info->type & (T_CMD_OPT|T_CMD_BEG|T_COPY_GRP|T_COPY_CMD) )
1299 {
1300 const int type = info->type & T_CMD_OPT ? T_DEF_OPT
1301 : info->type & T_COPY_GRP ? T_GRP_BEG
1302 : T_DEF_CMD;
1303
1304 const info_t * search;
1305 for ( search = ctrl.info; search < info; search++ )
1306 if ( search->type & type
1307 && !strcmp(search->c_name,info->c_name) )
1308 {
1309 //PRINT("COPY INDEX #%x: %s\n",info->type,info->c_name);
1310 info->index = search->index;
1311 break;
1312 }
1313 }
1314
1315 info++;
1316 }
1317 ctrl.end = info;
1318
1319 if (ctrl.n_cmd)
1320 ctrl.n_cmd++; // one more for CMD_NONE;
1321
1322 if (ctrl.n_opt_specific)
1323 ctrl.n_opt += ++ctrl.n_opt_specific;
1324
1325 TRACE("N: cmd=%u, grp=%u, opt=%d/%d\n",
1326 ctrl.n_cmd, ctrl.n_grp, ctrl.n_opt_specific, ctrl.n_opt );
1327 const enumError err = Generate(&ctrl);
1328
1329 fclose(ctrl.cf);
1330 fclose(ctrl.hf);
1331 ResetStringField(&ctrl.gopt);
1332 ResetStringField(&ctrl.copt);
1333 ResetStringField(&ctrl.opt_done);
1334
1335 if (err)
1336 return err;
1337 }
1338
1339 AddTables(df);
1340 print_section(df,sep2,"END");
1341 fclose(df);
1342 fclose(nf);
1343 CloseAll();
1344 return ERR_OK;
1345 }
1346
1347 //
1348 ///////////////////////////////////////////////////////////////////////////////
1349 /////////////// E N D ///////////////
1350 ///////////////////////////////////////////////////////////////////////////////
1351