# HG changeset patch # User Myhailo Danylenko # Date 1361681387 -7200 # Node ID 7e44adeed9a796807cc703555446c3cd3c84097f # Parent d328b18462bd38e5d8e3e82bba4c3cd098fbce52 Fixes to cmdopts diff -r d328b18462bd -r 7e44adeed9a7 cmdopts.diff --- a/cmdopts.diff Sun Feb 24 04:47:32 2013 +0200 +++ b/cmdopts.diff Sun Feb 24 06:49:47 2013 +0200 @@ -2,10 +2,201 @@ # Parent 92fa48ef53c909928706ab4c51518953339a38e4 Unified command option parsing +diff -r 92fa48ef53c9 mcabber/mcabber/commands.c +--- a/mcabber/mcabber/commands.c Sun Jan 27 00:40:37 2013 +0200 ++++ b/mcabber/mcabber/commands.c Sun Feb 24 06:49:31 2013 +0200 +@@ -1634,130 +1634,109 @@ + + static void do_say_to(char *arg) + { +- char **paramlst; +- char *fjid, *msg_utf8; ++ char *fjid; + char *msg; +- char *unescaped_msg = NULL; +- char *uncompletedfjid = NULL; +- char *file = NULL; ++ char *file; ++ gchar *freeme = NULL; // fjid ++ gchar *freeme2 = NULL; // msg + LmMessageSubType msg_type = LM_MESSAGE_SUB_TYPE_NOT_SET; +- bool quiet = FALSE; +- bool eval = FALSE; ++ cmdopts_t options = { ++ (cmdopt_t[5]){ ++ { CMDOPT_SWITCH, 'n', "normal", { .swc = 0 } }, ++ { CMDOPT_SWITCH, 'h', "headline", { .swc = 0 } }, ++ { CMDOPT_SWITCH, 'e', "escapes", { .swc = 0 } }, ++ { CMDOPT_SWITCH, 'q', "quiet", { .swc = 0 } }, ++ { CMDOPT_LAST, 'f', "file", { .opt = NULL } }, ++ }, ++ (cmdarg_t[2]){ ++ { CMDOPT_REQUIRED, { .arg = NULL } }, ++ { CMDOPT_LAST | CMDOPT_PLAIN | CMDOPT_CATCHALL, { .arg = NULL } }, ++ }, ++ NULL, ++ NULL, ++ }; + + if (!xmpp_is_online()) { + scr_LogPrint(LPRINT_NORMAL, "You are not connected."); + return; + } + +- msg_type = scan_mtype(&arg); +- paramlst = split_arg(arg, 2, 1); // jid, message (or option, jid, message) +- +- if (!*paramlst) { // No parameter? +- scr_LogPrint(LPRINT_NORMAL, "Please specify a Jabber ID."); +- free_arg_lst(paramlst); +- return; ++ { // parse arguments ++ const char *error = cmdopts_parse(arg, &options); ++ if (error != NULL) { ++ scr_log_print(LPRINT_NORMAL, error); ++ return; ++ } + } + +- // Check for an option parameter +- while (*paramlst) { +- if (!strcmp(*paramlst, "-q")) { +- char **oldparamlst = paramlst; +- paramlst = split_arg(*(oldparamlst+1), 2, 1); // jid, message +- free_arg_lst(oldparamlst); +- quiet = TRUE; +- } else if (!strcmp(*paramlst, "-e")) { +- char **oldparamlst = paramlst; +- paramlst = split_arg(*(oldparamlst+1), 2, 1); // jid, message +- free_arg_lst(oldparamlst); +- eval = TRUE; +- } else if (!strcmp(*paramlst, "-f")) { +- char **oldparamlst = paramlst; +- paramlst = split_arg(*(oldparamlst+1), 2, 1); // filename, jid +- free_arg_lst(oldparamlst); +- if (!*paramlst) { +- scr_LogPrint(LPRINT_NORMAL, "Wrong usage."); +- free_arg_lst(paramlst); +- return; +- } +- file = g_strdup(*paramlst); +- // One more parameter shift... +- oldparamlst = paramlst; +- paramlst = split_arg(*(oldparamlst+1), 2, 1); // jid, nothing +- free_arg_lst(oldparamlst); +- } else +- break; ++ if (options.opts[0].value.swc) { ++ msg_type = LM_MESSAGE_SUB_TYPE_NORMAL; ++ } else if (options.opts[1].value.swc) { ++ msg_type = LM_MESSAGE_SUB_TYPE_HEADLINE; + } + +- if (!*paramlst) { +- scr_LogPrint(LPRINT_NORMAL, "Wrong usage."); +- free_arg_lst(paramlst); +- return; +- } +- +- fjid = *paramlst; +- msg = *(paramlst+1); +- ++ fjid = options.args[0].value.arg; ++ msg = options.args[1].value.arg; ++ file = options.opts[4].value.opt; ++ ++ // ideally, this should go to commandline parsing subsystem + if (fjid[0] == '.') { + const gchar *cjid = (current_buddy ? CURRENT_JID : NULL); + if (fjid[1] == '\0') { +- fjid = g_strdup(cjid); ++ fjid = (char *)cjid; // FIXME + } else if (fjid[1] == JID_RESOURCE_SEPARATOR) { + char *res_utf8 = to_utf8(fjid+2); +- fjid = g_strdup_printf("%s%c%s", cjid, JID_RESOURCE_SEPARATOR, res_utf8); ++ freeme = fjid = g_strdup_printf("%s%c%s", cjid, JID_RESOURCE_SEPARATOR, res_utf8); + g_free(res_utf8); +- } else +- fjid = to_utf8(fjid); +- } else +- fjid = to_utf8(fjid); +- ++ } ++ } ++ ++ // ditto + if (!strchr(fjid, JID_DOMAIN_SEPARATOR)) { + const gchar *append_server = settings_opt_get("default_server"); + if (append_server) { + gchar *res = strchr(fjid, JID_RESOURCE_SEPARATOR); +- uncompletedfjid = fjid; + if (res) { + *res++ = '\0'; + fjid = g_strdup_printf("%s%c%s%c%s", fjid, JID_DOMAIN_SEPARATOR, append_server, + JID_RESOURCE_SEPARATOR, res); + } else + fjid = g_strdup_printf("%s%c%s", fjid, JID_DOMAIN_SEPARATOR, append_server); ++ g_free(freeme); ++ freeme = fjid; + } + } + ++ // as well + if (check_jid_syntax(fjid)) { + scr_LogPrint(LPRINT_NORMAL, "Please specify a valid Jabber ID."); +- free_arg_lst(paramlst); +- g_free(uncompletedfjid); +- g_free(fjid); ++ g_free(freeme); + return; + } + +- if (!file) { +- msg_utf8 = to_utf8(msg); +- if (eval) { +- unescaped_msg = ut_unescape_tabs_cr(msg_utf8); ++ if (file == NULL) { ++ if (options.opts[2].value.swc) { ++ freeme2 = ut_unescape_tabs_cr(msg); + // We must not free() if the original string was returned +- if (unescaped_msg == msg_utf8) +- unescaped_msg = NULL; ++ if (freeme2 == msg) ++ freeme2 = NULL; ++ else ++ msg = freeme2; + } +- msg = (unescaped_msg ? unescaped_msg : msg_utf8); + } else { + char *filename_xp; + if (msg) + scr_LogPrint(LPRINT_NORMAL, "say_to: extra parameter ignored."); + filename_xp = expand_filename(file); +- msg = msg_utf8 = load_message_from_file(filename_xp); ++ freeme2 = msg = load_message_from_file(filename_xp); + g_free(filename_xp); +- g_free(file); + } + +- send_message_to(fjid, msg, NULL, msg_type, quiet); +- +- g_free(uncompletedfjid); +- g_free(fjid); +- g_free(msg_utf8); +- g_free(unescaped_msg); +- free_arg_lst(paramlst); ++ send_message_to(fjid, msg, NULL, msg_type, options.opts[3].value.swc); ++ ++ cmdopts_free(&options); ++ g_free(freeme); ++ g_free(freeme2); + } + + // buffer_updown(updown, nblines) diff -r 92fa48ef53c9 mcabber/mcabber/utils.c --- a/mcabber/mcabber/utils.c Sun Jan 27 00:40:37 2013 +0200 -+++ b/mcabber/mcabber/utils.c Sun Feb 24 04:24:14 2013 +0200 -@@ -555,6 +555,311 @@ ++++ b/mcabber/mcabber/utils.c Sun Feb 24 06:49:31 2013 +0200 +@@ -555,6 +555,312 @@ *str = tolower(*str); } @@ -222,7 +413,6 @@ + } + } + state = in_space; -+ p ++; + } else if (*p == '\\' && !(flags & CMDOPT_PLAIN)) { // next char escape + memmove(p, p+1, e-(p+1)); + e --; @@ -267,14 +457,16 @@ + argument = options -> args; + do { + if (argument -> flags & CMDOPT_REQUIRED) { -+ if (argument -> flags & CMDOPT_SUBCOMMAND && argument -> value.cmd == NULL) { -+ error = "Subcommand is not specified"; -+ break; -+ } -+ } else { -+ if ((!(argument -> flags & CMDOPT_SUBCOMMAND)) && argument -> value.arg == NULL) { -+ error = "Required argument is not specified"; -+ break; ++ if (argument -> flags & CMDOPT_SUBCOMMAND) { ++ if (argument -> value.cmd == NULL) { ++ error = "Subcommand is not specified"; ++ break; ++ } ++ } else { ++ if (argument -> value.arg == NULL) { ++ error = "Required argument is not specified"; ++ break; ++ } + } + } + } while (!(argument++ -> flags & CMDOPT_LAST)); @@ -319,7 +511,7 @@ // Only quotes need a backslash diff -r 92fa48ef53c9 mcabber/mcabber/utils.h --- a/mcabber/mcabber/utils.h Sun Jan 27 00:40:37 2013 +0200 -+++ b/mcabber/mcabber/utils.h Sun Feb 24 04:24:14 2013 +0200 ++++ b/mcabber/mcabber/utils.h Sun Feb 24 06:49:31 2013 +0200 @@ -43,6 +43,93 @@ char **split_arg(const char *arg, unsigned int n, int dontstriplast); void free_arg_lst(char **arglst); @@ -348,7 +540,7 @@ + +// Flags: +// Only applies to options, defined if option does not have argument. -+#define CMDOPT_SWITCH ( 0<<1 ) ++#define CMDOPT_SWITCH ( 1<<0 ) +// Don't process quotes and escapes in argument (applies to option arguments too). +#define CMDOPT_PLAIN ( 1<<1 ) +// For options - put all encountered values into GSList value.multiopt @@ -356,14 +548,14 @@ +// For switches - increment value.swc instead of logical flipping. +// For arguments - grab the rest of the line without splitting on spaces. +// Implicitly last argument. -+#define CMDOPT_CATCHALL ( 2<<1 ) ++#define CMDOPT_CATCHALL ( 1<<2 ) +// Option/argument must have value. -+#define CMDOPT_REQUIRED ( 3<<1 ) ++#define CMDOPT_REQUIRED ( 1<<3 ) +// Last entry in struct sequence. -+#define CMDOPT_LAST ( 4<<1 ) ++#define CMDOPT_LAST ( 1<<4 ) +// Argument only, argument is the name for subcommand. +// Implicitly last argument. -+#define CMDOPT_SUBCOMMAND ( 5<<1 ) ++#define CMDOPT_SUBCOMMAND ( 1<<5 ) + +// thoughts about future: +// command struct contains cmdopts