fixed little bug with long-only options

This commit is contained in:
2026-07-01 11:57:07 +03:00
parent f1162e4df1
commit 566ca36af8
4 changed files with 29 additions and 18 deletions

View File

@@ -52,6 +52,8 @@ static glob_pars const Gdefault = {
* name has_arg flag val type argptr help * name has_arg flag val type argptr help
* BE carefull! The `help` field is mandatory! Omitting it equivalent of 'end_option' * BE carefull! The `help` field is mandatory! Omitting it equivalent of 'end_option'
*/ */
// if val < 33 || val > 127 we mean this like long-only option;
// you can repeat the same `val` for several long-only options without any problem
static sl_option_t cmdlnopts[] = { static sl_option_t cmdlnopts[] = {
// short option in only-long options should be zeroed, or you can add flag to set it to given value // short option in only-long options should be zeroed, or you can add flag to set it to given value
{"lo0", NEED_ARG, NULL, 0, arg_int, APTR(&G.lo0), _("only long arg 0 (int)")}, {"lo0", NEED_ARG, NULL, 0, arg_int, APTR(&G.lo0), _("only long arg 0 (int)")},

View File

@@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-04 17:48+0300\n" "POT-Creation-Date: 2026-03-31 11:35+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -36,7 +36,7 @@ msgstr ""
msgid "Configuration file options (format: key=value):\n" msgid "Configuration file options (format: key=value):\n"
msgstr "" msgstr ""
#: /home/eddy/Docs/SAO/C_diff/snippets_library/daemon.c:69 #: /home/eddy/Docs/SAO/C_diff/snippets_library/daemon.c:70
#, c-format #, c-format
msgid "" msgid ""
"\n" "\n"
@@ -44,11 +44,11 @@ msgid ""
msgstr "" msgstr ""
#. error reading self name #. error reading self name
#: /home/eddy/Docs/SAO/C_diff/snippets_library/daemon.c:117 #: /home/eddy/Docs/SAO/C_diff/snippets_library/daemon.c:95
msgid "Can't read self name" msgid "Can't read self name"
msgstr "" msgstr ""
#: /home/eddy/Docs/SAO/C_diff/snippets_library/daemon.c:141 #: /home/eddy/Docs/SAO/C_diff/snippets_library/daemon.c:119
msgid "Can't open PID file" msgid "Can't open PID file"
msgstr "" msgstr ""

View File

@@ -7,7 +7,7 @@
msgid "" msgid ""
msgstr "Project-Id-Version: PACKAGE VERSION\n" msgstr "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-03-04 17:30+0300\n" "POT-Creation-Date: 2026-03-31 11:31+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -35,7 +35,7 @@ msgstr "sl_conf_showhelp():
msgid "Configuration file options (format: key=value):\n" msgid "Configuration file options (format: key=value):\n"
msgstr "ïÐÃÉÉ ËÏÎÆÉÇÕÒÁÃÉÏÎÎÏÇÏ ÆÁÊÌÁ (ÆÏÒÍÁÔ: ËÌÀÞ=ÚÎÁÞÅÎÉÅ):\n" msgstr "ïÐÃÉÉ ËÏÎÆÉÇÕÒÁÃÉÏÎÎÏÇÏ ÆÁÊÌÁ (ÆÏÒÍÁÔ: ËÌÀÞ=ÚÎÁÞÅÎÉÅ):\n"
#: /home/eddy/Docs/SAO/C_diff/snippets_library/daemon.c:69 #: /home/eddy/Docs/SAO/C_diff/snippets_library/daemon.c:70
#, c-format #, c-format
msgid "\n" msgid "\n"
"Found running process (pid=%d), exit.\n" "Found running process (pid=%d), exit.\n"
@@ -43,11 +43,11 @@ msgstr "\n"
"ïÂÎÁÒÕÖÅÎ ÏÄÎÏÉÍÅÎÎÙÊ ÐÒÏÃÅÓÓ (pid=%d), ×ÙÈÏÄ.\n" "ïÂÎÁÒÕÖÅÎ ÏÄÎÏÉÍÅÎÎÙÊ ÐÒÏÃÅÓÓ (pid=%d), ×ÙÈÏÄ.\n"
#. error reading self name #. error reading self name
#: /home/eddy/Docs/SAO/C_diff/snippets_library/daemon.c:117 #: /home/eddy/Docs/SAO/C_diff/snippets_library/daemon.c:95
msgid "Can't read self name" msgid "Can't read self name"
msgstr "îÅ ÍÏÇÕ ÐÒÏÞÅÓÔØ ÉÍÑ ÐÒÏÃÅÓÓÁ" msgstr "îÅ ÍÏÇÕ ÐÒÏÞÅÓÔØ ÉÍÑ ÐÒÏÃÅÓÓÁ"
#: /home/eddy/Docs/SAO/C_diff/snippets_library/daemon.c:141 #: /home/eddy/Docs/SAO/C_diff/snippets_library/daemon.c:119
msgid "Can't open PID file" msgid "Can't open PID file"
msgstr "îÅ ÍÏÇÕ ÏÔËÒÙÔØ PID ÆÁÊÌ" msgstr "îÅ ÍÏÇÕ ÏÔËÒÙÔØ PID ÆÁÊÌ"
@@ -236,5 +236,3 @@ msgstr "
#: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:331 #: /home/eddy/Docs/SAO/C_diff/snippets_library/usefull_macros.c:331
msgid "Can't setup console" msgid "Can't setup console"
msgstr "îÅ ÍÏÇÕ ÎÁÓÔÒÏÉÔØ ËÏÎÓÏÌØ" msgstr "îÅ ÍÏÇÕ ÎÁÓÔÒÏÉÔØ ËÏÎÓÏÌØ"
#, c-format

View File

@@ -30,6 +30,9 @@
#include <ctype.h> // isalpha #include <ctype.h> // isalpha
#include "usefull_macros.h" #include "usefull_macros.h"
// check `val` field: if it's <33 || >127 - it's just ordered number, not short option
#define CHKOPTVAL(Oval) ((Oval) > 32 && (Oval) < 128)
const char *helpstring = NULL; // will be inited later, can't init with gettext on this stage const char *helpstring = NULL; // will be inited later, can't init with gettext on this stage
/** /**
@@ -130,8 +133,15 @@ static int get_optind(const char *key, int opt, sl_option_t *options, void (*hel
helpfun(-1, options); helpfun(-1, options);
return -1; // never reached until `helpfun` changed return -1; // never reached until `helpfun` changed
}else if(opt == ':') theopt = optopt; // search to show helpstring "need parameter" }else if(opt == ':') theopt = optopt; // search to show helpstring "need parameter"
for(oind = 0; opts->help && opts->val != theopt; oind++, opts++){ if(key[1] != '-'){ // search by unique short option
DBG("cmp %c and %c", theopt, opts->val); for(oind = 0; opts->help && opts->val != theopt; oind++, opts++){
DBG("cmp %c and %c", theopt, opts->val);
}
}else{ // search by long option
key += 2;
for(oind = 0; opts->help; oind++, opts++){
if(opts->name && 0 == strcmp(key, opts->name)) break;
}
} }
if(!opts->help) return -1; if(!opts->help) return -1;
if(opt == ':'){ if(opt == ':'){
@@ -249,7 +259,7 @@ void sl_parseargs_hf(int *argc, char ***argv, sl_option_t *options, void (*helpf
loptr->flag = opts->flag; loptr->flag = opts->flag;
loptr->val = opts->val; loptr->val = opts->val;
// fill short options if they are: // fill short options if they are:
if(!opts->flag && opts->val){ if(!opts->flag && CHKOPTVAL(opts->val)){
shortlist[i] = (char) opts->val; shortlist[i] = (char) opts->val;
*soptr++ = opts->val; *soptr++ = opts->val;
if(loptr->has_arg) // add ':' if option has required argument if(loptr->has_arg) // add ':' if option has required argument
@@ -371,21 +381,22 @@ void sl_parseargs(int *argc, char ***argv, sl_option_t *options){
/** /**
* @brief argsort - compare function for qsort * @brief argsort - compare function for qsort
* first - sort by short options; second - sort arguments without sort opts (by long options) * first - sort by short options; second - sort arguments without short opts (by long options)
*/ */
static int argsort(const void *a1, const void *a2){ static int argsort(const void *a1, const void *a2){
const sl_option_t *o1 = (sl_option_t*)a1, *o2 = (sl_option_t*)a2; const sl_option_t *o1 = (sl_option_t*)a1, *o2 = (sl_option_t*)a2;
const char *l1 = o1->name, *l2 = o2->name; const char *l1 = o1->name, *l2 = o2->name;
int s1 = o1->val, s2 = o2->val; int s1 = o1->val, s2 = o2->val;
int chk1 = CHKOPTVAL(s1), chk2 = CHKOPTVAL(s2);
int *f1 = o1->flag, *f2 = o2->flag; int *f1 = o1->flag, *f2 = o2->flag;
// check if both options has short arg // check if both options has short arg
if(f1 == NULL && f2 == NULL && s1 && s2){ // both have short arg if(f1 == NULL && f2 == NULL && chk1 && chk2){ // both have short arg
return (s1 - s2); return (s1 - s2);
}else if((f1 != NULL || !s1) && (f2 != NULL || !s2)){ // both don't have short arg - sort by long }else if((f1 != NULL || !chk1) && (f2 != NULL || !chk2)){ // both don't have short arg - sort by long
assert(l1); assert(l2); // no way to omit long option if short is absent assert(l1); assert(l2); // no way to omit long option if short is absent
return strcmp(l1, l2); return strcmp(l1, l2);
}else{ // only one have short arg -- return it }else{ // only one have short arg -- return it
if(f2 || !s2) return -1; // a1 have short - it is 'lesser' if(f2 || !chk2) return -1; // a1 have short - it is 'lesser'
else return 1; else return 1;
} }
} }
@@ -394,7 +405,7 @@ static int argsort(const void *a1, const void *a2){
static void pr_helpstring(sl_option_t *opt, char *buf, int indent, size_t bufsz){ static void pr_helpstring(sl_option_t *opt, char *buf, int indent, size_t bufsz){
size_t p = sprintf(buf, " "); // a little indent size_t p = sprintf(buf, " "); // a little indent
int havelongopt = opt->name && *opt->name; int havelongopt = opt->name && *opt->name;
if(!opt->flag && opt->val){ // .val is short argument if(!opt->flag && CHKOPTVAL(opt->val)){ // .val is short argument
p += snprintf(buf+p, bufsz-p, "-%c", opt->val); p += snprintf(buf+p, bufsz-p, "-%c", opt->val);
if(havelongopt) p += snprintf(buf+p, bufsz-p, ", "); // show comma only it there's shor arg if(havelongopt) p += snprintf(buf+p, bufsz-p, ", "); // show comma only it there's shor arg
} }