-
Notifications
You must be signed in to change notification settings - Fork 770
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Simple command line argument parsing utility in PJLIB #4013
Conversation
…function warnings
pjlib/include/pj/argparse.h
Outdated
while (*argv) { | ||
const char *arg = *argv; | ||
if ((*arg=='-' && *(arg+1) && !pj_isdigit(*(arg+1))) || | ||
(*arg=='-' && *(arg+1)=='-' && *(arg+2))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
according to the spec, *(arg+2) also needs to be a letter, so need to check !pj_isdigit()
as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment meant to say that a negative number (e.g. -1
) will not be considered as an option. But thinking about it again, and checking the behavior of some programs e.g. gcc
or clang
, they both consider -1
as an option, e.g.:
$ gcc -1
gcc: error: unrecognized command-line option ‘-1’
So in the latest commit, any arguments that start with dash is considered an option (and comment updated accordingly)
pjlib/include/pj/argparse.h
Outdated
* | ||
* @return PJ_TRUE if the option exists, else PJ_FALSE. | ||
*/ | ||
PJ_INLINE(pj_bool_t) pj_argparse_exists(const char *opt, char *const argv[]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could be mistaken here, but usually it's the other way around, pj_argparse_exists(argv, opt)
, with the object being searched (i.e. the main object) being the first parameter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that's a good point. Rearranged the argument (also in pj_argparse_get_bool()/_str()/_int()
to the same convention) in latest commit
pjlib/include/pj/argparse.h
Outdated
} | ||
|
||
/** | ||
* Check for an option and if it exists, returns PJ_TRUE remove that option |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return
PJ_TRUE and
remove
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
pjlib/include/pj/argparse.h
Outdated
|
||
/** | ||
* Check for an option and if it exists, get the value and remove both | ||
* the option the the value from argc/argv. Note that the function only |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and
the value
Also below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
pjlib/include/pj/argparse.h
Outdated
/** | ||
* Check for an option and if it exists, get the value and remove both | ||
* the option the the value from argc/argv. Note that the function only | ||
* supports whitespace as separator between option and value (i.e. equal |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
a single whitespace or whitespaces?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added "limitations" section in this PR and in argparse doxygen to clarify the problem. Also doxygen comments updated to use "whitespace(s)".
IMHO it is easier to have error returned when argument does not exist because:
|
Agreed that this is rather subjective, and it is in my view that since options are by definition optional, it is not wrong to consider lack of it as "success" condition. But I also understand your point, i.e. if we issue In the end, I chose current approach because it is easier to use (we'll discuss more below) and while taking this approach probably is not idealistic in term of "correctness", it's not wrong. Btw initially the API uses that approach i.e. to return
It is indeed intentional for Also this allows handling short and long options like this:
(if return value is initialized by the function, then the value would have been reset in the second call) So in most cases, checking if the default value has changed (e.g. not
See above. |
The PJSIP suite contains copy of
getopt
implementation, but it is in PJLIB-UTIL and also has different licensing than PJSIP.This PR implements a simple, header only argument parsing utilities that can be (and will be) used by
pjlib-test
and all unit testing apps to replace current manual parsing.Usage
Argparse provides these few utilities:
pj_argparse_exists(..)
: check if argument existspj_argparse_get_bool(..)
: get an argument and remove it from argc/argv if it existspj_argparse_get_str(..)
: get an argument and its value and remove the argument-value pair from argc/argv if it existspj_argparse_get_int(..)
: get an argument and its int value and remove the argument-value pair from argc/argv if it existspj_argparse_peek_next_option(..)
: get first option (argument with preceeding-
, or--
) in argv, to check if there is remaining unrecognized optionNote
The difference between
pj_argparse_exists(..)
andpj_argparse_get_bool()
is the latter removes the argument from argc/argv if the argument exists.There is a different semantic between the return value of
pj_argparse_get_bool()
andpj_argparse_get_str()
orpj_argparse_get_int()
.pj_argparse_get_bool()
returns "the value", i.e. TRUE if the the argument exists.pj_argparse_get_bool()
andpj_argparse_get_str()
returnspj_status_t
, i.e.PJ_SUCCESS
if everything is okay (an argument has been successfully parsed, or the argument does not exist), or error otherwise. In case of error, the error string would have been printed to the screen.This design decision is chosen for convenience.
Sample
For example, to parse these options:
the following code can be used:
Limitations
First, the utility only supports white space(s) as separator between an option and its value. Equal sign is not supported:
Second, the utility does not support double dash (
--
) as separator between options and operands (see this discussion in stackexchange on the meaning of--
)