diff options
-rw-r--r-- | gdb/ChangeLog | 13 | ||||
-rw-r--r-- | gdb/cli/cli-utils.c | 96 | ||||
-rw-r--r-- | gdb/cli/cli-utils.h | 45 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/skip.exp | 6 |
5 files changed, 151 insertions, 13 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 1a37862..7eb8d01 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,16 @@ +2018-07-12 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. + 2018-07-12 Sergio Durigan Junior <sergiodj@redhat.com> * ser-tcp.c (try_connect): Declare 'ioarg' as 'u_long' if building diff --git a/gdb/cli/cli-utils.c b/gdb/cli/cli-utils.c index c55b503..98b7414 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,21 @@ 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. */ + 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] == '$')))); +} + /* 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,12 +256,15 @@ number_is_in_list (const char *list, int number) return 1; number_or_range_parser parser (list); + + if (parser.finished ()) + error (_("Arguments must be numbers or '$' variables.")); while (!parser.finished ()) { int gotnum = parser.get_number (); if (gotnum == 0) - error (_("Args must be numbers or '$' variables.")); + error (_("Arguments must be numbers or '$' variables.")); if (gotnum == number) return 1; } @@ -304,3 +333,60 @@ check_for_argument (const char **str, const char *arg, int arg_len) } return 0; } + +/* See documentation in cli-utils.h. */ + +int +parse_flags (const char **str, const char *flags) +{ + const char *p = skip_spaces (*str); + + if (p[0] == '-' + && isalpha (p[1]) + && (p[2] == '\0' || isspace (p[2]))) + { + const char pf = p[1]; + const char *f = flags; + + while (*f != '\0') + { + if (*f == pf) + { + *str = skip_spaces (p + 2); + return f - flags + 1; + } + f++; + } + } + + return 0; +} + +/* See documentation in cli-utils.h. */ + +bool +parse_flags_qcs (const char *which_command, const char **str, + qcs_flags *flags) +{ + switch (parse_flags (str, "qcs")) + { + case 0: + return false; + case 1: + flags->quiet = true; + break; + case 2: + flags->cont = true; + break; + case 3: + flags->silent = true; + break; + default: + gdb_assert_not_reached ("int qcs flag out of bound"); + } + + if (flags->cont && flags->silent) + error (_("%s: -c and -s are mutually exclusive"), which_command); + + return true; +} diff --git a/gdb/cli/cli-utils.h b/gdb/cli/cli-utils.h index e34ee0d..fa7d02d 100644 --- a/gdb/cli/cli-utils.h +++ b/gdb/cli/cli-utils.h @@ -75,8 +75,7 @@ public: const char *end_ptr); /* Returns true if parsing has completed. */ - bool finished () const - { return m_finished; } + bool finished () const; /* Return the string being parsed. When parsing has finished, this points past the last parsed token. */ @@ -96,6 +95,7 @@ public: { gdb_assert (m_in_range); m_cur_tok = m_end_ptr; + m_in_range = false; } private: @@ -103,9 +103,6 @@ private: number_or_range_parser (const number_or_range_parser &); number_or_range_parser &operator= (const number_or_range_parser &); - /* True if parsing has completed. */ - bool m_finished; - /* The string being parsed. When parsing has finished, this points past the last parsed token. */ const char *m_cur_tok; @@ -173,4 +170,42 @@ 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); + +/* qcs_flags struct regroups the flags parsed by parse_flags_qcs. */ + +struct qcs_flags +{ + bool quiet = false; + bool cont = false; + bool silent = false; +}; + +/* A helper function that uses parse_flags to handle the flags qcs : + A flag -q sets FLAGS->QUIET to true. + A flag -c sets FLAGS->CONT to true. + A flag -s sets FLAGS->SILENT to true. + + The caller is responsible to initialize *FLAGS 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 true and updates *STR and one of FLAGS->QUIET, FLAGS->CONT, + FLAGS->SILENT if it finds a valid flag. + Returns false if no valid flag is found at the beginning of STR. + + Throws an error if a flag is found such that both FLAGS->CONT and + FLAGS->SILENT are true. */ + +extern bool parse_flags_qcs (const char *which_command, const char **str, + qcs_flags *flags); #endif /* CLI_UTILS_H */ diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 2ddf7f8..95ad798 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2018-07-12 Philippe Waroquiers <philippe.waroquiers@skynet.be> + + * gdb.base/skip.exp: Update expected error message. + 2018-07-11 Sergio Durigan Junior <sergiodj@redhat.com> Jan Kratochvil <jan.kratochvil@redhat.com> Paul Fertser <fercerpav@gmail.com> diff --git a/gdb/testsuite/gdb.base/skip.exp b/gdb/testsuite/gdb.base/skip.exp index 4b556b1..223c93d 100644 --- a/gdb/testsuite/gdb.base/skip.exp +++ b/gdb/testsuite/gdb.base/skip.exp @@ -69,9 +69,9 @@ gdb_test "skip function baz" "Function baz will be skipped when stepping\." gdb_test "skip enable 999" "No skiplist entries found with number 999." gdb_test "skip disable 999" "No skiplist entries found with number 999." gdb_test "skip delete 999" "No skiplist entries found with number 999." -gdb_test "skip enable a" "Args must be numbers or '\\$' variables." -gdb_test "skip disable a" "Args must be numbers or '\\$' variables." -gdb_test "skip delete a" "Args must be numbers or '\\$' variables." +gdb_test "skip enable a" "Arguments must be numbers or '\\$' variables." +gdb_test "skip disable a" "Arguments must be numbers or '\\$' variables." +gdb_test "skip delete a" "Arguments must be numbers or '\\$' variables." # Ask for info on a skiplist entry which doesn't exist. |