Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: nucleo_ucmd_helloworld
ucCmdLineOpt.c
00001 #include <string.h> 00002 #include "ucmd_internal.h" 00003 00004 ucMemoryManager_INIT(ucCmdLineOpt, ucCmdLineOpt_COUNT); 00005 00006 static ucCmdLineOpt *create_cmd_line_opt(void) { 00007 return ucMemoryManager_create(); 00008 } 00009 00010 static const char *add_opt_to_usage_response(ucOpt *opt, ucCmdLine *cmd, const char *response) { 00011 static const char *required_format = "%s %s"; 00012 static const char *optional_format = "%s [%s]"; 00013 return ucCmdLine_format_response( 00014 cmd, 00015 ucOpt_is_required(opt) ? required_format : optional_format, 00016 response, 00017 ucOpt_get_name(opt) 00018 ); 00019 } 00020 00021 static const char *add_arg_opts_to_usage_response(ucArgOpt *arg_opt, ucCmdLine *cmd, const char *response) { 00022 00023 while (NULL != arg_opt) { 00024 response = add_opt_to_usage_response((ucOpt*)arg_opt, cmd, response); 00025 arg_opt = ucArgOpt_get_next(arg_opt); 00026 } 00027 00028 return response; 00029 } 00030 00031 static void send_arg_opts_help(ucArgOpt *arg_opt, ucCmdLine *cmd, const char *prefix) { 00032 while (NULL != arg_opt) { 00033 ucOpt_send_help((ucOpt*)arg_opt, cmd, prefix); 00034 arg_opt = ucArgOpt_get_next(arg_opt); 00035 } 00036 } 00037 00038 ucCmdLineOpt *ucCmdLineOpt_get_next(ucCmdLineOpt *p) { 00039 if (NULL == p) return NULL; 00040 return p->next; 00041 } 00042 00043 ucArgOpt *ucCmdLineOpt_get_arg_opt(ucCmdLineOpt *p) { 00044 if (NULL == p) return NULL; 00045 return ucArgOptOwner_get_arg_opt((ucArgOptOwner*)p); 00046 } 00047 00048 ucSwitchOpt *ucCmdLineOpt_get_switch_opt(ucCmdLineOpt *p) { 00049 if (NULL == p) return NULL; 00050 return p->switch_opt; 00051 } 00052 00053 ucCmdLineOpt *ucCmdLineOpt_init(ucCmdLineOpt *p, ucCmdLineOpt_Func *func, void* state, const char *name, const char *desc, ucArgOpt *arg_opt, ucSwitchOpt *switch_opt, ucCmdLineOpt* next) { 00054 if (NULL == p) return NULL; 00055 if (NULL == ucArgOptOwner_init((ucArgOptOwner*)p, name, desc, ucBool_TRUE, arg_opt)) return NULL; 00056 p->func = func; 00057 p->state = state; 00058 p->switch_opt = switch_opt; 00059 p->next = next; 00060 return p; 00061 } 00062 00063 ucCmdLineOpt *ucCmdLineOpt_create(ucCmdLineOpt_Func *func, void *state, const char *name, const char *desc, ucArgOpt* arg_opt, ucSwitchOpt *switch_opt, ucCmdLineOpt *next) { 00064 return ucCmdLineOpt_init(create_cmd_line_opt(), func, state, name, desc, arg_opt, switch_opt, next); 00065 } 00066 00067 ucCmdLineOpt *ucCmdLineOpt_find_by_name(ucCmdLineOpt* p, const char *name) { 00068 while (NULL != p) { 00069 if (0 == strcmp(name, ucOpt_get_name((ucOpt*)p))) { 00070 return p; 00071 } 00072 p = ucCmdLineOpt_get_next(p); 00073 } 00074 return NULL; 00075 } 00076 00077 ucCmdLineOpt_Func *ucCmdLineOpt_get_func(ucCmdLineOpt *p) { 00078 if (NULL == p) return NULL; 00079 return p->func; 00080 } 00081 00082 void *ucCmdLineOpt_get_state(ucCmdLineOpt *p) { 00083 if (NULL == p) return NULL; 00084 return p->state; 00085 } 00086 00087 void ucCmdLineOpt_send_usage(ucCmdLineOpt *p, ucCmdLine *cmd) { 00088 ucSwitchOpt *switch_opt; 00089 00090 /* start the usage string with the name of the command */ 00091 const char *response = ucCmdLine_format_response(cmd, "%s", ucOpt_get_name((ucOpt*)p)); 00092 00093 /* add each available argument option of the command 00094 to the usage string */ 00095 response = add_arg_opts_to_usage_response(ucCmdLineOpt_get_arg_opt(p), cmd, response); 00096 00097 /* loop through each available switch option */ 00098 switch_opt = ucCmdLineOpt_get_switch_opt(p); 00099 while (NULL != switch_opt) { 00100 00101 /* add it to the usage string */ 00102 response = add_opt_to_usage_response((ucOpt*)switch_opt, cmd, response); 00103 00104 /* also add each of the switch's argument options to the 00105 usage string */ 00106 response = add_arg_opts_to_usage_response(ucSwitchOpt_get_arg_opt(switch_opt), cmd, response); 00107 00108 /* go to the next switch */ 00109 switch_opt = ucSwitchOpt_get_next(switch_opt); 00110 } 00111 00112 /* send the completed usage string */ 00113 ucCmdLine_respond(cmd, response); 00114 } 00115 00116 void ucCmdLineOpt_send_help(ucCmdLineOpt *p, ucCmdLine *cmd) { 00117 static const char *single_tab = "\t"; 00118 static const char *double_tab = "\t\t"; 00119 00120 ucSwitchOpt *switch_opt; 00121 00122 ucCmdLineOpt_send_usage(p, cmd); 00123 00124 ucOpt_send_help((ucOpt*)p, cmd, ""); 00125 send_arg_opts_help(ucCmdLineOpt_get_arg_opt(p), cmd, single_tab); 00126 00127 switch_opt = ucCmdLineOpt_get_switch_opt(p); 00128 while (NULL != switch_opt) { 00129 ucOpt_send_help((ucOpt*)switch_opt, cmd, single_tab); 00130 send_arg_opts_help(ucSwitchOpt_get_arg_opt(switch_opt), cmd, double_tab); 00131 switch_opt = ucSwitchOpt_get_next(switch_opt); 00132 } 00133 } 00134 00135 const char *ucCmdLineOpt_format_validation_err(ucCmdLineOpt *p, ucCmdLine *cmd) { 00136 static const char *invalid_switch = "Invalid switch: "; 00137 00138 ucCmdTok *cmd_tok; 00139 ucSwitchOpt *switch_opt, *found_switch_opt, *next_switch_opt; 00140 ucSwitchTok *switch_tok, *found_switch_tok, *next_switch_tok; 00141 const char *switch_name, *validation; 00142 00143 cmd_tok = ucCmdLine_get_cmd_tok(cmd); 00144 00145 validation = ucArgOptOwner_format_validation_err((ucArgOptOwner*)p, cmd, ucCmdTok_get_arg(cmd_tok), NULL); 00146 if (NULL != validation) return validation; 00147 00148 switch_tok = ucCmdTok_get_switch(cmd_tok); 00149 switch_opt = ucCmdLineOpt_get_switch_opt(p); 00150 00151 if (NULL == switch_opt) { 00152 if (NULL != switch_tok) { 00153 return ucCmdLine_format_response(cmd, "%sno switch options exist for command \"%s\".", invalid_switch, ucTok_get_value((ucTok*)cmd_tok)); 00154 } 00155 return NULL; 00156 } 00157 00158 next_switch_tok = switch_tok; 00159 00160 while (NULL != next_switch_tok) { 00161 found_switch_opt = ucSwitchOpt_find(switch_opt, ucTok_get_value((ucTok*)next_switch_tok)); 00162 if (NULL == found_switch_opt) { 00163 return ucCmdLine_format_response(cmd, "%sno option exists for switch \"%s\".", invalid_switch, ucTok_get_value(next_switch_tok)); 00164 } 00165 next_switch_tok = ucSwitchTok_get_next(next_switch_tok); 00166 } 00167 00168 next_switch_opt = switch_opt; 00169 00170 while (NULL != next_switch_opt) { 00171 switch_name = ucOpt_get_name((ucOpt*)next_switch_opt); 00172 found_switch_tok = ucSwitchTok_find(switch_tok, switch_name); 00173 00174 if (ucOpt_is_required((ucOpt*)next_switch_opt)) { 00175 if (NULL == found_switch_tok) { 00176 return ucCmdLine_format_response(cmd, "%sthe switch \"%s\" is required.", invalid_switch, switch_name); 00177 } 00178 } 00179 00180 if (NULL != found_switch_tok) { 00181 validation = ucSwitchOpt_format_validation_err(next_switch_opt, cmd, found_switch_tok); 00182 if (NULL != validation) return validation; 00183 } 00184 00185 next_switch_opt = ucSwitchOpt_get_next(next_switch_opt); 00186 } 00187 00188 return NULL; 00189 } 00190 00191 static const char *internal_process(ucCmdLineOpt *p, ucCmdLine *cmd, ucBool *invalid_command_handled) { 00192 ucCmdTok *cmd_tok; 00193 ucCmdLineOpt *opt; 00194 ucCmdLineOpt_Func *func; 00195 const char *cmd_value; 00196 const char *validation; 00197 00198 /* Get the command token of the command structure. */ 00199 cmd_tok = ucCmdLine_get_cmd_tok(cmd); 00200 00201 /* Get the command option that we'll process by finding 00202 the one that matches the name of the command. */ 00203 cmd_value = ucTok_get_value((ucTok*)cmd_tok); 00204 opt = ucCmdLineOpt_find_by_name(p, cmd_value); 00205 if (NULL == opt) { 00206 00207 /* The command is invalid (meaning it doesn't exist). 00208 Try to handle it. */ 00209 *invalid_command_handled = ucCmdLine_handle_invalid_command(cmd, cmd_value); 00210 00211 /* If the command was handled, then we don't return an error. */ 00212 if (*invalid_command_handled) { 00213 return NULL; 00214 } 00215 } 00216 00217 /* Send an indication that the command was received. */ 00218 ucCmdLine_acknowledge_command(cmd); 00219 00220 /* Check to see if the command is unknown. */ 00221 if (NULL == opt) return ucCmdLine_format_response(cmd, "Invalid command: no option found for \"%s\"", cmd_value); 00222 00223 /* Validate the command structure against the option. 00224 If validation fails, then return the validation result. */ 00225 validation = ucCmdLineOpt_format_validation_err(opt, cmd); 00226 if (validation) return validation; 00227 00228 /* Get the function callback from the command option. */ 00229 func = ucCmdLineOpt_get_func(opt); 00230 if (NULL == func) return "Invalid function: null pointer"; 00231 00232 /* Invoke the callback. */ 00233 return func(cmd, ucCmdLineOpt_get_state(opt)); 00234 } 00235 00236 const char *ucCmdLineOpt_process(ucCmdLineOpt* p, ucCmdLine *cmd) { 00237 ucBool invalid_command_handled = ucBool_FALSE; 00238 const char *response = internal_process(p, cmd, &invalid_command_handled); 00239 if (invalid_command_handled) { 00240 return response; 00241 } 00242 00243 if (response) { 00244 ucCmdLine_respond(cmd, response); 00245 } 00246 00247 ucCmdLine_terminate_response(cmd); 00248 00249 return response; 00250 } 00251 00252 void ucCmdLineOpt_destroy(ucCmdLineOpt *p) { 00253 ucMemoryManager_destroy(p); 00254 } 00255 00256 void ucCmdLineOpt_destroy_chain(ucCmdLineOpt *p) { 00257 ucCmdLineOpt *next = p; 00258 while (NULL != next) { 00259 p = next; 00260 next = ucCmdLineOpt_get_next(p); 00261 ucArgOpt_destroy_chain(ucCmdLineOpt_get_arg_opt(p)); 00262 ucSwitchOpt_destroy_chain(ucCmdLineOpt_get_switch_opt(p)); 00263 ucCmdLineOpt_destroy(p); 00264 } 00265 } 00266
Generated on Thu Jul 14 2022 20:04:57 by
1.7.2