public inbox for archer-commits@sourceware.org
help / color / mirror / Atom feed
* [SCM] archer-sergiodj-stap: First version of the parser for the arguments.
@ 2011-03-02 19:36 sergiodj
0 siblings, 0 replies; only message in thread
From: sergiodj @ 2011-03-02 19:36 UTC (permalink / raw)
To: archer-commits
The branch, archer-sergiodj-stap has been updated
via 18d8eb5f1c053ec00eef50f80beed020f96c9aae (commit)
from aabc4832abf2d0f52a9015d274deb71c44f5981a (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email.
- Log -----------------------------------------------------------------
commit 18d8eb5f1c053ec00eef50f80beed020f96c9aae
Author: Sergio Durigan Junior <sergiodj@redhat.com>
Date: Wed Mar 2 16:35:39 2011 -0300
First version of the parser for the arguments.
This first version is not ready yet, but it already works for some
simple expressions.
-----------------------------------------------------------------------
Summary of changes:
gdb/stap-probe.c | 282 ++++++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 244 insertions(+), 38 deletions(-)
First 500 lines of diff:
diff --git a/gdb/stap-probe.c b/gdb/stap-probe.c
index 56b48f6..c23cb96 100644
--- a/gdb/stap-probe.c
+++ b/gdb/stap-probe.c
@@ -33,19 +33,22 @@
#include <ctype.h>
-enum stap_arg_offset
+enum stap_arg_bitness
{
- STAP_ARG_OFFSET_UNDEFINED,
- STAP_ARG_OFFSET_32BIT_UNSIGNED,
- STAP_ARG_OFFSET_32BIT_SIGNED,
- STAP_ARG_OFFSET_64BIT_UNSIGNED,
- STAP_ARG_OFFSET_64BIT_SIGNED,
+ STAP_ARG_BITNESS_UNDEFINED,
+ STAP_ARG_BITNESS_32BIT_UNSIGNED,
+ STAP_ARG_BITNESS_32BIT_SIGNED,
+ STAP_ARG_BITNESS_64BIT_UNSIGNED,
+ STAP_ARG_BITNESS_64BIT_SIGNED,
};
struct stap_probe_arg
{
- enum stap_arg_offset offset;
- /* FIXME Add more fields to this struct. */
+ /* The bitness of this argument. */
+ enum stap_arg_bitness bitness;
+
+ /* The string representing this argument. */
+ char *arg_str;
};
#define STAP_MAX_ARGS 10
@@ -66,18 +69,206 @@ struct stap_args_info
In this case, the number of arguments for this probe is zero, so that's
why this variable is useful. */
static struct stap_args_info dummy_stap_args_info =
- { 0, NULL };
+ { 0, NULL, NULL };
+
+static void
+ep_skip_leading_whitespace (char **s)
+{
+ if ((s == NULL) || (*s == NULL))
+ return;
+ while (isspace (**s))
+ *s += 1;
+}
+
+static void
+stap_skip_whitespace_cond (char **s, int inside_paren)
+{
+ if (inside_paren)
+ ep_skip_leading_whitespace (s);
+}
+
+static int
+stap_parse_arg (const char **p)
+{
+ char *cur = (char *) *p;
+ int done = 0;
+ int paren_open = 0;
+
+ while (!done)
+ {
+ switch (*cur)
+ {
+ case ' ': case 0:
+ /* If we're here, then we have already parsed everything
+ from this argument. */
+ if (paren_open)
+ return 0;
+ done = 1;
+ break;
+
+ case '(':
+ ++paren_open;
+ ++cur;
+ stap_skip_whitespace_cond (&cur, paren_open);
+ break;
+
+ case ')':
+ if (!paren_open)
+ return 0;
+
+ --paren_open;
+ ++cur;
+ if (paren_open)
+ ep_skip_leading_whitespace (&cur);
+ break;
+
+ case '+': case '-':
+// break;
+
+ case '*': case '/':
+ case '>': case '<': case '|': case '&':
+ case '^': case '!':
+ {
+ char c = *cur;
+
+ ++cur;
+ switch (*cur)
+ {
+ case '>':
+ if (c != '<' && c != '>')
+ return 0;
+
+ ++cur;
+ break;
+
+ case '<':
+ if (c != '<')
+ return 0;
+
+ ++cur;
+ break;
+
+ case '=':
+ if (c != '=' && c != '<' && c != '>' && c != '!')
+ return 0;
+
+ ++cur;
+ break;
+
+ case '|':
+ if (c != '|')
+ return 0;
+
+ ++cur;
+ break;
+
+ case '&':
+ if (c != '&')
+ return 0;
+
+ ++cur;
+ break;
+ }
+ /* Infix operators take two arguments, one on either
+ side. Skipping the whitespaces that may happen on the
+ right side. */
+ stap_skip_whitespace_cond (&cur, paren_open);
+ }
+ break;
+
+ case '%':
+ {
+ ++cur;
+ stap_skip_whitespace_cond (&cur, paren_open);
+ if (*cur >= 'a' && *cur <= 'z')
+ {
+ /* We're dealing with a register name. */
+ while ((*cur >= 'a' && *cur <= 'z')
+ || (*cur >= '0' && *cur <= '9'))
+ ++cur;
+
+ stap_skip_whitespace_cond (&cur, paren_open);
+
+ /* Some registers (e.g. floating-point register stack
+ registers on Intel i386) have the following syntax:
+
+ `%st(0)', `%st(1)', and so on.
+
+ So it's ok to expect parenthesis here. */
+ if (*cur == '(')
+ {
+ ++cur;
+ stap_skip_whitespace_cond (&cur, paren_open);
+ if (*cur < '0' || *cur > '9')
+ /* This is an error, since we only expect numbers
+ inside this parenthesis. */
+ return 0;
+ ++cur;
+ stap_skip_whitespace_cond (&cur, paren_open);
+ if (*cur != ')')
+ /* We only expect one number. */
+ return 0;
+ ++cur;
+ stap_skip_whitespace_cond (&cur, paren_open);
+ }
+ }
+ }
+ break;
+
+ case '$':
+ {
+ /* This is an integer constant. */
+ ++cur;
+ stap_skip_whitespace_cond (&cur, paren_open);
+
+ while (isdigit (*cur))
+ ++cur;
+ }
+ break;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ {
+ /* Number. */
+ while (isdigit (*cur))
+ ++cur;
+
+ stap_skip_whitespace_cond (&cur, paren_open);
+ }
+ break;
+ }
+ }
+
+ *p = cur;
+
+ return 1;
+}
+
+static void
+stap_free_args_info (void *args_info_ptr)
+{
+ struct stap_args_info *a = (struct stap_args_info *) args_info_ptr;
+ int i;
+
+ for (i = 0; i < STAP_MAX_ARGS; i++)
+ if (a->arg->arg_str)
+ xfree (a->arg->arg_str);
+
+ xfree (a->arg);
+ xfree (a);
+}
void
stap_parse_probe_arguments (struct stap_probe *probe)
{
struct stap_args_info *args_info;
+ struct cleanup *back_to;
const char *cur = probe->args;
int current_arg = -1;
enum
{
NEW_ARG,
- OFFSET,
+ BITNESS,
PARSE_ARG,
} current_state;
@@ -88,7 +279,8 @@ stap_parse_probe_arguments (struct stap_probe *probe)
return;
args_info = xmalloc (sizeof (struct stap_args_info));
- args_info->arg = xmalloc (STAP_MAX_ARGS * sizeof (struct stap_probe_arg));
+ back_to = make_cleanup (stap_free_args_info, args_info);
+ args_info->arg = xcalloc (STAP_MAX_ARGS, sizeof (struct stap_probe_arg));
/* Ok, let's start. */
current_state = NEW_ARG;
@@ -103,17 +295,16 @@ stap_parse_probe_arguments (struct stap_probe *probe)
if (current_arg >= STAP_MAX_ARGS)
{
/*complaint*/
- xfree (args_info->arg);
- xfree (args_info);
+ do_cleanups (back_to);
return;
}
- current_state = OFFSET;
+ current_state = BITNESS;
break;
- case OFFSET:
+ case BITNESS:
{
- enum stap_arg_offset o;
+ enum stap_arg_bitness b;
int got_minus = 0;
/* We expect to find something like:
@@ -127,8 +318,8 @@ stap_parse_probe_arguments (struct stap_probe *probe)
&& cur[1] != '@')
{
current_state = PARSE_ARG;
- args_info->arg[current_arg].offset
- = STAP_ARG_OFFSET_UNDEFINED;
+ args_info->arg[current_arg].bitness
+ = STAP_ARG_BITNESS_UNDEFINED;
break;
}
@@ -140,23 +331,22 @@ stap_parse_probe_arguments (struct stap_probe *probe)
}
if (*cur == '4')
- o = got_minus ? STAP_ARG_OFFSET_32BIT_SIGNED
- : STAP_ARG_OFFSET_32BIT_UNSIGNED;
+ b = got_minus ? STAP_ARG_BITNESS_32BIT_SIGNED
+ : STAP_ARG_BITNESS_32BIT_UNSIGNED;
else if (*cur == '8')
- o = got_minus ? STAP_ARG_OFFSET_64BIT_SIGNED
- : STAP_ARG_OFFSET_64BIT_UNSIGNED;
+ b = got_minus ? STAP_ARG_BITNESS_64BIT_SIGNED
+ : STAP_ARG_BITNESS_64BIT_UNSIGNED;
else
{
/*FIXME complaint*/
/* We have an error, because we don't expect anything
except 4 and 8. */
- xfree (args_info->arg);
- xfree (args_info);
+ do_cleanups (back_to);
return;
}
- args_info->arg[current_arg].offset = o;
+ args_info->arg[current_arg].bitness = b;
/* Discard the number and the `@' sign. */
cur += 2;
/* Move on. */
@@ -165,12 +355,35 @@ stap_parse_probe_arguments (struct stap_probe *probe)
break;
case PARSE_ARG:
- /* FIXME THIS IS JUST FOR TESTING */
- while (*cur++ != ' ');
- /* Start it over again. */
- current_state = NEW_ARG;
+ {
+ const char *start = cur;
+
+ if (!stap_parse_arg (&cur))
+ {
+ /* We have tried to parse this argument, but it's
+ malformed. This is an error. */
+ do_cleanups (back_to);
+ return;
+ }
+
+ args_info->arg[current_arg].arg_str
+ = savestring (start, cur - start);
+ /* Start it over again. */
+ ep_skip_leading_whitespace ((char **) &cur);
+ current_state = NEW_ARG;
+ }
break;
}
+
+ if (!*cur && current_state != NEW_ARG)
+ {
+ /* We reached the end of the argument string, but we're
+ still in the middle of the process of parsing an argument.
+ It means the argument string is malformed. */
+ /* complaint*/
+ do_cleanups (back_to);
+ return;
+ }
}
args_info->n_args = current_arg + 1;
@@ -180,6 +393,8 @@ stap_parse_probe_arguments (struct stap_probe *probe)
args_info->probe = probe;
probe->parsed_args = args_info;
+
+ discard_cleanups (back_to);
}
int
@@ -203,15 +418,6 @@ stap_free_parsed_args (struct stap_args_info *parsed_args)
xfree (parsed_args);
}
-static void
-ep_skip_leading_whitespace (char **s)
-{
- if ((s == NULL) || (*s == NULL))
- return;
- while (isspace (**s))
- *s += 1;
-}
-
/* A helper function to extract an argument from *ARG. An argument is
delimited by whitespace. The return value is either NULL if no
argument was found, or an xmalloc'd string. */
hooks/post-receive
--
Repository for Project Archer.
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2011-03-02 19:36 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-03-02 19:36 [SCM] archer-sergiodj-stap: First version of the parser for the arguments sergiodj
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).