From: Pedro Alves <palves@redhat.com>
To: Philippe Waroquiers <philippe.waroquiers@skynet.be>,
gdb-patches@sourceware.org
Subject: Re: [RFA_v3 1/8] Add helper functions parse_flags and parse_flags_qcs
Date: Mon, 09 Jul 2018 19:14:00 -0000 [thread overview]
Message-ID: <fa82f0c7-1f72-5749-4a88-a6f8829b54fa@redhat.com> (raw)
In-Reply-To: <20180624183708.888-2-philippe.waroquiers@skynet.be>
Hi Philippe,
This looks mostly good to me. A few minor comments below,
and a suggestion.
On 06/24/2018 07:37 PM, Philippe Waroquiers wrote:
>
> The error message for 'thread apply -$unknownconvvar p 1'
> is now the more clear:
> Convenience variable must have integer value.
> Invalid thread ID: -$unknownconvvar p 1
> instead of previously:
> negative value
>
> gdb/ChangeLog
> 2018-06-24 Philippe Waroquiers <philippe.waroquiers@skynet.be>
>
> * cli-utils.c (number_or_range_parser::get_number): Only handle
> numbers or convenience var as numbers.
> (parse_flags): New function.
> (parse_flags_qcs): New function.
> (number_or_range_parser::finished): ensure parsing end is detected
> before end of string.
> * cli-utils.h (parse_flags): New function.
> (parse_flags_qcs): New function.
> (number_or_range_parser): Remove m_finished bool.
> (number_or_range_parser::skip_range): set m_in_range to false.
Note some tab vs spaces mixup above.
> ---
> gdb/cli/cli-utils.c | 98 +++++++++++++++++++++++++++++++++++++++++++--
> gdb/cli/cli-utils.h | 35 +++++++++++++---
> 2 files changed, 124 insertions(+), 9 deletions(-)
>
> diff --git a/gdb/cli/cli-utils.c b/gdb/cli/cli-utils.c
> index c55b5035e4..6fef419216 100644
> --- a/gdb/cli/cli-utils.c
> +++ b/gdb/cli/cli-utils.c
> @@ -137,7 +137,6 @@ number_or_range_parser::number_or_range_parser (const char *string)
> void
> number_or_range_parser::init (const char *string)
> {
> - m_finished = false;
> m_cur_tok = string;
> m_last_retval = 0;
> m_end_value = 0;
> @@ -169,7 +168,10 @@ number_or_range_parser::get_number ()
> /* Default case: state->m_cur_tok is pointing either to a solo
> number, or to the first number of a range. */
> m_last_retval = get_number_trailer (&m_cur_tok, '-');
> - if (*m_cur_tok == '-')
> + /* If get_number_trailer has found a -, it might be the start
> + of a command option. So, do not parse a range if the - is
> + followed by an alpha. */
> + if (*m_cur_tok == '-' && !isalpha (*(m_cur_tok + 1)))
> {
> const char **temp;
>
> @@ -196,8 +198,17 @@ number_or_range_parser::get_number ()
> }
> }
> else
> - error (_("negative value"));
> - m_finished = *m_cur_tok == '\0';
> + {
> + if (isdigit (*(m_cur_tok + 1)))
> + error (_("negative value"));
> + if (*(m_cur_tok + 1) == '$')
> + {
> + /* Convenience variable. */
> + m_last_retval = ::get_number (&m_cur_tok);
> + if (m_last_retval < 0)
> + error (_("negative value"));
> + }
> + }
> return m_last_retval;
> }
>
> @@ -215,6 +226,22 @@ number_or_range_parser::setup_range (int start_value, int end_value,
> m_end_value = end_value;
> }
>
> +/* See documentation in cli-utils.h. */
> +
> +bool
> +number_or_range_parser::finished () const
> +{
> + /* Parsing is finished when at end of string or null string,
> + or
> + we are not in a range and not in front of an integer,
> + negative integer, convenience var or negative convenience var. */
Seems strange that "or" is in its own line. Hit meta-q in emacs?
> + return (m_cur_tok == NULL || *m_cur_tok == '\0')
> + || (!m_in_range
> + && !(isdigit (*m_cur_tok) || *m_cur_tok == '$')
> + && !(*m_cur_tok == '-'
> + && (isdigit (*(m_cur_tok + 1)) || *(m_cur_tok + 1) == '$')));
> +}
> +
GNU's convention is to wrap the whole multi-line expression
in parens so that emacs indents the || in the second line under
"(m_curr_tok". We don't really need the parens in the first
line, so that gives us:
bool
number_or_range_parser::finished () const
{
/* Parsing is finished when at end of string or null string, or we
are not in a range and not in front of an integer, negative
integer, convenience var or negative convenience var. */
return (m_cur_tok == NULL || *m_cur_tok == '\0'
|| (!m_in_range
&& !(isdigit (*m_cur_tok) || *m_cur_tok == '$')
&& !(*m_cur_tok == '-'
&& (isdigit (*(m_cur_tok + 1)) || *(m_cur_tok + 1) == '$')));
}
You could also use m_cur_tok[1] instead of "*(m_cur_tok + 1)" if you
like to make it a little bit shorter.
> /* Accept a number and a string-form list of numbers such as is
> accepted by get_number_or_range. Return TRUE if the number is
> in the list.
> @@ -230,6 +257,9 @@ number_is_in_list (const char *list, int number)
> return 1;
>
> number_or_range_parser parser (list);
> +
> + if (parser.finished ())
> + error (_("Args must be numbers or '$' variables."));
I think it's better to spell out "Arguments".
> +
> +int
> +parse_flags_qcs (const char *which_command, const char **str,
> + bool *quiet, bool *cont, bool *silent)
> +{
> + const char *flags = "qcs";
> + int res;
"res" is not used.
> +
> + switch (parse_flags (str, flags))
> + {
> + case 0:
> + return 0;
> + case 1:
> + *quiet = true;
> + break;
> + case 2:
> + *cont = true;
> + break;
> + case 3:
> + *silent = true;
> + break;
> + default:
> + gdb_assert (0);
Use gdb_assert_not_reached.
> + }
> +
> + if (*cont && *silent)
> + error (_("%s: -c and -s are mutually exclusive"), which_command);
> +
> + return 1;
> +}
> @@ -173,4 +170,32 @@ check_for_argument (char **str, const char *arg, int arg_len)
> arg, arg_len);
> }
>
> +/* A helper function that looks for a set of flags at the start of a
> + string. The possible flags are given as a null terminated string.
> + A flag in STR must either be at the end of the string,
> + or be followed by whitespace.
> + Returns 0 if no valid flag is found at the start of STR.
> + Otherwise updates *STR, and returns N (which is > 0),
> + such that FLAGS [N - 1] is the valid found flag. */
> +extern int parse_flags (const char **str, const char *flags);
> +
> +/* A helper function that uses parse_flags to handle the flags qcs :
> + A flag -q sets *QUIET to true.
> + A flag -c sets *CONT to true.
> + A flag -s sets *SILENT to true.
> +
> + The caller is responsible to initialize *QUIET, *CONT, *SILENT to
> + false before the (first) call to parse_flags_qcs.
> + parse_flags_qcs can then be called iteratively to search for more
> + valid flags, as part of a 'main parsing loop' searching for -q/-c/-s
> + flags together with other flags and options.
> +
> + Returns 1 and updates *STR and one of *QUIET, *CONT, *SILENT
> + if it finds a valid flag.
> + Returns 0 if no valid flag is found at the beginning of STR.
This can be bool and true/false, right?
> +
> + Throws an error if a flag is found such that both *CONT and *SILENT
> + are true. */
> +extern int parse_flags_qcs (const char *which_command, const char **str,
> + bool *quiet, bool *cont, bool *silent);
I suspect that using a single structure instead of multiple output bools,
like this:
struct qcs_flags
{
bool quiet = false;
bool cont = false;
bool silent = false;
};
extern bool parse_flags_qcs (const char *which_command, const char **str,
qcs_flags *flags);
would make the code a little clearer. Note that that way the "= false"
default initializers are part of the type, no need to do that explicitly
at the callers.
Thanks,
Pedro Alves
next prev parent reply other threads:[~2018-07-09 19:14 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-06-24 18:37 [RFA_v3 0/8] Implement 'frame apply COMMAND', enhance 'thread apply COMMAND' Philippe Waroquiers
2018-06-24 18:37 ` [RFA_v3 3/8] Add [FLAG]... arguments to 'thread apply' Philippe Waroquiers
2018-07-09 19:18 ` Pedro Alves
2018-06-24 18:37 ` [RFA_v3 5/8] Announce the user visible changes for frame/thread apply in NEWS Philippe Waroquiers
2018-06-24 18:37 ` [RFA_v3 4/8] Documents the new commands 'frame apply', faas, taas, tfaas Philippe Waroquiers
2018-07-09 19:16 ` Pedro Alves
2018-06-24 18:37 ` [RFA_v3 8/8] Add a self-test for cli-utils.c Philippe Waroquiers
2018-07-09 19:27 ` Pedro Alves
2018-06-24 18:37 ` [RFA_v3 6/8] Add a test for 'frame apply' Philippe Waroquiers
2018-07-09 19:19 ` Pedro Alves
2018-06-24 18:37 ` [RFA_v3 1/8] Add helper functions parse_flags and parse_flags_qcs Philippe Waroquiers
2018-07-09 19:14 ` Pedro Alves [this message]
2018-06-24 18:37 ` [RFA_v3 7/8] Modify gdb.threads/pthreads.exp to test FLAG qcs arguments for thread apply Philippe Waroquiers
2018-06-24 18:37 ` [RFA_v3 2/8] Implement frame apply [all | COUNT | -COUNT | id ID... ] [FLAG]... COMMAND Philippe Waroquiers
2018-07-09 19:16 ` Pedro Alves
2018-07-10 21:50 ` Philippe Waroquiers
2018-06-29 12:22 ` [RFA_v3 0/8] Implement 'frame apply COMMAND', enhance 'thread apply COMMAND' Andrew Burgess
2018-06-29 20:16 ` Philippe Waroquiers
2018-06-29 20:38 ` Philippe Waroquiers
2018-07-09 19:01 ` Pedro Alves
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=fa82f0c7-1f72-5749-4a88-a6f8829b54fa@redhat.com \
--to=palves@redhat.com \
--cc=gdb-patches@sourceware.org \
--cc=philippe.waroquiers@skynet.be \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).