diff options
Diffstat (limited to 'project/dclib/dclib-gen-ui.inc')
| -rw-r--r-- | project/dclib/dclib-gen-ui.inc | 1303 |
1 files changed, 1303 insertions, 0 deletions
diff --git a/project/dclib/dclib-gen-ui.inc b/project/dclib/dclib-gen-ui.inc new file mode 100644 index 0000000..a35f540 --- /dev/null +++ b/project/dclib/dclib-gen-ui.inc @@ -0,0 +1,1303 @@ + +/*************************************************************************** + * * + * _____ ____ * + * | __ \ / __ \ _ _ _____ * + * | | \ \ / / \_\ | | | | _ \ * + * | | \ \| | | | | | |_| | * + * | | | || | | | | | ___/ * + * | | / /| | __ | | | | _ \ * + * | |__/ / \ \__/ / | |___| | |_| | * + * |_____/ \____/ |_____|_|_____/ * + * * + * Wiimms source code library * + * * + *************************************************************************** + * * + * Copyright (c) 2012-2020 by Dirk Clemens <wiimm@wiimm.de> * + * * + *************************************************************************** + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * See file gpl-2.0.txt or http://www.gnu.org/licenses/gpl-2.0.txt * + * * + ***************************************************************************/ + +#define _GNU_SOURCE 1 + +#include <sys/types.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#include "dclib-basics.h" +#include "dclib-ui.h" + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// struct control_t /////////////// +/////////////////////////////////////////////////////////////////////////////// + +typedef struct control_t +{ + FILE * cf; // output c file + FILE * hf; // output h file + FILE * df; // output def file + + const info_t * info; // pointer to first info_t + const info_t * end; // pointer to end of info_t + + int n_cmd; // number of commands + int n_grp; // number of helper groups + int n_opt_specific; // number of cmd specific options (=OPT__N_SPECIFIC) + int n_opt; // number of options (=OPT__N_TOTAL) + int n_cmd_opt; // number of options of current command + bool need_sep; // separator needed + ccp cmd_name; // name of current command + ccp opt_prefix; // prefix for option variables, never NULL + + u8 *opt_allow_grp; // grp allowed options: field[n_grp][n_opt_specific] + u8 *opt_allow_cmd; // cmd allowed options: field[n_cmd][n_opt_specific] + + StringField_t gopt; // global options + StringField_t copt; // command specfic options + StringField_t opt_done; // option handled + +} control_t; + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// helpers /////////////// +/////////////////////////////////////////////////////////////////////////////// + +static char tabs[] = "\t\t\t\t"; + +static char sep1[] = + "////////////////////////////////////////" + "///////////////////////////////////////"; + +static char sep2[] = + "########################################" + "#######################################"; + +//----------------------------------------------------------------------------- + +static void print_section ( FILE *f, ccp sep, ccp name ) +{ + const size_t namelen = strlen(name); + const int fill = ( 49 - namelen ) /2; + const int fw = 49 - fill; + fprintf(f,"\n%.2s\f\n%s\n%.15s%*s%*s%.15s\n%s\n\n", + sep, sep, sep, fill, "", -fw, name, sep, sep ); +} + +//----------------------------------------------------------------------------- + +static void print_info_opt +( + control_t * ctrl, + const info_t * info, + const info_t * default_info, + const info_t * first_info, // NULL or first info of a list of infos + ccp cmd_name +) +{ + ASSERT(ctrl); + ASSERT(info); + + FILE * cf = ctrl->cf; + ASSERT(cf); + + if (cmd_name) + fprintf(cf,"static const InfoOption_t option_%s_%s_%s =\n", + ctrl->opt_prefix, cmd_name, info->c_name ); + + fprintf(cf," {\tOPT_%s, %s, %s, %s, %s, %s, ", + info->c_name, + info->type & F_OPT_OPTPARAM ? "true" : "false", + info->type & F_HIDDEN ? "true" : "false", + info->type & F_DEPRECATED ? "true" : "false", + info->type & F_IGNORE ? "true" : "false", + first_info && info>first_info && info[-1].type&T_SEP_OPT ? "true" : "false" ); + ccp start = ( default_info ? default_info : info ) -> namelist; + if ( *start && start[1] == '|' ) + { + fprintf(cf,"'%c', ",*start); + start += 2; + } + else + fprintf(cf,"0, "); + + ccp end = start; + while ( *end && *end != '|' ) + end++; + #ifdef TEST0 + fprintf(cf,"\"%.*s\", // hid=%x, dep=%x, sep=%x\n", + (int)(end-start), start, + info->type & F_HIDDEN, + info->type & F_DEPRECATED, + info > ctrl->info ? info[-1].type & T_SEP_OPT : 0 ); + #else + fprintf(cf,"\"%.*s\",\n", (int)(end-start), start ); + #endif + + ccp param = info->param; + ccp help = info->help; + if (default_info) + { + if (!help) + help = default_info->help; + if (!param) + param = default_info->param; + } + + if ( info->type & F_OPT_XPARAM || default_info && default_info->type & F_OPT_XPARAM ) + fprintf(cf,"\t\"%s\",\n", param && *param ? param : "param" ); + else + fprintf(cf,"\t0,\n"); + + DumpText(cf,0,0,help,-1,0,""); + fprintf(cf,"\n }%c\n\n",cmd_name ? ';' : ',' ); +} + +//----------------------------------------------------------------------------- + +static void print_opt +( + control_t * ctrl, + const info_t * info, + const info_t * first_info // NULL or first info of a list of infos +) +{ + ASSERT(ctrl); + ASSERT(info); + + ctrl->n_opt++; + print_info_opt(ctrl,info,0,first_info,0); + fprintf( ctrl->hf, "\tOPT_%s,\n", info->c_name ); +}; + +//----------------------------------------------------------------------------- + +static void print_opt_link ( control_t * ctrl, const info_t * info ) +{ + ASSERT(ctrl); + ASSERT(ctrl->cf); + ASSERT(ctrl->opt_prefix); + ASSERT(info); + + if (!InsertStringField(&ctrl->opt_done,info->c_name,false)) + return; + + if ( ctrl->need_sep ) + { + ctrl->need_sep = false; + if ( ctrl->n_cmd_opt ) + fprintf(ctrl->cf,"\n\tOptionInfo + OPT_NONE, // separator\n\n" ); + } + + if ( !info->help || info->type & T_DEF_OPT ) + fprintf(ctrl->cf,"\tOptionInfo + OPT_%s,\n", info->c_name ); + else + fprintf(ctrl->cf,"\t&option_%s_%s,\n", ctrl->opt_prefix, info->c_name ); + + if (ctrl->cmd_name) + { + fprintf(ctrl->df,"#:def_cmd_opt( \"%s\", \"%s\", \\\n", + ctrl->cmd_name, info->c_name ); + DumpText(ctrl->df,0,0,info->param,-1,1,", \\\n"); + DumpText(ctrl->df,0,0,info->help,-1,1," )\n\n"); + } + + ctrl->n_cmd_opt++; +} + +//----------------------------------------------------------------------------- + +static const info_t * print_links_iterator + ( control_t * ctrl, const info_t * info, ccp prefix ); + +//----------------------------------------------------------------------------- + +static void print_cmd_links ( control_t * ctrl, const info_t * ref ) +{ + ASSERT(ctrl); + ASSERT(ref); + + const info_t * info; + for ( info = ctrl->info; info < ctrl->end; info++ ) + if ( info->type & T_CMD_BEG && !strcmp(info->c_name,ref->c_name) ) + { + print_links_iterator(ctrl,info,"cmd"); + break; + } +} + +//----------------------------------------------------------------------------- + +static void print_grp_links ( control_t * ctrl, const info_t * ref ) +{ + ASSERT(ctrl); + ASSERT(ref); + + const info_t * info; + for ( info = ctrl->info; info < ctrl->end; info++ ) + if ( info->type & T_GRP_BEG && !strcmp(info->c_name,ref->c_name) ) + { + print_links_iterator(ctrl,info,"grp"); + break; + } +} + +//----------------------------------------------------------------------------- + +static const info_t * print_links_iterator + ( control_t * ctrl, const info_t * info, ccp prefix ) +{ + ASSERT(ctrl); + ASSERT(info); + + ccp saved_prefix = ctrl->opt_prefix; + char buf[100]; + if (prefix) + { + snprintf(buf,sizeof(buf),"%s_%s",prefix,info->c_name); + ctrl->opt_prefix = buf; + }; + + for ( info++; info < ctrl->end && !(info->type & (T_CMD_BEG|T_GRP_BEG) ); info++ ) + { + if ( info->type & F_HIDDEN ) + { + // ignored -> do nothing + } + else if ( info->type & T_SEP_OPT ) + ctrl->need_sep = true; + else if ( info->type & (F_OPT_GLOBAL|T_CMD_OPT) ) + print_opt_link(ctrl,info); + else if ( info->type & T_COPY_CMD ) + print_cmd_links(ctrl,info); + else if ( info->type & T_COPY_GRP ) + print_grp_links(ctrl,info); + } + + ctrl->opt_prefix = saved_prefix; + return info; +} + +//----------------------------------------------------------------------------- + +static void dump_help ( const info_t * info_cmd ) +{ + char * temp_param = iobuf; + char * temp_help = iobuf + sizeof(iobuf)/8; + char * temp_xhelp = iobuf + sizeof(iobuf)/4; + + DumpText(0,temp_param,iobuf+sizeof(iobuf),info_cmd->param,-1,0,""); + ccp ff = info_cmd->help ? strchr(info_cmd->help,'\f') : 0; + if (ff) + { + DumpText(0,temp_help,iobuf+sizeof(iobuf),info_cmd->help,ff-info_cmd->help,0,""); + DumpText(0,temp_xhelp,iobuf+sizeof(iobuf),ff+1,-1,0,""); + } + else + { + DumpText(0,temp_help,iobuf+sizeof(iobuf),info_cmd->help,-1,0,""); + StringCopyE(temp_xhelp,iobuf+sizeof(iobuf),"\t0"); + } +} + +//----------------------------------------------------------------------------- + +static void print_links ( control_t * ctrl ) +{ + ASSERT(ctrl); + FILE * cf = ctrl->cf; + ASSERT(cf); + + print_section(cf,sep1,"InfoOption tabs"); + + char * temp_param = iobuf; + char * temp_help = iobuf + sizeof(iobuf)/8; + char * temp_xhelp = iobuf + sizeof(iobuf)/4; + char * sum_beg = iobuf + sizeof(iobuf)/2; + char * sum_end = iobuf + sizeof(iobuf); + char * sum = sum_beg; + + const info_t * info_cmd = ctrl->info; + ASSERT ( info_cmd->type & T_DEF_TOOL ); + fprintf(cf,"static const InfoOption_t * option_tab_tool[] =\n{\n"); + + ctrl->n_cmd_opt = 0; + ctrl->need_sep = false; + + print_links_iterator(ctrl,info_cmd,"def"); + fprintf(cf,"\n\t0\n};\n\n"); + + dump_help(info_cmd); + sum = snprintfE(sum,sum_end, + " {\t0,\n" // id + "\tfalse,\n" // hidden + "\tfalse,\n" // deprecated + "\tfalse,\n" // separator + "\t\"%s\",\n" // name1 + "\t0,\n" // name2 + "%s,\n" // param + "%s,\n" // help + "%s,\n" // xhelp + "\t%u,\n" // n_opt + "\toption_tab_tool,\n" // opt + "\t0\n" // opt_allowed + " },\n\n" + ,info_cmd->c_name + ,temp_param + ,temp_help + ,temp_xhelp + ,ctrl->n_cmd_opt + ); + + bool separator = false; + for ( info_cmd++; info_cmd < ctrl->end; info_cmd++ ) + { + if ( info_cmd->type & T_SEP_CMD ) + separator = true; + //if ( !( info_cmd->type & T_DEF_CMD ) || info_cmd->type & F_HIDDEN ) + if ( !( info_cmd->type & T_DEF_CMD ) ) + continue; + + fprintf(cf,"static const InfoOption_t * option_tab_cmd_%s[] =\n{\n", + info_cmd->c_name); + + ctrl->n_cmd_opt = 0; + ctrl->need_sep = false; + ctrl->cmd_name = info_cmd->c_name; + ResetStringField(&ctrl->opt_done); + + const info_t * info; + for ( info = info_cmd; info < ctrl->end; info++ ) + if ( info->type & T_CMD_BEG && !strcmp(info->c_name,info_cmd->c_name) ) + { + print_links_iterator(ctrl,info,"cmd"); + break; + } + fprintf(cf,"\n\t0\n};\n\n"); + + ccp name1 = info_cmd->namelist, ptr = name1; + while ( *ptr && *ptr != '|' ) + ptr++; + const int len1 = ptr - name1; + char name2[100] = "0"; + if ( *ptr == '|' ) + { + ccp n2 = ++ptr; + while ( *ptr && *ptr != '|' ) + ptr++; + if ( ptr > n2 ) + snprintf(name2,sizeof(name2),"\"%.*s\"",(int)(ptr-n2),n2); + } + + dump_help(info_cmd); + sum = snprintfE(sum,sum_end, + " {\tCMD_%s,\n" // id + "\t%s,\n" // hidden + "\t%s,\n" // deprecated + "\t%s,\n" // separator + "\t\"%.*s\",\n" // name1 + "\t%s,\n" // name2 + "%s,\n" // param + "%s,\n" // help + "%s,\n" // xhelp + "\t%u,\n" // n_opt + "\toption_tab_cmd_%s,\n" // opt + "\toption_allowed_cmd_%s\n" // opt_allowed + " },\n\n" + ,info_cmd->c_name + ,info_cmd->type & F_HIDDEN ? "true" : "false" + ,info_cmd->type & F_DEPRECATED ? "true" : "false" + ,separator ? "true" : "false" + ,len1 ,name1 + ,name2 + ,temp_param + ,temp_help + ,temp_xhelp + ,ctrl->n_cmd_opt + ,info_cmd->c_name + ,info_cmd->c_name + ); + separator = false; + } + + print_section(cf,sep1,"InfoCommand"); + fprintf(cf,"static const InfoCommand_t CommandInfo[CMD__N+1] =\n{\n"); + fputs(sum_beg,cf); + fprintf(cf," {0,0,0,0,0,0,0,0,0,0,0,0}\n};\n"); +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// Generate() /////////////// +/////////////////////////////////////////////////////////////////////////////// + +static char var_buf[10000]; + +//----------------------------------------------------------------------------- + +static void CheckUsedName ( StringField_t *list, ccp name, uint len, ccp title ) +{ + //printf("CHECK: |%.*s|\n",len,name); + ccp key = MEMDUP(name,len); + if (!InsertStringField(list,key,len)) + fprintf(stderr,"!UI-WARNING: %s already defined: %.*s\n", title, len, name ); +} + +//----------------------------------------------------------------------------- + +static enumError Generate ( control_t * ctrl ) +{ + ASSERT(ctrl); + ASSERT(ctrl->info); + + FILE * cf = ctrl->cf; + FILE * hf = ctrl->hf; + ASSERT(cf); + ASSERT(hf); + + FREE(ctrl->opt_allow_grp); + FREE(ctrl->opt_allow_cmd); + ctrl->opt_allow_grp = ctrl->opt_allow_cmd = 0; + + const info_t *info; + StringField_t used_name; + InitializeStringField(&used_name); + + + //----- ui header + + fprintf(cf,text_ui_head); + fprintf(hf,text_ui_head); + + + //----- setup guard + + char guard[100]; + snprintf(guard,sizeof(guard),"SZS_UI_%s_h",ctrl->info->c_name); + char * ptr; + for ( ptr = guard; *ptr; ptr++ ) + *ptr = *ptr == '-' ? '_' : toupper((int)*ptr); + fprintf(hf,"\n#ifndef %s\n#define %s\n",guard,guard); + + + //----- header + + ASSERT( ctrl->info->type & T_DEF_TOOL ); + ccp tool_name = ctrl->info->c_name; + + fprintf(cf,"#include <getopt.h>\n"); + fprintf(cf,"#include \"ui-%s.h\"\n",tool_name); + + fprintf(hf,"#include \"dclib-basics.h\"\n"); + fprintf(hf,"#include \"dclib-ui.h\"\n"); + + + //----- print enum enumOptions & OptionInfo[] + + print_section(cf,sep1,"OptionInfo[]"); + print_section(hf,sep1,"enum enumOptions"); + + char * var_ptr = var_buf; + char * var_end = var_buf + sizeof(var_buf); + var_ptr = snprintfE(var_ptr,var_end, + "//extern const InfoOption_t OptionInfo[OPT__N_TOTAL+1];\n"); + + fprintf(cf, + "static const InfoOption_t OptionInfo[OPT__N_TOTAL+1] =\n" + "{\n" + " {0,0,0,0,0,0,0,0,0,0}, // OPT_NONE,\n" + "\n" + ); + + fprintf(hf, + "typedef enum enumOptions\n" + "{\n" + "\tOPT_NONE,\n" + "\n" + ); + + ctrl->n_opt = 1; + ctrl->n_opt_specific = 0; + if ( ctrl->n_cmd ) + { + fprintf(cf," //----- command specific options -----\n\n"); + fprintf(hf,"\t//----- command specific options -----\n\n"); + + const info_t *first_info = 0; + for ( info = ctrl->info; info < ctrl->end; info++ ) + if ( info->type & F_OPT_COMMAND ) + { + if (!first_info) + first_info = info; + print_opt(ctrl,info,first_info); + } + + ctrl->n_opt_specific = ctrl->n_opt; + + fprintf(cf, + " {0,0,0,0,0,0,0,0,0,0}, // OPT__N_SPECIFIC == %d\n\n" + " //----- global options -----\n\n", + ctrl->n_opt_specific ); + + fprintf(hf, + "\n\tOPT__N_SPECIFIC, // == %d\n\n" + "\t//----- global options -----\n\n", + ctrl->n_opt_specific ); + } + + const info_t *first_info = 0; + for ( info = ctrl->info; info < ctrl->end; info++ ) + if ( info->type & F_OPT_GLOBAL ) + { + if (!first_info) + first_info = info; + print_opt(ctrl,info,first_info); + } + + fprintf(cf, + " {0,0,0,0,0,0,0,0,0,0} // OPT__N_TOTAL == %d\n\n" + "};\n" + ,ctrl->n_opt ); + + fprintf(hf, + "\n\tOPT__N_TOTAL // == %d\n\n" + "} enumOptions;\n" + ,ctrl->n_opt ); + + if (ctrl->n_opt_specific) + { + noTRACE("opt_allowed = ( %2u + %2u ) * %2u\n", + ctrl->n_grp, ctrl->n_cmd, ctrl->n_opt_specific ); + if (ctrl->n_grp) + { + ctrl->opt_allow_grp = CALLOC(ctrl->n_grp,ctrl->n_opt_specific); + } + ctrl->opt_allow_cmd = CALLOC(ctrl->n_cmd,ctrl->n_opt_specific); + } + + + //----- print alternate option infos + + bool done = false; + const info_t * last_cmd = ctrl->info; + ctrl->opt_prefix = "def"; + for ( info = ctrl->info; info < ctrl->end; info++ ) + { + if ( info->type & T_CMD_BEG ) + { + ctrl->opt_prefix = "cmd"; + last_cmd = info; + } + else if ( info->type & T_GRP_BEG ) + { + ctrl->opt_prefix = "grp"; + last_cmd = info; + } + else if ( info->type & T_CMD_OPT && info->help && *info->help ) + { + if (!done) + { + print_section(cf,sep1,"alternate option infos"); + done = true; + } + + const info_t * info0; + for ( info0 = ctrl->info; info0 < info; info0++ ) + if ( info0->type & T_DEF_OPT && !strcmp(info->c_name,info0->c_name) ) + { + print_info_opt(ctrl,info,info0,0,last_cmd->c_name); + break; + } + } + } + + //----- print enum enumOptionsBit + + if ( ctrl->n_cmd ) + { + print_section(hf,sep1,"enum enumOptionsBit"); + + fprintf(hf, + "//\t***** only for verification *****\n" + "\n" + "//typedef enum enumOptionsBit\n" + "//{\n" + "//\t//----- command specific options -----\n" + "//\n" + ); + + for ( info = ctrl->info; info < ctrl->end; info++ ) + if ( info->type & F_OPT_COMMAND ) + fprintf(hf,"//\tOB_%s%.*s= 1llu << OPT_%s,\n", + info->c_name, + ( 28 - (int)strlen(info->c_name) ) / 8, tabs, + info->c_name ); + + fprintf(hf,"//\n//\t//----- group & command options -----\n"); + + for ( info = ctrl->info; info < ctrl->end; ) + { + ccp cmd_name; + u8 * opt_allow = 0; + if ( info->type & T_CMD_BEG ) + { + cmd_name = info->c_name; + fprintf(hf,"//\n//\tOB_CMD_%s%.*s=", + info->c_name, + ( 24 - (int)strlen(info->c_name) ) / 8, tabs ); + if (ctrl->opt_allow_cmd) + { + //PRINT("SELECT ALLOW CMD %u/%s\n",info->index,info->c_name); + opt_allow = ctrl->opt_allow_cmd + info->index * ctrl->n_opt_specific; + } + } + else if ( info->type & T_GRP_BEG ) + { + cmd_name = info->c_name; + fprintf(hf,"//\n//\tOB_GRP_%s%.*s=", + info->c_name, + ( 24 - (int)strlen(info->c_name) ) / 8, tabs ); + if (ctrl->opt_allow_grp) + { + //PRINT("SELECT ALLOW GRP %u/%s\n",info->index,info->c_name); + opt_allow = ctrl->opt_allow_grp + info->index * ctrl->n_opt_specific; + } + } + else + { + info++; + continue; + } + + info++; + char * dest = iobuf; + while ( info < ctrl->end ) + { + if ( info->type & T_ALL_OPT ) + { + dest += sprintf(dest,"\n//\t\t\t\t| ~(u64)0"); + if (opt_allow) + { + //PRINT("ALLOW ALL\n"); + memset(opt_allow,1,ctrl->n_opt_specific); + } + } + else if ( info->type & T_COPY_CMD ) + { + dest += sprintf(dest,"\n//\t\t\t\t| OB_CMD_%s",info->c_name); + if (opt_allow) + { + //PRINT("OR CMD %u/%s\n",info->index,info->c_name); + DASSERT(ctrl->opt_allow_cmd); + u8 * src = ctrl->opt_allow_cmd + info->index * ctrl->n_opt_specific; + u8 * dest = opt_allow; + int count = ctrl->n_opt_specific; + while ( count-- > 0 ) + *dest++ |= *src++; + } + } + else if ( info->type & T_COPY_GRP ) + { + dest += sprintf(dest,"\n//\t\t\t\t| OB_GRP_%s",info->c_name); + if ( opt_allow && ctrl->opt_allow_grp ) + { + //PRINT("OR GRP %u/%s\n",info->index,info->c_name); + u8 * src = ctrl->opt_allow_grp + info->index * ctrl->n_opt_specific; + u8 * dest = opt_allow; + int count = ctrl->n_opt_specific; + while ( count-- > 0 ) + *dest++ |= *src++; + } + } + else if ( info->type & T_CMD_OPT ) + { + if (FindStringField(&ctrl->copt,info->c_name)) + { + dest += sprintf(dest,"\n//\t\t\t\t| OB_%s",info->c_name); + if ( opt_allow && info->index ) + { + //PRINT("ALLOW OPT %u/%s\n",info->index,info->c_name); + opt_allow[info->index] = 1; + } + } + else if (!FindStringField(&ctrl->gopt,info->c_name)) + ERROR0(ERR_SEMANTIC,"Option not defined: %s %s --%s", + tool_name, cmd_name, info->c_name ); + } + else if ( info->type & (T_CMD_BEG|T_GRP_BEG) ) + break; + ASSERT( dest < iobuf + sizeof(iobuf) ); + info++; + } + if ( dest == iobuf ) + fprintf(hf," 0,\n"); + else + fprintf(hf,"%s,\n",iobuf+8); + } + + fprintf(hf,"//\n//} enumOptionsBit;\n"); + } + + + //----- print enum enumCommands & CommandTab[] + + print_section(hf,sep1,"enum enumCommands"); + fprintf(hf, + "typedef enum enumCommands\n" + "{\n" + "\tCMD__NONE," + ); + + if ( ctrl->n_cmd ) + { + print_section(cf,sep1,"CommandTab[]"); + fputs("\n\n",hf); + + var_ptr = snprintfE(var_ptr,var_end, + "//extern const KeywordTab_t CommandTab[];\n"); + + fprintf(cf, + "static const KeywordTab_t CommandTab[] =\n" + "{\n" + ); + + for ( info = ctrl->info; info < ctrl->end; info++ ) + if ( info->type & T_DEF_CMD ) + { + fprintf( hf, "\tCMD_%s,\n",info->c_name); + ccp ptr = info->namelist; + while (*ptr) + { + ccp n1 = ptr; + while ( *ptr && *ptr != '|' ) + ptr++; + const int l1 = ptr - n1; + CheckUsedName(&used_name,n1,l1,"Command"); + while ( *ptr == '|' ) + ptr++; + if (*ptr) + { + ccp n2 = ptr; + while ( *ptr && *ptr != '|' ) + ptr++; + const int l2 = ptr - n2; + CheckUsedName(&used_name,n2,l2,"Command"); + + fprintf(cf, + " { CMD_%s,%.*s\"%.*s\",%.*s\"%.*s\",%.*s0 },\n", + info->c_name, (20-(int)strlen(info->c_name))/8, tabs, + l1, n1, (20-l1)/8, tabs, + l2, n2, (20-l2)/8, tabs ); + + while ( *ptr == '|' ) + ptr++; + } + else + fprintf(cf, " { CMD_%s,%.*s\"%.*s\",%.*s0,\t\t0 },\n", + info->c_name, (20-(int)strlen(info->c_name))/8, tabs, + l1, n1, (20-l1)/8, tabs ); + } + } + else if ( info->type == T_SEP_CMD ) + fprintf(hf,"\n"); + + fprintf(cf, + "\n { CMD__N,0,0,0 }\n" + "};\n" + ); + + ResetStringField(&used_name); + } + + fprintf(hf, + "\n\tCMD__N // == %u\n\n" + "} enumCommands;\n" + , ctrl->n_cmd ); + + + //----- print options + + print_section(cf,sep1,"OptionShort & OptionLong"); + + char * dest = iobuf; + for ( info = ctrl->info; info < ctrl->end; info++ ) + if ( info->type & T_DEF_OPT && info->namelist[1] == '|' ) + { + CheckUsedName(&used_name,info->namelist,1,"Short option"); + *dest++ = info->namelist[0]; + if ( ( info->type & (F_OPT_OPTPARAM|F_OPT_PARAM) ) == F_OPT_PARAM ) + *dest++ = ':'; + } + *dest = 0; + fprintf(cf,"static const char OptionShort[] = \"%s\";\n\n",iobuf); + var_ptr = snprintfE(var_ptr,var_end, + "//extern const char OptionShort[];\n"); + + ccp opt_buf[UIOPT_INDEX_SIZE]; + memset(opt_buf,0,sizeof(opt_buf)); + int getopt_idx = UIOPT_LONG_BASE; + ResetStringField(&used_name); + + fprintf(cf,"static const struct option OptionLong[] =\n{\n"); + var_ptr = snprintfE(var_ptr,var_end, + "//extern const struct option OptionLong[];\n"); + + for ( info = ctrl->info; info < ctrl->end; info++ ) + if ( info->type & T_DEF_OPT ) + { + ccp ptr = info->namelist; + const int pmode = (info->type & F_OPT_OPTPARAM) + ? 2 + : (info->type & F_OPT_PARAM) + ? 1 + : 0; + + if ( info->namelist[1] == '|' ) + { + snprintf(iobuf,sizeof(iobuf),"%d, 0, '%c'", + pmode, info->namelist[0] ); + ptr += 2; + opt_buf[(u8)(info->namelist[0])] = info->c_name; + } + else + { + snprintf(iobuf,sizeof(iobuf),"%d, 0, GO_%s", + pmode, info->c_name ); + ASSERT_MSG( getopt_idx < UIOPT_INDEX_SIZE, + "getopt_idx >= UIOPT_INDEX_SIZE [ 0x%x >= 0x%x ]\n", + getopt_idx, UIOPT_INDEX_SIZE ); + if ( getopt_idx < UIOPT_INDEX_SIZE ) + opt_buf[getopt_idx++] = info->c_name; + } + + int indent = 0; + while (*ptr) + { + ccp start = ptr; + while ( *ptr && *ptr != '|' ) + ptr++; + const int len = ptr - start; + if (len) + { + CheckUsedName(&used_name,start,len,"Long option"); + fprintf(cf,"\t%s{ \"%.*s\",%.*s%s },\n", + indent ? " " : "", len, start, (26-len-indent)/8, tabs, iobuf ); + indent = 1; + } + if (*ptr) + ptr++; + } + } + fprintf(cf,"\n\t{0,0,0,0}\n};\n"); + + + //----- print enumGetOpt + + print_section(hf,sep1,"enumGetOpt"); + fprintf(hf,"typedef enum enumGetOpt\n{"); + + // add '?' temporary; + ASSERT(!opt_buf['?']); + opt_buf['?'] = "_ERR"; + + static const int septab[] = { 0, '0', '9'+1, '?', '?'+1, + 'A', 'Z'+1, 'a', 'z'+1, + UIOPT_LONG_BASE, UIOPT_INDEX_SIZE }; + const int * sepptr = septab; + int i; + for ( i = 0; i < UIOPT_INDEX_SIZE; i++ ) + if ( opt_buf[i] ) + { + if ( i >= *sepptr ) + { + fputc('\n',hf); + while ( i >= *sepptr ) + sepptr++; + } + if ( i < UIOPT_LONG_BASE ) + fprintf(hf,"\tGO_%s%.*s= '%c',\n", + opt_buf[i], (28-(int)strlen(opt_buf[i]))/8, tabs, i ); + else if ( i == UIOPT_LONG_BASE ) + fprintf(hf,"\tGO_%s%.*s= 0x%02x,\n", + opt_buf[i], (28-(int)strlen(opt_buf[i]))/8, tabs, i ); + else + fprintf(hf,"\tGO_%s,\n",opt_buf[i]); + } + + fprintf(hf,"\n} enumGetOpt;\n"); + opt_buf['?'] = 0; + + + //----- print option index + + print_section(cf,sep1,"OptionUsed & OptionIndex"); + + fprintf(cf,"static u8 OptionUsed[OPT__N_TOTAL+1] = {0};\n\n"); + var_ptr = snprintfE(var_ptr,var_end, + "//extern u8 OptionUsed[OPT__N_TOTAL+1];\n"); + + fprintf(cf,"static const OptionIndex_t OptionIndex[UIOPT_INDEX_SIZE] =\n{\n"); + var_ptr = snprintfE(var_ptr,var_end, + "//extern const OptionIndex_t OptionIndex[UIOPT_INDEX_SIZE];\n" + "//UIOPT_INDEX_SIZE := 0x%x = %u\n", + UIOPT_INDEX_SIZE, UIOPT_INDEX_SIZE ); + + for ( i = 0; i < UIOPT_INDEX_SIZE; ) + { + int start = i; + while ( i < UIOPT_INDEX_SIZE && !opt_buf[i] ) + i++; + int len = i - start; + while ( len > 0 ) + { + const int now_len = len < 16 ? len : 16 - start % 16; + fprintf(cf,"\t/* 0x%0*x */\t %.*s\n", + UIOPT_INDEX_FW, + start, + 2*now_len + now_len/4, + "0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0," ); + start += now_len; + len -= now_len; + } + + while ( i < UIOPT_INDEX_SIZE && opt_buf[i] ) + { + fprintf(cf,"\t/* 0x%0*x %c */\tOPT_%s,\n", + UIOPT_INDEX_FW, i, i > ' ' && i < 0x7f ? i : ' ', opt_buf[i]); + i++; + } + } + fprintf(cf,"};\n"); + + + //----- option allowed + + if (ctrl->opt_allow_cmd) + { + print_section(cf,sep1,"opt_allowed_cmd_*"); + for ( info = ctrl->info; info < ctrl->end; info++ ) + { + if ( !( info->type & T_DEF_CMD ) ) + continue; + + fprintf(cf,"static u8 option_allowed_cmd_%s[%u] = // cmd #%u\n{", + info->c_name, ctrl->n_opt_specific, info->index ); + + int i; + u8 * ptr = ctrl->opt_allow_cmd + info->index * ctrl->n_opt_specific; + for ( i = 0; i < ctrl->n_opt_specific; i++ ) + fprintf(cf, "%s%u%s", + !(i%30) ? "\n " : !(i%10) ? " " : !(i%5) ? " " : "", + ptr[i], + i < ctrl->n_opt_specific-1 ? "," : "" ); + + fprintf(cf,"\n};\n\n"); + } + } + + //----- InfoCommand + + print_links(ctrl); + var_ptr = snprintfE(var_ptr,var_end, + "//extern const InfoCommand_t CommandInfo[CMD__N+1];\n"); + + //----- InfoUI + + char xname[100]; + { + StringCopyS(xname,sizeof(xname),ctrl->info->c_name); + char *ptr; + for ( ptr = xname; *ptr; ptr++ ) + if (!isalnum((int)*ptr)) + *ptr = '_'; + } + + print_section(cf,sep1,"InfoUI"); + + var_ptr = snprintfE(var_ptr,var_end, + "extern const InfoUI_t InfoUI_%s;\n", + xname ); + + fprintf(cf, + "const InfoUI_t InfoUI_%s =\n" + "{\n" + "\t\"%s\",\n" // tool_name + "\t%s\n" // n_cmd + "\t%s\n" // cmd_tab + "\tCommandInfo,\n" // cmd_info + "\t%s\n" // n_opt_specific + "\tOPT__N_TOTAL,\n" // n_opt_total + "\tOptionInfo,\n" // opt_info + "\tOptionUsed,\n" // opt_used + "\tOptionIndex,\n" // opt_index + "\tOptionShort,\n" // opt_short + "\tOptionLong\n" // opt_long + "};\n", + xname, + ctrl->info->c_name, + ctrl->n_cmd ? "CMD__N," : "0, // n_cmd", + ctrl->n_cmd ? "CommandTab," : "0, // cmd_tab", + ctrl->n_cmd ? "OPT__N_SPECIFIC," : "0, // n_opt_specific" ); + + + //----- external vars + + print_section(hf,sep1,"external vars"); + fputs(var_buf,hf); + + + //----- terminate + + print_section(cf,sep1,"END"); + print_section(hf,sep1,"END"); + fprintf(hf,"#endif // %s\n\n",guard); + ResetStringField(&used_name); + + return ERR_OK; +}; + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// dummy functions /////////////// +/////////////////////////////////////////////////////////////////////////////// + +static void print_title ( FILE * f ) {} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// AddTables() /////////////// +/////////////////////////////////////////////////////////////////////////////// + +static void AddTables ( FILE * df ) +{ + DASSERT(df); +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// main() /////////////// +/////////////////////////////////////////////////////////////////////////////// + +int ui_main ( int argc, char ** argv ) +{ + static ccp def_null_name = "/dev/null"; + FILE * nf = fopen(def_null_name,"wb"); + if (!nf) + { + fprintf(stderr,"!!! Can't create file: %s\n",def_null_name); + return ERR_CANT_CREATE; + } + + static ccp def_fname = "src/ui/ui.def"; + FILE * df = fopen(def_fname,"wb"); + if (!df) + { + fprintf(stderr,"!!! Can't create file: %s\n",def_fname); + return ERR_CANT_CREATE; + } + + char fname_c[200], fname_c_temp[210]; + char fname_h[200], fname_h_temp[210]; + info_t * info = info_tab; + + while ( info->type != T_END ) + { + if ( ! ( info->type & T_DEF_TOOL ) ) + { + fprintf(stderr,"!!! Missing T_DEF_TOOL entry.\n"); + return ERR_SYNTAX; + } + + control_t ctrl; + memset(&ctrl,0,sizeof(ctrl)); + ctrl.df = nf; + ctrl.opt_prefix = ""; + InitializeStringField(&ctrl.gopt); + InitializeStringField(&ctrl.copt); + InitializeStringField(&ctrl.opt_done); + + if ( !( info->type & F_HIDDEN ) ) + { + ctrl.df = df; + snprintf(iobuf,sizeof(iobuf),"Tool '%s'",info->c_name); + print_section(df,sep2,iobuf); + fprintf(df,"#:def_tool( \"%s\", \\\n",info->c_name); + DumpText(df,0,0,info->param,-1,1,", \\\n"); + DumpText(df,0,0,info->help,-1,1," )\n\n"); + } + + snprintf(fname_c,sizeof(fname_c),"src/ui/ui-%s.c",info->c_name); + StringCat2S(fname_c_temp,sizeof(fname_c_temp),fname_c,".temp"); + ctrl.cf = fopen(fname_c_temp,"wb"); + if (!ctrl.cf) + { + fprintf(stderr,"!!! Can't create file: %s\n",fname_c_temp); + return ERR_CANT_CREATE; + } + + snprintf(fname_h,sizeof(fname_h),"src/ui/ui-%s.h",info->c_name); + StringCat2S(fname_h_temp,sizeof(fname_h_temp),fname_h,".temp"); + ctrl.hf = fopen(fname_h_temp,"wb"); + if (!ctrl.hf) + { + fclose(ctrl.cf); + fprintf(stderr,"!!! Can't create file: %s\n",fname_h_temp); + return ERR_CANT_CREATE; + } + + ctrl.info = info++; + while ( ! ( info->type & (T_END|T_DEF_TOOL)) ) + { + if ( info->type & T_DEF_OPT ) + { + if ( info->type & F_OPT_GLOBAL ) + { + InsertStringField(&ctrl.gopt,info->c_name,false); + ++ctrl.n_opt; + //opt_index = 0 for global options + } + else + { + InsertStringField(&ctrl.copt,info->c_name,false); + info->index = ++ctrl.n_opt_specific; + } + + if ( !info->help ) + { + // copy 'param' and 'help' info from previous tool + const info_t * search; + for ( search = info; search >= info_tab; search-- ) + if ( search->type & T_DEF_OPT + && search->help + && !strcmp(search->c_name,info->c_name) ) + { + info->help = search->help; + if (!info->param) + info->param = search->param; + break; + } + } + + if ( !( info->type & F_HIDDEN ) ) + { + fprintf(ctrl.df,"#:def_opt( \"%s\", \"%s\", \"%s%s%s%s%s\", \\\n", + info->c_name, info->namelist, + info->type & F_OPT_COMMAND ? "C" : "", + info->type & F_OPT_GLOBAL ? "G" : "", + info->type & F_OPT_MULTIUSE ? "M" : "", + info->type & F_OPT_PARAM ? "P" : "", + info->type & F_OPT_OPTPARAM ? "O" : "" ); + DumpText(ctrl.df,0,0,info->param,-1,1,", \\\n"); + DumpText(ctrl.df,0,0,info->help,-1,1," )\n\n"); + } + } + else if ( info->type & T_DEF_CMD ) + { + info->index = ++ctrl.n_cmd; + + if ( !info->help ) + { + // copy 'param' and 'help' info from previous tool + const info_t * search = info-1; + for ( search = info; search >= info_tab; search-- ) + if ( search->type & T_DEF_CMD + && search->help + && !strcmp(search->c_name,info->c_name) ) + { + info->help = search->help; + if (!info->param) + info->param = search->param; + break; + } + } + + if ( !( info->type & F_HIDDEN ) ) + { + fprintf(ctrl.df,"#:def_cmd( \"%s\", \"%s\", \\\n", + info->c_name, info->namelist ); + DumpText(ctrl.df,0,0,info->param,-1,1,", \\\n"); + + ccp ff = info->help ? strchr(info->help,'\f') : 0; + if (ff) + { + DumpText(ctrl.df,0,0,info->help,ff-info->help,1,", \\\n"); + DumpText(ctrl.df,0,0,ff+1,-1,1," )\n\n"); + } + else + DumpText(ctrl.df,0,0,info->help,-1,1," )\n\n"); + } + } + else if ( info->type & T_GRP_BEG ) + info->index = ctrl.n_grp++; // NULL based + else if ( info->type & (T_CMD_OPT|T_CMD_BEG|T_COPY_GRP|T_COPY_CMD) ) + { + const int type = info->type & T_CMD_OPT ? T_DEF_OPT + : info->type & T_COPY_GRP ? T_GRP_BEG + : T_DEF_CMD; + + const info_t * search; + for ( search = ctrl.info; search < info; search++ ) + if ( search->type & type + && !strcmp(search->c_name,info->c_name) ) + { + //PRINT("COPY INDEX #%x: %s\n",info->type,info->c_name); + info->index = search->index; + break; + } + } + + info++; + } + ctrl.end = info; + + if (ctrl.n_cmd) + ctrl.n_cmd++; // one more for CMD_NONE; + + if (ctrl.n_opt_specific) + ctrl.n_opt += ++ctrl.n_opt_specific; + + TRACE("N: cmd=%u, grp=%u, opt=%d/%d\n", + ctrl.n_cmd, ctrl.n_grp, ctrl.n_opt_specific, ctrl.n_opt ); + const enumError err = Generate(&ctrl); + + fclose(ctrl.cf); + fclose(ctrl.hf); + rename(fname_c_temp,fname_c); + rename(fname_h_temp,fname_h); + + ResetStringField(&ctrl.gopt); + ResetStringField(&ctrl.copt); + ResetStringField(&ctrl.opt_done); + + if (err) + return err; + } + + AddTables(df); + print_section(df,sep2,"END"); + fclose(df); + fclose(nf); + return ERR_OK; +} + +// +/////////////////////////////////////////////////////////////////////////////// +/////////////// E N D /////////////// +/////////////////////////////////////////////////////////////////////////////// |
