public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] Extend SystemTap SDT probe argument parser
@ 2013-12-11  3:56 Sergio Durigan Junior
  2013-12-16 17:01 ` Sergio Durigan Junior
  2013-12-17 11:03 ` Pedro Alves
  0 siblings, 2 replies; 10+ messages in thread
From: Sergio Durigan Junior @ 2013-12-11  3:56 UTC (permalink / raw)
  To: GDB Patches; +Cc: Sergio Durigan Junior

This patch extends the current generic parser for SystemTap SDT probe
arguments.  It can be almost considered a cleanup, but the main point of
it is actually to allow the generic parser to accept multiple prefixes
and suffixes for the its operands (i.e., integers, register names, and
register indirection).

I have chosen to implement this as a list of const strings, which needs
to be declared as "static const char *const *", and is provided to
gdbarch on initialization.  I think it is cleaner to implement it this
way, but for a moment I wondered whether demanding the variables to be
declared as "static" is a good idea...  After some thought and
discussion, I decided to leave it as is.

This patch is actually a preparation for an upcoming patch for ARM,
which implements the support for multiple integer prefixes (as defined
by ARM's asm spec).  And AArch64 will also need this, for the same
reason.

This patch was regtested on all architectures that it touches (i.e.,
i386, x86_64, ARM, PPC/PPC64, s390x and IA-64).  No regressions were found.

2013-12-11  Sergio Durigan Junior  <sergiodj@redhat.com>

	* amd64-tdep.c (amd64_init_abi): Declare SystemTap SDT probe
	argument prefixes and suffixes.  Initialize gdbarch with them.
	* arm-linux-tdep.c (arm_linux_init_abi): Likewise.
	* gdbarch.c: Regenerate.
	* gdbarch.h: Regenerate.
	* gdbarch.sh (stap_integer_prefix, stap_integer_suffix)
	(stap_register_prefix, stap_register_suffix)
	(stap_register_indirection_prefix)
	(stap_register_indirection_suffix): Declare as "const char *const
	*" instead of "const char *".  Adjust printing function.
	(pstring_list): New function.
	* i386-tdep.c (i386_elf_init_abi): Declare SystemTap SDT probe
	argument prefixes and suffixes.  Initialize gdbarch with them.
	* ia64-linux-tdep.c (ia64_linux_init_abi): Likewise.
	* ppc-linux-tdep.c (ppc_linux_init_abi): Likewise.
	* s390-linux-tdep.c (s390_gdbarch_init): Likewise.
	* stap-probe.c (stap_is_generic_prefix): New function.
	(stap_is_register_prefix): Likewise.
	(stap_is_register_indirection_prefix): Likewise.
	(stap_is_integer_prefix): Likewise.
	(stap_generic_check_suffix): Likewise.
	(stap_check_integer_suffix): Likewise.
	(stap_check_register_suffix): Likewise.
	(stap_check_register_indirection_suffix): Likewise.
	(stap_parse_register_operand): Remove unecessary declarations for
	variables holding prefix and suffix information.  Use the new
	functions listed above for checking for prefixes and suffixes.
	(stap_parse_single_operand): Likewise.
---
 gdb/ChangeLog         |  31 ++++++
 gdb/amd64-tdep.c      |  14 ++-
 gdb/arm-linux-tdep.c  |  14 ++-
 gdb/gdbarch.c         |  71 +++++++-----
 gdb/gdbarch.h         |  76 +++++++++----
 gdb/gdbarch.sh        |  79 +++++++++++---
 gdb/i386-tdep.c       |  15 ++-
 gdb/ia64-linux-tdep.c |  11 +-
 gdb/ppc-linux-tdep.c  |  11 +-
 gdb/s390-linux-tdep.c |  11 +-
 gdb/stap-probe.c      | 291 +++++++++++++++++++++++++++++++++++++-------------
 11 files changed, 466 insertions(+), 158 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 35a1d73..efda387 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,36 @@
 2013-12-11  Sergio Durigan Junior  <sergiodj@redhat.com>
 
+	* amd64-tdep.c (amd64_init_abi): Declare SystemTap SDT probe
+	argument prefixes and suffixes.  Initialize gdbarch with them.
+	* arm-linux-tdep.c (arm_linux_init_abi): Likewise.
+	* gdbarch.c: Regenerate.
+	* gdbarch.h: Regenerate.
+	* gdbarch.sh (stap_integer_prefix, stap_integer_suffix)
+	(stap_register_prefix, stap_register_suffix)
+	(stap_register_indirection_prefix)
+	(stap_register_indirection_suffix): Declare as "const char *const
+	*" instead of "const char *".  Adjust printing function.
+	(pstring_list): New function.
+	* i386-tdep.c (i386_elf_init_abi): Declare SystemTap SDT probe
+	argument prefixes and suffixes.  Initialize gdbarch with them.
+	* ia64-linux-tdep.c (ia64_linux_init_abi): Likewise.
+	* ppc-linux-tdep.c (ppc_linux_init_abi): Likewise.
+	* s390-linux-tdep.c (s390_gdbarch_init): Likewise.
+	* stap-probe.c (stap_is_generic_prefix): New function.
+	(stap_is_register_prefix): Likewise.
+	(stap_is_register_indirection_prefix): Likewise.
+	(stap_is_integer_prefix): Likewise.
+	(stap_generic_check_suffix): Likewise.
+	(stap_check_integer_suffix): Likewise.
+	(stap_check_register_suffix): Likewise.
+	(stap_check_register_indirection_suffix): Likewise.
+	(stap_parse_register_operand): Remove unecessary declarations for
+	variables holding prefix and suffix information.  Use the new
+	functions listed above for checking for prefixes and suffixes.
+	(stap_parse_single_operand): Likewise.
+
+2013-12-11  Sergio Durigan Junior  <sergiodj@redhat.com>
+
 	* break-catch-throw.c (fetch_probe_arguments): Pass selected frame
 	to get_probe_argument_count and evaluate_probe_argument.
 	* probe.c (get_probe_argument_count): Adjust declaration to accept
diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
index 19968fc..ec67f06 100644
--- a/gdb/amd64-tdep.c
+++ b/gdb/amd64-tdep.c
@@ -2832,6 +2832,10 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   const struct target_desc *tdesc = info.target_desc;
+  static const char *const stap_integer_prefix[] = { "$", NULL };
+  static const char *const stap_register_prefix[] = { "%", NULL };
+  static const char *const stap_register_indirection_prefix[] = { "(", NULL };
+  static const char *const stap_register_indirection_suffix[] = { ")", NULL };
 
   /* AMD64 generally uses `fxsave' instead of `fsave' for saving its
      floating-point registers.  */
@@ -2944,10 +2948,12 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   set_gdbarch_gen_return_address (gdbarch, amd64_gen_return_address);
 
   /* SystemTap variables and functions.  */
-  set_gdbarch_stap_integer_prefix (gdbarch, "$");
-  set_gdbarch_stap_register_prefix (gdbarch, "%");
-  set_gdbarch_stap_register_indirection_prefix (gdbarch, "(");
-  set_gdbarch_stap_register_indirection_suffix (gdbarch, ")");
+  set_gdbarch_stap_integer_prefix (gdbarch, stap_integer_prefix);
+  set_gdbarch_stap_register_prefix (gdbarch, stap_register_prefix);
+  set_gdbarch_stap_register_indirection_prefix (gdbarch,
+					    stap_register_indirection_prefix);
+  set_gdbarch_stap_register_indirection_suffix (gdbarch,
+					    stap_register_indirection_suffix);
   set_gdbarch_stap_is_single_operand (gdbarch,
 				      i386_stap_is_single_operand);
   set_gdbarch_stap_parse_special_token (gdbarch,
diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c
index 9deed10..4f385b5 100644
--- a/gdb/arm-linux-tdep.c
+++ b/gdb/arm-linux-tdep.c
@@ -1235,6 +1235,10 @@ static void
 arm_linux_init_abi (struct gdbarch_info info,
 		    struct gdbarch *gdbarch)
 {
+  static const char *const stap_integer_prefix[] = { "#", NULL };
+  static const char *const stap_register_prefix[] = { "r", NULL };
+  static const char *const stap_register_indirection_prefix[] = { "[", NULL };
+  static const char *const stap_register_indirection_suffix[] = { "]", NULL };
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   linux_init_abi (info, gdbarch);
@@ -1334,10 +1338,12 @@ arm_linux_init_abi (struct gdbarch_info info,
   set_gdbarch_process_record (gdbarch, arm_process_record);
 
   /* SystemTap functions.  */
-  set_gdbarch_stap_integer_prefix (gdbarch, "#");
-  set_gdbarch_stap_register_prefix (gdbarch, "r");
-  set_gdbarch_stap_register_indirection_prefix (gdbarch, "[");
-  set_gdbarch_stap_register_indirection_suffix (gdbarch, "]");
+  set_gdbarch_stap_integer_prefix (gdbarch, stap_integer_prefix);
+  set_gdbarch_stap_register_prefix (gdbarch, stap_register_prefix);
+  set_gdbarch_stap_register_indirection_prefix (gdbarch,
+					    stap_register_indirection_prefix);
+  set_gdbarch_stap_register_indirection_suffix (gdbarch,
+					    stap_register_indirection_suffix);
   set_gdbarch_stap_gdb_register_prefix (gdbarch, "r");
   set_gdbarch_stap_is_single_operand (gdbarch, arm_stap_is_single_operand);
   set_gdbarch_stap_parse_special_token (gdbarch,
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index fb3595f..4594f20 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -86,6 +86,29 @@ pstring (const char *string)
   return string;
 }
 
+static char *
+pstring_list (const char *const *list)
+{
+  static char ret[100];
+  const char *const *p;
+  int offset = 0;
+
+  if (list == NULL)
+    return "(null)";
+
+  ret[0] = '\0';
+  for (p = list; *p != NULL && offset < sizeof (ret); ++p)
+    {
+      xsnprintf (ret + offset, sizeof (ret) - offset, "%s, ", *p);
+      offset += 2 + strlen (*p);
+    }
+
+  if (offset > 0)
+    ret[offset - 2] = '\0';
+
+  return ret;
+}
+
 
 /* Maintain the struct gdbarch object.  */
 
@@ -265,12 +288,12 @@ struct gdbarch
   gdbarch_get_siginfo_type_ftype *get_siginfo_type;
   gdbarch_record_special_symbol_ftype *record_special_symbol;
   gdbarch_get_syscall_number_ftype *get_syscall_number;
-  const char * stap_integer_prefix;
-  const char * stap_integer_suffix;
-  const char * stap_register_prefix;
-  const char * stap_register_suffix;
-  const char * stap_register_indirection_prefix;
-  const char * stap_register_indirection_suffix;
+  const char *const * stap_integer_prefix;
+  const char *const * stap_integer_suffix;
+  const char *const * stap_register_prefix;
+  const char *const * stap_register_suffix;
+  const char *const * stap_register_indirection_prefix;
+  const char *const * stap_register_indirection_suffix;
   const char * stap_gdb_register_prefix;
   const char * stap_gdb_register_suffix;
   gdbarch_stap_is_single_operand_ftype *stap_is_single_operand;
@@ -1352,10 +1375,10 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
                       pstring (gdbarch->stap_gdb_register_suffix));
   fprintf_unfiltered (file,
                       "gdbarch_dump: stap_integer_prefix = %s\n",
-                      pstring (gdbarch->stap_integer_prefix));
+                      pstring_list (gdbarch->stap_integer_prefix));
   fprintf_unfiltered (file,
                       "gdbarch_dump: stap_integer_suffix = %s\n",
-                      pstring (gdbarch->stap_integer_suffix));
+                      pstring_list (gdbarch->stap_integer_suffix));
   fprintf_unfiltered (file,
                       "gdbarch_dump: gdbarch_stap_is_single_operand_p() = %d\n",
                       gdbarch_stap_is_single_operand_p (gdbarch));
@@ -1370,16 +1393,16 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
                       host_address_to_string (gdbarch->stap_parse_special_token));
   fprintf_unfiltered (file,
                       "gdbarch_dump: stap_register_indirection_prefix = %s\n",
-                      pstring (gdbarch->stap_register_indirection_prefix));
+                      pstring_list (gdbarch->stap_register_indirection_prefix));
   fprintf_unfiltered (file,
                       "gdbarch_dump: stap_register_indirection_suffix = %s\n",
-                      pstring (gdbarch->stap_register_indirection_suffix));
+                      pstring_list (gdbarch->stap_register_indirection_suffix));
   fprintf_unfiltered (file,
                       "gdbarch_dump: stap_register_prefix = %s\n",
-                      pstring (gdbarch->stap_register_prefix));
+                      pstring_list (gdbarch->stap_register_prefix));
   fprintf_unfiltered (file,
                       "gdbarch_dump: stap_register_suffix = %s\n",
-                      pstring (gdbarch->stap_register_suffix));
+                      pstring_list (gdbarch->stap_register_suffix));
   fprintf_unfiltered (file,
                       "gdbarch_dump: gdbarch_static_transform_name_p() = %d\n",
                       gdbarch_static_transform_name_p (gdbarch));
@@ -4004,7 +4027,7 @@ set_gdbarch_get_syscall_number (struct gdbarch *gdbarch,
   gdbarch->get_syscall_number = get_syscall_number;
 }
 
-const char *
+const char *const *
 gdbarch_stap_integer_prefix (struct gdbarch *gdbarch)
 {
   gdb_assert (gdbarch != NULL);
@@ -4016,12 +4039,12 @@ gdbarch_stap_integer_prefix (struct gdbarch *gdbarch)
 
 void
 set_gdbarch_stap_integer_prefix (struct gdbarch *gdbarch,
-                                 const char * stap_integer_prefix)
+                                 const char *const * stap_integer_prefix)
 {
   gdbarch->stap_integer_prefix = stap_integer_prefix;
 }
 
-const char *
+const char *const *
 gdbarch_stap_integer_suffix (struct gdbarch *gdbarch)
 {
   gdb_assert (gdbarch != NULL);
@@ -4033,12 +4056,12 @@ gdbarch_stap_integer_suffix (struct gdbarch *gdbarch)
 
 void
 set_gdbarch_stap_integer_suffix (struct gdbarch *gdbarch,
-                                 const char * stap_integer_suffix)
+                                 const char *const * stap_integer_suffix)
 {
   gdbarch->stap_integer_suffix = stap_integer_suffix;
 }
 
-const char *
+const char *const *
 gdbarch_stap_register_prefix (struct gdbarch *gdbarch)
 {
   gdb_assert (gdbarch != NULL);
@@ -4050,12 +4073,12 @@ gdbarch_stap_register_prefix (struct gdbarch *gdbarch)
 
 void
 set_gdbarch_stap_register_prefix (struct gdbarch *gdbarch,
-                                  const char * stap_register_prefix)
+                                  const char *const * stap_register_prefix)
 {
   gdbarch->stap_register_prefix = stap_register_prefix;
 }
 
-const char *
+const char *const *
 gdbarch_stap_register_suffix (struct gdbarch *gdbarch)
 {
   gdb_assert (gdbarch != NULL);
@@ -4067,12 +4090,12 @@ gdbarch_stap_register_suffix (struct gdbarch *gdbarch)
 
 void
 set_gdbarch_stap_register_suffix (struct gdbarch *gdbarch,
-                                  const char * stap_register_suffix)
+                                  const char *const * stap_register_suffix)
 {
   gdbarch->stap_register_suffix = stap_register_suffix;
 }
 
-const char *
+const char *const *
 gdbarch_stap_register_indirection_prefix (struct gdbarch *gdbarch)
 {
   gdb_assert (gdbarch != NULL);
@@ -4084,12 +4107,12 @@ gdbarch_stap_register_indirection_prefix (struct gdbarch *gdbarch)
 
 void
 set_gdbarch_stap_register_indirection_prefix (struct gdbarch *gdbarch,
-                                              const char * stap_register_indirection_prefix)
+                                              const char *const * stap_register_indirection_prefix)
 {
   gdbarch->stap_register_indirection_prefix = stap_register_indirection_prefix;
 }
 
-const char *
+const char *const *
 gdbarch_stap_register_indirection_suffix (struct gdbarch *gdbarch)
 {
   gdb_assert (gdbarch != NULL);
@@ -4101,7 +4124,7 @@ gdbarch_stap_register_indirection_suffix (struct gdbarch *gdbarch)
 
 void
 set_gdbarch_stap_register_indirection_suffix (struct gdbarch *gdbarch,
-                                              const char * stap_register_indirection_suffix)
+                                              const char *const * stap_register_indirection_suffix)
 {
   gdbarch->stap_register_indirection_suffix = stap_register_indirection_suffix;
 }
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index b58efc8..1d60f28 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -1034,37 +1034,57 @@ extern LONGEST gdbarch_get_syscall_number (struct gdbarch *gdbarch, ptid_t ptid)
 extern void set_gdbarch_get_syscall_number (struct gdbarch *gdbarch, gdbarch_get_syscall_number_ftype *get_syscall_number);
 
 /* SystemTap related fields and functions.
-   Prefix used to mark an integer constant on the architecture's assembly
+   Prefix(es) used to mark an integer constant on the architecture's assembly.
    For example, on x86 integer constants are written as:
   
     $10 ;; integer constant 10
   
-   in this case, this prefix would be the character `$'. */
+   in this case, this prefix would be the character `$'.
+  
+   This variable must be declared as `static const char *const var[]',
+   and must also be NUL-terminated, like the following example:
+  
+     static const char *const example[] = { "prefix1", "prefix2", NULL }; */
 
-extern const char * gdbarch_stap_integer_prefix (struct gdbarch *gdbarch);
-extern void set_gdbarch_stap_integer_prefix (struct gdbarch *gdbarch, const char * stap_integer_prefix);
+extern const char *const * gdbarch_stap_integer_prefix (struct gdbarch *gdbarch);
+extern void set_gdbarch_stap_integer_prefix (struct gdbarch *gdbarch, const char *const * stap_integer_prefix);
 
-/* Suffix used to mark an integer constant on the architecture's assembly. */
+/* Suffix(es) used to mark an integer constant on the architecture's assembly.
+  
+   This variable must be declared as `static const char *const var[]',
+   and must also be NUL-terminated, like the following example:
+  
+     static const char *const example[] = { "prefix1", "prefix2", NULL }; */
 
-extern const char * gdbarch_stap_integer_suffix (struct gdbarch *gdbarch);
-extern void set_gdbarch_stap_integer_suffix (struct gdbarch *gdbarch, const char * stap_integer_suffix);
+extern const char *const * gdbarch_stap_integer_suffix (struct gdbarch *gdbarch);
+extern void set_gdbarch_stap_integer_suffix (struct gdbarch *gdbarch, const char *const * stap_integer_suffix);
 
-/* Prefix used to mark a register name on the architecture's assembly.
+/* Prefix(es) used to mark a register name on the architecture's assembly.
    For example, on x86 the register name is written as:
   
     %eax ;; register eax
   
-   in this case, this prefix would be the character `%'. */
+   in this case, this prefix would be the character `%'.
+  
+   This variable must be declared as `static const char *const var[]',
+   and must also be NUL-terminated, like the following example:
+  
+     static const char *const example[] = { "prefix1", "prefix2", NULL }; */
 
-extern const char * gdbarch_stap_register_prefix (struct gdbarch *gdbarch);
-extern void set_gdbarch_stap_register_prefix (struct gdbarch *gdbarch, const char * stap_register_prefix);
+extern const char *const * gdbarch_stap_register_prefix (struct gdbarch *gdbarch);
+extern void set_gdbarch_stap_register_prefix (struct gdbarch *gdbarch, const char *const * stap_register_prefix);
 
-/* Suffix used to mark a register name on the architecture's assembly */
+/* Suffix(es) used to mark a register name on the architecture's assembly
+  
+   This variable must be declared as `static const char *const var[]',
+   and must also be NUL-terminated, like the following example:
+  
+     static const char *const example[] = { "prefix1", "prefix2", NULL }; */
 
-extern const char * gdbarch_stap_register_suffix (struct gdbarch *gdbarch);
-extern void set_gdbarch_stap_register_suffix (struct gdbarch *gdbarch, const char * stap_register_suffix);
+extern const char *const * gdbarch_stap_register_suffix (struct gdbarch *gdbarch);
+extern void set_gdbarch_stap_register_suffix (struct gdbarch *gdbarch, const char *const * stap_register_suffix);
 
-/* Prefix used to mark a register indirection on the architecture's assembly.
+/* Prefix(es) used to mark a register indirection on the architecture's assembly.
    For example, on x86 the register indirection is written as:
   
     (%eax) ;; indirecting eax
@@ -1072,12 +1092,17 @@ extern void set_gdbarch_stap_register_suffix (struct gdbarch *gdbarch, const cha
    in this case, this prefix would be the charater `('.
   
    Please note that we use the indirection prefix also for register
-   displacement, e.g., `4(%eax)' on x86. */
+   displacement, e.g., `4(%eax)' on x86.
+  
+   This variable must be declared as `static const char *const var[]',
+   and must also be NUL-terminated, like the following example:
+  
+     static const char *const example = { "prefix1", "prefix2", NULL }; */
 
-extern const char * gdbarch_stap_register_indirection_prefix (struct gdbarch *gdbarch);
-extern void set_gdbarch_stap_register_indirection_prefix (struct gdbarch *gdbarch, const char * stap_register_indirection_prefix);
+extern const char *const * gdbarch_stap_register_indirection_prefix (struct gdbarch *gdbarch);
+extern void set_gdbarch_stap_register_indirection_prefix (struct gdbarch *gdbarch, const char *const * stap_register_indirection_prefix);
 
-/* Suffix used to mark a register indirection on the architecture's assembly.
+/* Suffix(es) used to mark a register indirection on the architecture's assembly.
    For example, on x86 the register indirection is written as:
   
     (%eax) ;; indirecting eax
@@ -1085,12 +1110,17 @@ extern void set_gdbarch_stap_register_indirection_prefix (struct gdbarch *gdbarc
    in this case, this prefix would be the charater `)'.
   
    Please note that we use the indirection suffix also for register
-   displacement, e.g., `4(%eax)' on x86. */
+   displacement, e.g., `4(%eax)' on x86.
+  
+   This variable must be declared as `static const char *const var[]',
+   and must also be NUL-terminated, like the following example:
+  
+     static const char *const example = { "prefix1", "prefix2", NULL }; */
 
-extern const char * gdbarch_stap_register_indirection_suffix (struct gdbarch *gdbarch);
-extern void set_gdbarch_stap_register_indirection_suffix (struct gdbarch *gdbarch, const char * stap_register_indirection_suffix);
+extern const char *const * gdbarch_stap_register_indirection_suffix (struct gdbarch *gdbarch);
+extern void set_gdbarch_stap_register_indirection_suffix (struct gdbarch *gdbarch, const char *const * stap_register_indirection_suffix);
 
-/* Prefix used to name a register using GDB's nomenclature.
+/* Prefix(es) used to name a register using GDB's nomenclature.
   
    For example, on PPC a register is represented by a number in the assembly
    language (e.g., `10' is the 10th general-purpose register).  However,
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index a678a78..1d11b31 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -826,29 +826,49 @@ M:LONGEST:get_syscall_number:ptid_t ptid:ptid
 
 # SystemTap related fields and functions.
 
-# Prefix used to mark an integer constant on the architecture's assembly
+# Prefix(es) used to mark an integer constant on the architecture's assembly.
 # For example, on x86 integer constants are written as:
 #
 #  \$10 ;; integer constant 10
 #
 # in this case, this prefix would be the character \`\$\'.
-v:const char *:stap_integer_prefix:::0:0::0:pstring (gdbarch->stap_integer_prefix)
+#
+# This variable must be declared as \`static const char *const var\[\]\',
+# and must also be NUL-terminated, like the following example:
+#
+#   static const char *const example\[\] \= \{ "prefix1", "prefix2", NULL \};
+v:const char *const *:stap_integer_prefix:::0:0::0:pstring_list (gdbarch->stap_integer_prefix)
 
-# Suffix used to mark an integer constant on the architecture's assembly.
-v:const char *:stap_integer_suffix:::0:0::0:pstring (gdbarch->stap_integer_suffix)
+# Suffix(es) used to mark an integer constant on the architecture's assembly.
+#
+# This variable must be declared as \`static const char *const var\[\]\',
+# and must also be NUL-terminated, like the following example:
+#
+#   static const char *const example\[\] \= \{ "prefix1", "prefix2", NULL \};
+v:const char *const *:stap_integer_suffix:::0:0::0:pstring_list (gdbarch->stap_integer_suffix)
 
-# Prefix used to mark a register name on the architecture's assembly.
+# Prefix(es) used to mark a register name on the architecture's assembly.
 # For example, on x86 the register name is written as:
 #
 #  \%eax ;; register eax
 #
 # in this case, this prefix would be the character \`\%\'.
-v:const char *:stap_register_prefix:::0:0::0:pstring (gdbarch->stap_register_prefix)
+#
+# This variable must be declared as \`static const char *const var\[\]\',
+# and must also be NUL-terminated, like the following example:
+#
+#   static const char *const example\[\] \= \{ "prefix1", "prefix2", NULL \};
+v:const char *const *:stap_register_prefix:::0:0::0:pstring_list (gdbarch->stap_register_prefix)
 
-# Suffix used to mark a register name on the architecture's assembly
-v:const char *:stap_register_suffix:::0:0::0:pstring (gdbarch->stap_register_suffix)
+# Suffix(es) used to mark a register name on the architecture's assembly
+#
+# This variable must be declared as \`static const char *const var\[\]\',
+# and must also be NUL-terminated, like the following example:
+#
+#   static const char *const example\[\] \= \{ "prefix1", "prefix2", NULL \};
+v:const char *const *:stap_register_suffix:::0:0::0:pstring_list (gdbarch->stap_register_suffix)
 
-# Prefix used to mark a register indirection on the architecture's assembly.
+# Prefix(es) used to mark a register indirection on the architecture's assembly.
 # For example, on x86 the register indirection is written as:
 #
 #  \(\%eax\) ;; indirecting eax
@@ -857,9 +877,14 @@ v:const char *:stap_register_suffix:::0:0::0:pstring (gdbarch->stap_register_suf
 #
 # Please note that we use the indirection prefix also for register
 # displacement, e.g., \`4\(\%eax\)\' on x86.
-v:const char *:stap_register_indirection_prefix:::0:0::0:pstring (gdbarch->stap_register_indirection_prefix)
+#
+# This variable must be declared as \`static const char *const var\[\]\',
+# and must also be NUL-terminated, like the following example:
+#
+#   static const char *const example \= \{ "prefix1", "prefix2", NULL \};
+v:const char *const *:stap_register_indirection_prefix:::0:0::0:pstring_list (gdbarch->stap_register_indirection_prefix)
 
-# Suffix used to mark a register indirection on the architecture's assembly.
+# Suffix(es) used to mark a register indirection on the architecture's assembly.
 # For example, on x86 the register indirection is written as:
 #
 #  \(\%eax\) ;; indirecting eax
@@ -868,9 +893,14 @@ v:const char *:stap_register_indirection_prefix:::0:0::0:pstring (gdbarch->stap_
 #
 # Please note that we use the indirection suffix also for register
 # displacement, e.g., \`4\(\%eax\)\' on x86.
-v:const char *:stap_register_indirection_suffix:::0:0::0:pstring (gdbarch->stap_register_indirection_suffix)
+#
+# This variable must be declared as \`static const char *const var\[\]\',
+# and must also be NUL-terminated, like the following example:
+#
+#   static const char *const example \= \{ "prefix1", "prefix2", NULL \};
+v:const char *const *:stap_register_indirection_suffix:::0:0::0:pstring_list (gdbarch->stap_register_indirection_suffix)
 
-# Prefix used to name a register using GDB's nomenclature.
+# Prefix(es) used to name a register using GDB's nomenclature.
 #
 # For example, on PPC a register is represented by a number in the assembly
 # language (e.g., \`10\' is the 10th general-purpose register).  However,
@@ -1481,6 +1511,29 @@ pstring (const char *string)
   return string;
 }
 
+static char *
+pstring_list (const char *const *list)
+{
+  static char ret[100];
+  const char *const *p;
+  int offset = 0;
+
+  if (list == NULL)
+    return "(null)";
+
+  ret[0] = '\0';
+  for (p = list; *p != NULL && offset < sizeof (ret); ++p)
+    {
+      xsnprintf (ret + offset, sizeof (ret) - offset, "%s, ", *p);
+      offset += 2 + strlen (*p);
+    }
+
+  if (offset > 0)
+    ret[offset - 2] = '\0';
+
+  return ret;
+}
+
 EOF
 
 # gdbarch open the gdbarch object
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index a1a4453..c01c9c2 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -3919,14 +3919,21 @@ i386_stap_parse_special_token (struct gdbarch *gdbarch,
 void
 i386_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
+  static const char *const stap_integer_prefix[] = { "$", NULL };
+  static const char *const stap_register_prefix[] = { "%", NULL };
+  static const char *const stap_register_indirection_prefix[] = { "(", NULL };
+  static const char *const stap_register_indirection_suffix[] = { ")", NULL };
+
   /* We typically use stabs-in-ELF with the SVR4 register numbering.  */
   set_gdbarch_stab_reg_to_regnum (gdbarch, i386_svr4_reg_to_regnum);
 
   /* Registering SystemTap handlers.  */
-  set_gdbarch_stap_integer_prefix (gdbarch, "$");
-  set_gdbarch_stap_register_prefix (gdbarch, "%");
-  set_gdbarch_stap_register_indirection_prefix (gdbarch, "(");
-  set_gdbarch_stap_register_indirection_suffix (gdbarch, ")");
+  set_gdbarch_stap_integer_prefix (gdbarch, stap_integer_prefix);
+  set_gdbarch_stap_register_prefix (gdbarch, stap_register_prefix);
+  set_gdbarch_stap_register_indirection_prefix (gdbarch,
+					    stap_register_indirection_prefix);
+  set_gdbarch_stap_register_indirection_suffix (gdbarch,
+					    stap_register_indirection_suffix);
   set_gdbarch_stap_is_single_operand (gdbarch,
 				      i386_stap_is_single_operand);
   set_gdbarch_stap_parse_special_token (gdbarch,
diff --git a/gdb/ia64-linux-tdep.c b/gdb/ia64-linux-tdep.c
index d1eb529..b73a5fb 100644
--- a/gdb/ia64-linux-tdep.c
+++ b/gdb/ia64-linux-tdep.c
@@ -135,6 +135,9 @@ static void
 ia64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  static const char *const stap_register_prefix[] = { "r", NULL };
+  static const char *const stap_register_indirection_prefix[] = { "[", NULL };
+  static const char *const stap_register_indirection_suffix[] = { "]", NULL };
 
   linux_init_abi (info, gdbarch);
 
@@ -157,9 +160,11 @@ ia64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
                                              svr4_fetch_objfile_link_map);
 
   /* SystemTap related.  */
-  set_gdbarch_stap_register_prefix (gdbarch, "r");
-  set_gdbarch_stap_register_indirection_prefix (gdbarch, "[");
-  set_gdbarch_stap_register_indirection_suffix (gdbarch, "]");
+  set_gdbarch_stap_register_prefix (gdbarch, stap_register_prefix);
+  set_gdbarch_stap_register_indirection_prefix (gdbarch,
+					    stap_register_indirection_prefix);
+  set_gdbarch_stap_register_indirection_suffix (gdbarch,
+					    stap_register_indirection_suffix);
   set_gdbarch_stap_gdb_register_prefix (gdbarch, "r");
   set_gdbarch_stap_is_single_operand (gdbarch,
 				      ia64_linux_stap_is_single_operand);
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
index fc09560..890e5e5 100644
--- a/gdb/ppc-linux-tdep.c
+++ b/gdb/ppc-linux-tdep.c
@@ -1245,6 +1245,9 @@ ppc_linux_init_abi (struct gdbarch_info info,
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   struct tdesc_arch_data *tdesc_data = (void *) info.tdep_info;
+  static const char *const stap_integer_prefix[] = { "i", NULL };
+  static const char *const stap_register_indirection_prefix[] = { "(", NULL };
+  static const char *const stap_register_indirection_suffix[] = { ")", NULL };
 
   linux_init_abi (info, gdbarch);
 
@@ -1263,9 +1266,11 @@ ppc_linux_init_abi (struct gdbarch_info info,
   set_gdbarch_get_syscall_number (gdbarch, ppc_linux_get_syscall_number);
 
   /* SystemTap functions.  */
-  set_gdbarch_stap_integer_prefix (gdbarch, "i");
-  set_gdbarch_stap_register_indirection_prefix (gdbarch, "(");
-  set_gdbarch_stap_register_indirection_suffix (gdbarch, ")");
+  set_gdbarch_stap_integer_prefix (gdbarch, stap_integer_prefix);
+  set_gdbarch_stap_register_indirection_prefix (gdbarch,
+					    stap_register_indirection_prefix);
+  set_gdbarch_stap_register_indirection_suffix (gdbarch,
+					    stap_register_indirection_suffix);
   set_gdbarch_stap_gdb_register_prefix (gdbarch, "r");
   set_gdbarch_stap_is_single_operand (gdbarch, ppc_stap_is_single_operand);
   set_gdbarch_stap_parse_special_token (gdbarch,
diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
index cd41de5..d521c2e 100644
--- a/gdb/s390-linux-tdep.c
+++ b/gdb/s390-linux-tdep.c
@@ -3026,6 +3026,9 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   int have_linux_v1 = 0;
   int have_linux_v2 = 0;
   int first_pseudo_reg, last_pseudo_reg;
+  static const char *const stap_register_prefix[] = { "%", NULL };
+  static const char *const stap_register_indirection_prefix[] = { "(", NULL };
+  static const char *const stap_register_indirection_suffix[] = { ")", NULL };
 
   /* Default ABI and register size.  */
   switch (info.bfd_arch_info->mach)
@@ -3358,9 +3361,11 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type);
 
   /* SystemTap functions.  */
-  set_gdbarch_stap_register_prefix (gdbarch, "%");
-  set_gdbarch_stap_register_indirection_prefix (gdbarch, "(");
-  set_gdbarch_stap_register_indirection_suffix (gdbarch, ")");
+  set_gdbarch_stap_register_prefix (gdbarch, stap_register_prefix);
+  set_gdbarch_stap_register_indirection_prefix (gdbarch,
+					    stap_register_indirection_prefix);
+  set_gdbarch_stap_register_indirection_suffix (gdbarch,
+					    stap_register_indirection_suffix);
   set_gdbarch_stap_is_single_operand (gdbarch, s390_stap_is_single_operand);
 
   return gdbarch;
diff --git a/gdb/stap-probe.c b/gdb/stap-probe.c
index 33d4569..625ec38 100644
--- a/gdb/stap-probe.c
+++ b/gdb/stap-probe.c
@@ -346,6 +346,171 @@ stap_get_expected_argument_type (struct gdbarch *gdbarch,
     }
 }
 
+/* Helper function to check for a generic list of prefixes.  Return 1
+   if any prefix has been found, zero otherwise.  */
+
+static int
+stap_is_generic_prefix (struct gdbarch *gdbarch, const char *s,
+			const char **r, const char *const *prefixes)
+{
+  const char *const *p;
+
+  if (prefixes == NULL)
+    {
+      if (r != NULL)
+	*r = "";
+
+      return 1;
+    }
+
+  for (p = prefixes; *p != NULL; ++p)
+    {
+      if (strncasecmp (s, *p, strlen (*p)) == 0)
+	{
+	  if (r != NULL)
+	    *r = *p;
+
+	  return 1;
+	}
+    }
+
+  return 0;
+}
+
+/* Return 1 if S points to a register prefix, zero otherwise.  */
+
+static int
+stap_is_register_prefix (struct gdbarch *gdbarch, const char *s,
+			 const char **r)
+{
+  const char *const *t = gdbarch_stap_register_prefix (gdbarch);
+
+  return stap_is_generic_prefix (gdbarch, s, r, t);
+}
+
+/* Return 1 if S points to a register indirection prefix, zero
+   otherwise.  */
+
+static int
+stap_is_register_indirection_prefix (struct gdbarch *gdbarch, const char *s,
+				     const char **r)
+{
+  const char *const *t = gdbarch_stap_register_indirection_prefix (gdbarch);
+
+  return stap_is_generic_prefix (gdbarch, s, r, t);
+}
+
+/* Return 1 if S points to an integer prefix, zero otherwise.
+
+   This function takes care of analyzing whether we are dealing with
+   an expected integer prefix, or, if there is no integer prefix to be
+   expected, whether we are dealing with a digit.  */
+
+static int
+stap_is_integer_prefix (struct gdbarch *gdbarch, const char *s,
+			const char **r)
+{
+  const char *const *t = gdbarch_stap_integer_prefix (gdbarch);
+  const char *const *p;
+
+  if (t == NULL)
+    {
+      /* A NULL value here means that integers do not have prefix.  We
+	 just check for a digit then.  */
+      if (r != NULL)
+	*r = "";
+
+      return isdigit (*s);
+    }
+
+  for (p = t; *p != NULL; ++p)
+    {
+      size_t len = strlen (*p);
+
+      if ((len == 0 && isdigit (*s))
+	  || (len > 0 && strncasecmp (s, *p, len) == 0))
+	{
+	  /* Integers may or may not have a prefix.  The "len == 0"
+	     check covers the case when integers do not have a prefix
+	     (therefore, we just check if we have a digit).  The call
+	     to "strncasecmp" covers the case when they have a
+	     prefix.  */
+	  if (r != NULL)
+	    *r = *p;
+
+	  return 1;
+	}
+    }
+
+  return 0;
+}
+
+/* Helper function to check for a generic list of suffixes.  If we are
+   not expecting any suffixes, then it just returns 1.  If we are
+   expecting at least one suffix, then it returns 1 if a suffix has
+   been found, zero otherwise.  */
+
+static int
+stap_generic_check_suffix (struct gdbarch *gdbarch, const char *s,
+			   const char **r, const char *const *suffixes)
+{
+  const char *const *p;
+  int found = 0;
+
+  if (suffixes == NULL)
+    {
+      if (r != NULL)
+	*r = "";
+
+      return 1;
+    }
+
+  for (p = suffixes; *p != NULL; ++p)
+    if (strncasecmp (s, *p, strlen (*p)) == 0)
+      {
+	if (r != NULL)
+	  *r = *p;
+
+	found = 1;
+	break;
+      }
+
+  return found;
+}
+
+/* Return 1 if S points to an integer suffix, zero otherwise.  */
+
+static int
+stap_check_integer_suffix (struct gdbarch *gdbarch, const char *s,
+			   const char **r)
+{
+  const char *const *p = gdbarch_stap_integer_suffix (gdbarch);
+
+  return stap_generic_check_suffix (gdbarch, s, r, p);
+}
+
+/* Return 1 if S points to a register suffix, zero otherwise.  */
+
+static int
+stap_check_register_suffix (struct gdbarch *gdbarch, const char *s,
+			    const char **r)
+{
+  const char *const *p = gdbarch_stap_register_suffix (gdbarch);
+
+  return stap_generic_check_suffix (gdbarch, s, r, p);
+}
+
+/* Return 1 if S points to a register indirection suffix, zero otherwise.  */
+
+static int
+stap_check_register_indirection_suffix (struct gdbarch *gdbarch, const char *s,
+					const char **r)
+{
+  const char *const *p = gdbarch_stap_register_indirection_suffix (gdbarch);
+
+  return stap_generic_check_suffix (gdbarch, s, r, p);
+}
+
 /* Function responsible for parsing a register operand according to
    SystemTap parlance.  Assuming:
 
@@ -385,24 +550,14 @@ stap_parse_register_operand (struct stap_parse_info *p)
   const char *start;
   char *regname;
   int len;
-
-  /* Prefixes for the parser.  */
-  const char *reg_prefix = gdbarch_stap_register_prefix (gdbarch);
-  const char *reg_ind_prefix
-    = gdbarch_stap_register_indirection_prefix (gdbarch);
   const char *gdb_reg_prefix = gdbarch_stap_gdb_register_prefix (gdbarch);
-  int reg_prefix_len = reg_prefix ? strlen (reg_prefix) : 0;
-  int reg_ind_prefix_len = reg_ind_prefix ? strlen (reg_ind_prefix) : 0;
   int gdb_reg_prefix_len = gdb_reg_prefix ? strlen (gdb_reg_prefix) : 0;
-
-  /* Suffixes for the parser.  */
-  const char *reg_suffix = gdbarch_stap_register_suffix (gdbarch);
-  const char *reg_ind_suffix
-    = gdbarch_stap_register_indirection_suffix (gdbarch);
   const char *gdb_reg_suffix = gdbarch_stap_gdb_register_suffix (gdbarch);
-  int reg_suffix_len = reg_suffix ? strlen (reg_suffix) : 0;
-  int reg_ind_suffix_len = reg_ind_suffix ? strlen (reg_ind_suffix) : 0;
   int gdb_reg_suffix_len = gdb_reg_suffix ? strlen (gdb_reg_suffix) : 0;
+  const char *reg_prefix;
+  const char *reg_ind_prefix;
+  const char *reg_suffix;
+  const char *reg_ind_suffix;
 
   /* Checking for a displacement argument.  */
   if (*p->arg == '+')
@@ -438,11 +593,10 @@ stap_parse_register_operand (struct stap_parse_info *p)
     }
 
   /* Getting rid of register indirection prefix.  */
-  if (reg_ind_prefix
-      && strncmp (p->arg, reg_ind_prefix, reg_ind_prefix_len) == 0)
+  if (stap_is_register_indirection_prefix (gdbarch, p->arg, &reg_ind_prefix))
     {
       indirect_p = 1;
-      p->arg += reg_ind_prefix_len;
+      p->arg += strlen (reg_ind_prefix);
     }
 
   if (disp_p && !indirect_p)
@@ -450,8 +604,8 @@ stap_parse_register_operand (struct stap_parse_info *p)
 	   p->saved_arg);
 
   /* Getting rid of register prefix.  */
-  if (reg_prefix && strncmp (p->arg, reg_prefix, reg_prefix_len) == 0)
-    p->arg += reg_prefix_len;
+  if (stap_is_register_prefix (gdbarch, p->arg, &reg_prefix))
+    p->arg += strlen (reg_prefix);
 
   /* Now we should have only the register name.  Let's extract it and get
      the associated number.  */
@@ -509,23 +663,21 @@ stap_parse_register_operand (struct stap_parse_info *p)
     }
 
   /* Getting rid of the register name suffix.  */
-  if (reg_suffix)
-    {
-      if (strncmp (p->arg, reg_suffix, reg_suffix_len) != 0)
-	error (_("Missing register name suffix `%s' on expression `%s'."),
-	       reg_suffix, p->saved_arg);
-
-      p->arg += reg_suffix_len;
-    }
+  if (stap_check_register_suffix (gdbarch, p->arg, &reg_suffix))
+    p->arg += strlen (reg_suffix);
+  else
+    error (_("Missing register name suffix on expression `%s'."),
+	   p->saved_arg);
 
   /* Getting rid of the register indirection suffix.  */
-  if (indirect_p && reg_ind_suffix)
+  if (indirect_p)
     {
-      if (strncmp (p->arg, reg_ind_suffix, reg_ind_suffix_len) != 0)
-	error (_("Missing indirection suffix `%s' on expression `%s'."),
-	       reg_ind_suffix, p->saved_arg);
-
-      p->arg += reg_ind_suffix_len;
+      if (stap_check_register_indirection_suffix (gdbarch, p->arg,
+						  &reg_ind_suffix))
+	p->arg += strlen (reg_ind_suffix);
+      else
+	error (_("Missing indirection suffix on expression `%s'."),
+	       p->saved_arg);
     }
 }
 
@@ -548,19 +700,7 @@ static void
 stap_parse_single_operand (struct stap_parse_info *p)
 {
   struct gdbarch *gdbarch = p->gdbarch;
-
-  /* Prefixes for the parser.  */
-  const char *const_prefix = gdbarch_stap_integer_prefix (gdbarch);
-  const char *reg_prefix = gdbarch_stap_register_prefix (gdbarch);
-  const char *reg_ind_prefix
-    = gdbarch_stap_register_indirection_prefix (gdbarch);
-  int const_prefix_len = const_prefix ? strlen (const_prefix) : 0;
-  int reg_prefix_len = reg_prefix ? strlen (reg_prefix) : 0;
-  int reg_ind_prefix_len = reg_ind_prefix ? strlen (reg_ind_prefix) : 0;
-
-  /* Suffixes for the parser.  */
-  const char *const_suffix = gdbarch_stap_integer_suffix (gdbarch);
-  int const_suffix_len = const_suffix ? strlen (const_suffix) : 0;
+  const char *int_prefix = NULL;
 
   /* We first try to parse this token as a "special token".  */
   if (gdbarch_stap_parse_special_token_p (gdbarch))
@@ -607,8 +747,7 @@ stap_parse_single_operand (struct stap_parse_info *p)
 	  tmp = endp;
 	}
 
-      if (!reg_ind_prefix
-	  || strncmp (tmp, reg_ind_prefix, reg_ind_prefix_len) != 0)
+      if (!stap_is_register_indirection_prefix (gdbarch, tmp, NULL))
 	{
 	  /* This is not a displacement.  We skip the operator, and deal
 	     with it later.  */
@@ -637,16 +776,23 @@ stap_parse_single_operand (struct stap_parse_info *p)
       char *endp;
       long number;
 
-      /* We can be dealing with a numeric constant (if `const_prefix' is
-	 NULL), or with a register displacement.  */
+      /* We can be dealing with a numeric constant, or with a register
+	 displacement.  */
       number = strtol (tmp, &endp, 10);
       tmp = endp;
 
       if (p->inside_paren_p)
 	tmp = skip_spaces_const (tmp);
-      if (!const_prefix && reg_ind_prefix
-	  && strncmp (tmp, reg_ind_prefix, reg_ind_prefix_len) != 0)
+
+      /* If "stap_is_integer_prefix" returns true, it means we can
+	 accept integers without a prefix here.  But we also need to
+	 check whether the next token (i.e., "tmp") is not a register
+	 indirection prefix.  */
+      if (stap_is_integer_prefix (gdbarch, p->arg, NULL)
+	  && !stap_is_register_indirection_prefix (gdbarch, tmp, NULL))
 	{
+	  const char *int_suffix;
+
 	  /* We are dealing with a numeric constant.  */
 	  write_exp_elt_opcode (OP_LONG);
 	  write_exp_elt_type (builtin_type (gdbarch)->builtin_long);
@@ -655,30 +801,26 @@ stap_parse_single_operand (struct stap_parse_info *p)
 
 	  p->arg = tmp;
 
-	  if (const_suffix)
-	    {
-	      if (strncmp (p->arg, const_suffix, const_suffix_len) == 0)
-		p->arg += const_suffix_len;
-	      else
-		error (_("Invalid constant suffix on expression `%s'."),
-		       p->saved_arg);
-	    }
+	  if (stap_check_integer_suffix (gdbarch, p->arg, &int_suffix))
+	    p->arg += strlen (int_suffix);
+	  else
+	    error (_("Invalid constant suffix on expression `%s'."),
+		   p->saved_arg);
 	}
-      else if (reg_ind_prefix
-	       && strncmp (tmp, reg_ind_prefix, reg_ind_prefix_len) == 0)
+      else if (stap_is_register_indirection_prefix (gdbarch, tmp, NULL))
 	stap_parse_register_operand (p);
       else
 	error (_("Unknown numeric token on expression `%s'."),
 	       p->saved_arg);
     }
-  else if (const_prefix
-	   && strncmp (p->arg, const_prefix, const_prefix_len) == 0)
+  else if (stap_is_integer_prefix (gdbarch, p->arg, &int_prefix))
     {
       /* We are dealing with a numeric constant.  */
       long number;
       char *endp;
+      const char *int_suffix;
 
-      p->arg += const_prefix_len;
+      p->arg += strlen (int_prefix);
       number = strtol (p->arg, &endp, 10);
       p->arg = endp;
 
@@ -687,19 +829,14 @@ stap_parse_single_operand (struct stap_parse_info *p)
       write_exp_elt_longcst (number);
       write_exp_elt_opcode (OP_LONG);
 
-      if (const_suffix)
-	{
-	  if (strncmp (p->arg, const_suffix, const_suffix_len) == 0)
-	    p->arg += const_suffix_len;
-	  else
-	    error (_("Invalid constant suffix on expression `%s'."),
-		   p->saved_arg);
-	}
+      if (stap_check_integer_suffix (gdbarch, p->arg, &int_suffix))
+	p->arg += strlen (int_suffix);
+      else
+	error (_("Invalid constant suffix on expression `%s'."),
+	       p->saved_arg);
     }
-  else if ((reg_prefix
-	    && strncmp (p->arg, reg_prefix, reg_prefix_len) == 0)
-	   || (reg_ind_prefix
-	       && strncmp (p->arg, reg_ind_prefix, reg_ind_prefix_len) == 0))
+  else if (stap_is_register_prefix (gdbarch, p->arg, NULL)
+	   || stap_is_register_indirection_prefix (gdbarch, p->arg, NULL))
     stap_parse_register_operand (p);
   else
     error (_("Operator `%c' not recognized on expression `%s'."),
-- 
1.7.11.7

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Extend SystemTap SDT probe argument parser
  2013-12-11  3:56 [PATCH] Extend SystemTap SDT probe argument parser Sergio Durigan Junior
@ 2013-12-16 17:01 ` Sergio Durigan Junior
  2013-12-16 17:09   ` Mark Kettenis
  2013-12-17 11:03 ` Pedro Alves
  1 sibling, 1 reply; 10+ messages in thread
From: Sergio Durigan Junior @ 2013-12-16 17:01 UTC (permalink / raw)
  To: GDB Patches

On Wednesday, December 11 2013, I wrote:

> This patch extends the current generic parser for SystemTap SDT probe
> arguments.  It can be almost considered a cleanup, but the main point of
> it is actually to allow the generic parser to accept multiple prefixes
> and suffixes for the its operands (i.e., integers, register names, and
> register indirection).

Ping.

> I have chosen to implement this as a list of const strings, which needs
> to be declared as "static const char *const *", and is provided to
> gdbarch on initialization.  I think it is cleaner to implement it this
> way, but for a moment I wondered whether demanding the variables to be
> declared as "static" is a good idea...  After some thought and
> discussion, I decided to leave it as is.
>
> This patch is actually a preparation for an upcoming patch for ARM,
> which implements the support for multiple integer prefixes (as defined
> by ARM's asm spec).  And AArch64 will also need this, for the same
> reason.
>
> This patch was regtested on all architectures that it touches (i.e.,
> i386, x86_64, ARM, PPC/PPC64, s390x and IA-64).  No regressions were found.
>
> 2013-12-11  Sergio Durigan Junior  <sergiodj@redhat.com>
>
> 	* amd64-tdep.c (amd64_init_abi): Declare SystemTap SDT probe
> 	argument prefixes and suffixes.  Initialize gdbarch with them.
> 	* arm-linux-tdep.c (arm_linux_init_abi): Likewise.
> 	* gdbarch.c: Regenerate.
> 	* gdbarch.h: Regenerate.
> 	* gdbarch.sh (stap_integer_prefix, stap_integer_suffix)
> 	(stap_register_prefix, stap_register_suffix)
> 	(stap_register_indirection_prefix)
> 	(stap_register_indirection_suffix): Declare as "const char *const
> 	*" instead of "const char *".  Adjust printing function.
> 	(pstring_list): New function.
> 	* i386-tdep.c (i386_elf_init_abi): Declare SystemTap SDT probe
> 	argument prefixes and suffixes.  Initialize gdbarch with them.
> 	* ia64-linux-tdep.c (ia64_linux_init_abi): Likewise.
> 	* ppc-linux-tdep.c (ppc_linux_init_abi): Likewise.
> 	* s390-linux-tdep.c (s390_gdbarch_init): Likewise.
> 	* stap-probe.c (stap_is_generic_prefix): New function.
> 	(stap_is_register_prefix): Likewise.
> 	(stap_is_register_indirection_prefix): Likewise.
> 	(stap_is_integer_prefix): Likewise.
> 	(stap_generic_check_suffix): Likewise.
> 	(stap_check_integer_suffix): Likewise.
> 	(stap_check_register_suffix): Likewise.
> 	(stap_check_register_indirection_suffix): Likewise.
> 	(stap_parse_register_operand): Remove unecessary declarations for
> 	variables holding prefix and suffix information.  Use the new
> 	functions listed above for checking for prefixes and suffixes.
> 	(stap_parse_single_operand): Likewise.
> ---
>  gdb/ChangeLog         |  31 ++++++
>  gdb/amd64-tdep.c      |  14 ++-
>  gdb/arm-linux-tdep.c  |  14 ++-
>  gdb/gdbarch.c         |  71 +++++++-----
>  gdb/gdbarch.h         |  76 +++++++++----
>  gdb/gdbarch.sh        |  79 +++++++++++---
>  gdb/i386-tdep.c       |  15 ++-
>  gdb/ia64-linux-tdep.c |  11 +-
>  gdb/ppc-linux-tdep.c  |  11 +-
>  gdb/s390-linux-tdep.c |  11 +-
>  gdb/stap-probe.c      | 291 +++++++++++++++++++++++++++++++++++++-------------
>  11 files changed, 466 insertions(+), 158 deletions(-)
>
> diff --git a/gdb/ChangeLog b/gdb/ChangeLog
> index 35a1d73..efda387 100644
> --- a/gdb/ChangeLog
> +++ b/gdb/ChangeLog
> @@ -1,5 +1,36 @@
>  2013-12-11  Sergio Durigan Junior  <sergiodj@redhat.com>
>  
> +	* amd64-tdep.c (amd64_init_abi): Declare SystemTap SDT probe
> +	argument prefixes and suffixes.  Initialize gdbarch with them.
> +	* arm-linux-tdep.c (arm_linux_init_abi): Likewise.
> +	* gdbarch.c: Regenerate.
> +	* gdbarch.h: Regenerate.
> +	* gdbarch.sh (stap_integer_prefix, stap_integer_suffix)
> +	(stap_register_prefix, stap_register_suffix)
> +	(stap_register_indirection_prefix)
> +	(stap_register_indirection_suffix): Declare as "const char *const
> +	*" instead of "const char *".  Adjust printing function.
> +	(pstring_list): New function.
> +	* i386-tdep.c (i386_elf_init_abi): Declare SystemTap SDT probe
> +	argument prefixes and suffixes.  Initialize gdbarch with them.
> +	* ia64-linux-tdep.c (ia64_linux_init_abi): Likewise.
> +	* ppc-linux-tdep.c (ppc_linux_init_abi): Likewise.
> +	* s390-linux-tdep.c (s390_gdbarch_init): Likewise.
> +	* stap-probe.c (stap_is_generic_prefix): New function.
> +	(stap_is_register_prefix): Likewise.
> +	(stap_is_register_indirection_prefix): Likewise.
> +	(stap_is_integer_prefix): Likewise.
> +	(stap_generic_check_suffix): Likewise.
> +	(stap_check_integer_suffix): Likewise.
> +	(stap_check_register_suffix): Likewise.
> +	(stap_check_register_indirection_suffix): Likewise.
> +	(stap_parse_register_operand): Remove unecessary declarations for
> +	variables holding prefix and suffix information.  Use the new
> +	functions listed above for checking for prefixes and suffixes.
> +	(stap_parse_single_operand): Likewise.
> +
> +2013-12-11  Sergio Durigan Junior  <sergiodj@redhat.com>
> +
>  	* break-catch-throw.c (fetch_probe_arguments): Pass selected frame
>  	to get_probe_argument_count and evaluate_probe_argument.
>  	* probe.c (get_probe_argument_count): Adjust declaration to accept
> diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
> index 19968fc..ec67f06 100644
> --- a/gdb/amd64-tdep.c
> +++ b/gdb/amd64-tdep.c
> @@ -2832,6 +2832,10 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>  {
>    struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
>    const struct target_desc *tdesc = info.target_desc;
> +  static const char *const stap_integer_prefix[] = { "$", NULL };
> +  static const char *const stap_register_prefix[] = { "%", NULL };
> +  static const char *const stap_register_indirection_prefix[] = { "(", NULL };
> +  static const char *const stap_register_indirection_suffix[] = { ")", NULL };
>  
>    /* AMD64 generally uses `fxsave' instead of `fsave' for saving its
>       floating-point registers.  */
> @@ -2944,10 +2948,12 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>    set_gdbarch_gen_return_address (gdbarch, amd64_gen_return_address);
>  
>    /* SystemTap variables and functions.  */
> -  set_gdbarch_stap_integer_prefix (gdbarch, "$");
> -  set_gdbarch_stap_register_prefix (gdbarch, "%");
> -  set_gdbarch_stap_register_indirection_prefix (gdbarch, "(");
> -  set_gdbarch_stap_register_indirection_suffix (gdbarch, ")");
> +  set_gdbarch_stap_integer_prefix (gdbarch, stap_integer_prefix);
> +  set_gdbarch_stap_register_prefix (gdbarch, stap_register_prefix);
> +  set_gdbarch_stap_register_indirection_prefix (gdbarch,
> +					    stap_register_indirection_prefix);
> +  set_gdbarch_stap_register_indirection_suffix (gdbarch,
> +					    stap_register_indirection_suffix);
>    set_gdbarch_stap_is_single_operand (gdbarch,
>  				      i386_stap_is_single_operand);
>    set_gdbarch_stap_parse_special_token (gdbarch,
> diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c
> index 9deed10..4f385b5 100644
> --- a/gdb/arm-linux-tdep.c
> +++ b/gdb/arm-linux-tdep.c
> @@ -1235,6 +1235,10 @@ static void
>  arm_linux_init_abi (struct gdbarch_info info,
>  		    struct gdbarch *gdbarch)
>  {
> +  static const char *const stap_integer_prefix[] = { "#", NULL };
> +  static const char *const stap_register_prefix[] = { "r", NULL };
> +  static const char *const stap_register_indirection_prefix[] = { "[", NULL };
> +  static const char *const stap_register_indirection_suffix[] = { "]", NULL };
>    struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
>  
>    linux_init_abi (info, gdbarch);
> @@ -1334,10 +1338,12 @@ arm_linux_init_abi (struct gdbarch_info info,
>    set_gdbarch_process_record (gdbarch, arm_process_record);
>  
>    /* SystemTap functions.  */
> -  set_gdbarch_stap_integer_prefix (gdbarch, "#");
> -  set_gdbarch_stap_register_prefix (gdbarch, "r");
> -  set_gdbarch_stap_register_indirection_prefix (gdbarch, "[");
> -  set_gdbarch_stap_register_indirection_suffix (gdbarch, "]");
> +  set_gdbarch_stap_integer_prefix (gdbarch, stap_integer_prefix);
> +  set_gdbarch_stap_register_prefix (gdbarch, stap_register_prefix);
> +  set_gdbarch_stap_register_indirection_prefix (gdbarch,
> +					    stap_register_indirection_prefix);
> +  set_gdbarch_stap_register_indirection_suffix (gdbarch,
> +					    stap_register_indirection_suffix);
>    set_gdbarch_stap_gdb_register_prefix (gdbarch, "r");
>    set_gdbarch_stap_is_single_operand (gdbarch, arm_stap_is_single_operand);
>    set_gdbarch_stap_parse_special_token (gdbarch,
> diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
> index fb3595f..4594f20 100644
> --- a/gdb/gdbarch.c
> +++ b/gdb/gdbarch.c
> @@ -86,6 +86,29 @@ pstring (const char *string)
>    return string;
>  }
>  
> +static char *
> +pstring_list (const char *const *list)
> +{
> +  static char ret[100];
> +  const char *const *p;
> +  int offset = 0;
> +
> +  if (list == NULL)
> +    return "(null)";
> +
> +  ret[0] = '\0';
> +  for (p = list; *p != NULL && offset < sizeof (ret); ++p)
> +    {
> +      xsnprintf (ret + offset, sizeof (ret) - offset, "%s, ", *p);
> +      offset += 2 + strlen (*p);
> +    }
> +
> +  if (offset > 0)
> +    ret[offset - 2] = '\0';
> +
> +  return ret;
> +}
> +
>  
>  /* Maintain the struct gdbarch object.  */
>  
> @@ -265,12 +288,12 @@ struct gdbarch
>    gdbarch_get_siginfo_type_ftype *get_siginfo_type;
>    gdbarch_record_special_symbol_ftype *record_special_symbol;
>    gdbarch_get_syscall_number_ftype *get_syscall_number;
> -  const char * stap_integer_prefix;
> -  const char * stap_integer_suffix;
> -  const char * stap_register_prefix;
> -  const char * stap_register_suffix;
> -  const char * stap_register_indirection_prefix;
> -  const char * stap_register_indirection_suffix;
> +  const char *const * stap_integer_prefix;
> +  const char *const * stap_integer_suffix;
> +  const char *const * stap_register_prefix;
> +  const char *const * stap_register_suffix;
> +  const char *const * stap_register_indirection_prefix;
> +  const char *const * stap_register_indirection_suffix;
>    const char * stap_gdb_register_prefix;
>    const char * stap_gdb_register_suffix;
>    gdbarch_stap_is_single_operand_ftype *stap_is_single_operand;
> @@ -1352,10 +1375,10 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
>                        pstring (gdbarch->stap_gdb_register_suffix));
>    fprintf_unfiltered (file,
>                        "gdbarch_dump: stap_integer_prefix = %s\n",
> -                      pstring (gdbarch->stap_integer_prefix));
> +                      pstring_list (gdbarch->stap_integer_prefix));
>    fprintf_unfiltered (file,
>                        "gdbarch_dump: stap_integer_suffix = %s\n",
> -                      pstring (gdbarch->stap_integer_suffix));
> +                      pstring_list (gdbarch->stap_integer_suffix));
>    fprintf_unfiltered (file,
>                        "gdbarch_dump: gdbarch_stap_is_single_operand_p() = %d\n",
>                        gdbarch_stap_is_single_operand_p (gdbarch));
> @@ -1370,16 +1393,16 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
>                        host_address_to_string (gdbarch->stap_parse_special_token));
>    fprintf_unfiltered (file,
>                        "gdbarch_dump: stap_register_indirection_prefix = %s\n",
> -                      pstring (gdbarch->stap_register_indirection_prefix));
> +                      pstring_list (gdbarch->stap_register_indirection_prefix));
>    fprintf_unfiltered (file,
>                        "gdbarch_dump: stap_register_indirection_suffix = %s\n",
> -                      pstring (gdbarch->stap_register_indirection_suffix));
> +                      pstring_list (gdbarch->stap_register_indirection_suffix));
>    fprintf_unfiltered (file,
>                        "gdbarch_dump: stap_register_prefix = %s\n",
> -                      pstring (gdbarch->stap_register_prefix));
> +                      pstring_list (gdbarch->stap_register_prefix));
>    fprintf_unfiltered (file,
>                        "gdbarch_dump: stap_register_suffix = %s\n",
> -                      pstring (gdbarch->stap_register_suffix));
> +                      pstring_list (gdbarch->stap_register_suffix));
>    fprintf_unfiltered (file,
>                        "gdbarch_dump: gdbarch_static_transform_name_p() = %d\n",
>                        gdbarch_static_transform_name_p (gdbarch));
> @@ -4004,7 +4027,7 @@ set_gdbarch_get_syscall_number (struct gdbarch *gdbarch,
>    gdbarch->get_syscall_number = get_syscall_number;
>  }
>  
> -const char *
> +const char *const *
>  gdbarch_stap_integer_prefix (struct gdbarch *gdbarch)
>  {
>    gdb_assert (gdbarch != NULL);
> @@ -4016,12 +4039,12 @@ gdbarch_stap_integer_prefix (struct gdbarch *gdbarch)
>  
>  void
>  set_gdbarch_stap_integer_prefix (struct gdbarch *gdbarch,
> -                                 const char * stap_integer_prefix)
> +                                 const char *const * stap_integer_prefix)
>  {
>    gdbarch->stap_integer_prefix = stap_integer_prefix;
>  }
>  
> -const char *
> +const char *const *
>  gdbarch_stap_integer_suffix (struct gdbarch *gdbarch)
>  {
>    gdb_assert (gdbarch != NULL);
> @@ -4033,12 +4056,12 @@ gdbarch_stap_integer_suffix (struct gdbarch *gdbarch)
>  
>  void
>  set_gdbarch_stap_integer_suffix (struct gdbarch *gdbarch,
> -                                 const char * stap_integer_suffix)
> +                                 const char *const * stap_integer_suffix)
>  {
>    gdbarch->stap_integer_suffix = stap_integer_suffix;
>  }
>  
> -const char *
> +const char *const *
>  gdbarch_stap_register_prefix (struct gdbarch *gdbarch)
>  {
>    gdb_assert (gdbarch != NULL);
> @@ -4050,12 +4073,12 @@ gdbarch_stap_register_prefix (struct gdbarch *gdbarch)
>  
>  void
>  set_gdbarch_stap_register_prefix (struct gdbarch *gdbarch,
> -                                  const char * stap_register_prefix)
> +                                  const char *const * stap_register_prefix)
>  {
>    gdbarch->stap_register_prefix = stap_register_prefix;
>  }
>  
> -const char *
> +const char *const *
>  gdbarch_stap_register_suffix (struct gdbarch *gdbarch)
>  {
>    gdb_assert (gdbarch != NULL);
> @@ -4067,12 +4090,12 @@ gdbarch_stap_register_suffix (struct gdbarch *gdbarch)
>  
>  void
>  set_gdbarch_stap_register_suffix (struct gdbarch *gdbarch,
> -                                  const char * stap_register_suffix)
> +                                  const char *const * stap_register_suffix)
>  {
>    gdbarch->stap_register_suffix = stap_register_suffix;
>  }
>  
> -const char *
> +const char *const *
>  gdbarch_stap_register_indirection_prefix (struct gdbarch *gdbarch)
>  {
>    gdb_assert (gdbarch != NULL);
> @@ -4084,12 +4107,12 @@ gdbarch_stap_register_indirection_prefix (struct gdbarch *gdbarch)
>  
>  void
>  set_gdbarch_stap_register_indirection_prefix (struct gdbarch *gdbarch,
> -                                              const char * stap_register_indirection_prefix)
> +                                              const char *const * stap_register_indirection_prefix)
>  {
>    gdbarch->stap_register_indirection_prefix = stap_register_indirection_prefix;
>  }
>  
> -const char *
> +const char *const *
>  gdbarch_stap_register_indirection_suffix (struct gdbarch *gdbarch)
>  {
>    gdb_assert (gdbarch != NULL);
> @@ -4101,7 +4124,7 @@ gdbarch_stap_register_indirection_suffix (struct gdbarch *gdbarch)
>  
>  void
>  set_gdbarch_stap_register_indirection_suffix (struct gdbarch *gdbarch,
> -                                              const char * stap_register_indirection_suffix)
> +                                              const char *const * stap_register_indirection_suffix)
>  {
>    gdbarch->stap_register_indirection_suffix = stap_register_indirection_suffix;
>  }
> diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
> index b58efc8..1d60f28 100644
> --- a/gdb/gdbarch.h
> +++ b/gdb/gdbarch.h
> @@ -1034,37 +1034,57 @@ extern LONGEST gdbarch_get_syscall_number (struct gdbarch *gdbarch, ptid_t ptid)
>  extern void set_gdbarch_get_syscall_number (struct gdbarch *gdbarch, gdbarch_get_syscall_number_ftype *get_syscall_number);
>  
>  /* SystemTap related fields and functions.
> -   Prefix used to mark an integer constant on the architecture's assembly
> +   Prefix(es) used to mark an integer constant on the architecture's assembly.
>     For example, on x86 integer constants are written as:
>    
>      $10 ;; integer constant 10
>    
> -   in this case, this prefix would be the character `$'. */
> +   in this case, this prefix would be the character `$'.
> +  
> +   This variable must be declared as `static const char *const var[]',
> +   and must also be NUL-terminated, like the following example:
> +  
> +     static const char *const example[] = { "prefix1", "prefix2", NULL }; */
>  
> -extern const char * gdbarch_stap_integer_prefix (struct gdbarch *gdbarch);
> -extern void set_gdbarch_stap_integer_prefix (struct gdbarch *gdbarch, const char * stap_integer_prefix);
> +extern const char *const * gdbarch_stap_integer_prefix (struct gdbarch *gdbarch);
> +extern void set_gdbarch_stap_integer_prefix (struct gdbarch *gdbarch, const char *const * stap_integer_prefix);
>  
> -/* Suffix used to mark an integer constant on the architecture's assembly. */
> +/* Suffix(es) used to mark an integer constant on the architecture's assembly.
> +  
> +   This variable must be declared as `static const char *const var[]',
> +   and must also be NUL-terminated, like the following example:
> +  
> +     static const char *const example[] = { "prefix1", "prefix2", NULL }; */
>  
> -extern const char * gdbarch_stap_integer_suffix (struct gdbarch *gdbarch);
> -extern void set_gdbarch_stap_integer_suffix (struct gdbarch *gdbarch, const char * stap_integer_suffix);
> +extern const char *const * gdbarch_stap_integer_suffix (struct gdbarch *gdbarch);
> +extern void set_gdbarch_stap_integer_suffix (struct gdbarch *gdbarch, const char *const * stap_integer_suffix);
>  
> -/* Prefix used to mark a register name on the architecture's assembly.
> +/* Prefix(es) used to mark a register name on the architecture's assembly.
>     For example, on x86 the register name is written as:
>    
>      %eax ;; register eax
>    
> -   in this case, this prefix would be the character `%'. */
> +   in this case, this prefix would be the character `%'.
> +  
> +   This variable must be declared as `static const char *const var[]',
> +   and must also be NUL-terminated, like the following example:
> +  
> +     static const char *const example[] = { "prefix1", "prefix2", NULL }; */
>  
> -extern const char * gdbarch_stap_register_prefix (struct gdbarch *gdbarch);
> -extern void set_gdbarch_stap_register_prefix (struct gdbarch *gdbarch, const char * stap_register_prefix);
> +extern const char *const * gdbarch_stap_register_prefix (struct gdbarch *gdbarch);
> +extern void set_gdbarch_stap_register_prefix (struct gdbarch *gdbarch, const char *const * stap_register_prefix);
>  
> -/* Suffix used to mark a register name on the architecture's assembly */
> +/* Suffix(es) used to mark a register name on the architecture's assembly
> +  
> +   This variable must be declared as `static const char *const var[]',
> +   and must also be NUL-terminated, like the following example:
> +  
> +     static const char *const example[] = { "prefix1", "prefix2", NULL }; */
>  
> -extern const char * gdbarch_stap_register_suffix (struct gdbarch *gdbarch);
> -extern void set_gdbarch_stap_register_suffix (struct gdbarch *gdbarch, const char * stap_register_suffix);
> +extern const char *const * gdbarch_stap_register_suffix (struct gdbarch *gdbarch);
> +extern void set_gdbarch_stap_register_suffix (struct gdbarch *gdbarch, const char *const * stap_register_suffix);
>  
> -/* Prefix used to mark a register indirection on the architecture's assembly.
> +/* Prefix(es) used to mark a register indirection on the architecture's assembly.
>     For example, on x86 the register indirection is written as:
>    
>      (%eax) ;; indirecting eax
> @@ -1072,12 +1092,17 @@ extern void set_gdbarch_stap_register_suffix (struct gdbarch *gdbarch, const cha
>     in this case, this prefix would be the charater `('.
>    
>     Please note that we use the indirection prefix also for register
> -   displacement, e.g., `4(%eax)' on x86. */
> +   displacement, e.g., `4(%eax)' on x86.
> +  
> +   This variable must be declared as `static const char *const var[]',
> +   and must also be NUL-terminated, like the following example:
> +  
> +     static const char *const example = { "prefix1", "prefix2", NULL }; */
>  
> -extern const char * gdbarch_stap_register_indirection_prefix (struct gdbarch *gdbarch);
> -extern void set_gdbarch_stap_register_indirection_prefix (struct gdbarch *gdbarch, const char * stap_register_indirection_prefix);
> +extern const char *const * gdbarch_stap_register_indirection_prefix (struct gdbarch *gdbarch);
> +extern void set_gdbarch_stap_register_indirection_prefix (struct gdbarch *gdbarch, const char *const * stap_register_indirection_prefix);
>  
> -/* Suffix used to mark a register indirection on the architecture's assembly.
> +/* Suffix(es) used to mark a register indirection on the architecture's assembly.
>     For example, on x86 the register indirection is written as:
>    
>      (%eax) ;; indirecting eax
> @@ -1085,12 +1110,17 @@ extern void set_gdbarch_stap_register_indirection_prefix (struct gdbarch *gdbarc
>     in this case, this prefix would be the charater `)'.
>    
>     Please note that we use the indirection suffix also for register
> -   displacement, e.g., `4(%eax)' on x86. */
> +   displacement, e.g., `4(%eax)' on x86.
> +  
> +   This variable must be declared as `static const char *const var[]',
> +   and must also be NUL-terminated, like the following example:
> +  
> +     static const char *const example = { "prefix1", "prefix2", NULL }; */
>  
> -extern const char * gdbarch_stap_register_indirection_suffix (struct gdbarch *gdbarch);
> -extern void set_gdbarch_stap_register_indirection_suffix (struct gdbarch *gdbarch, const char * stap_register_indirection_suffix);
> +extern const char *const * gdbarch_stap_register_indirection_suffix (struct gdbarch *gdbarch);
> +extern void set_gdbarch_stap_register_indirection_suffix (struct gdbarch *gdbarch, const char *const * stap_register_indirection_suffix);
>  
> -/* Prefix used to name a register using GDB's nomenclature.
> +/* Prefix(es) used to name a register using GDB's nomenclature.
>    
>     For example, on PPC a register is represented by a number in the assembly
>     language (e.g., `10' is the 10th general-purpose register).  However,
> diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
> index a678a78..1d11b31 100755
> --- a/gdb/gdbarch.sh
> +++ b/gdb/gdbarch.sh
> @@ -826,29 +826,49 @@ M:LONGEST:get_syscall_number:ptid_t ptid:ptid
>  
>  # SystemTap related fields and functions.
>  
> -# Prefix used to mark an integer constant on the architecture's assembly
> +# Prefix(es) used to mark an integer constant on the architecture's assembly.
>  # For example, on x86 integer constants are written as:
>  #
>  #  \$10 ;; integer constant 10
>  #
>  # in this case, this prefix would be the character \`\$\'.
> -v:const char *:stap_integer_prefix:::0:0::0:pstring (gdbarch->stap_integer_prefix)
> +#
> +# This variable must be declared as \`static const char *const var\[\]\',
> +# and must also be NUL-terminated, like the following example:
> +#
> +#   static const char *const example\[\] \= \{ "prefix1", "prefix2", NULL \};
> +v:const char *const *:stap_integer_prefix:::0:0::0:pstring_list (gdbarch->stap_integer_prefix)
>  
> -# Suffix used to mark an integer constant on the architecture's assembly.
> -v:const char *:stap_integer_suffix:::0:0::0:pstring (gdbarch->stap_integer_suffix)
> +# Suffix(es) used to mark an integer constant on the architecture's assembly.
> +#
> +# This variable must be declared as \`static const char *const var\[\]\',
> +# and must also be NUL-terminated, like the following example:
> +#
> +#   static const char *const example\[\] \= \{ "prefix1", "prefix2", NULL \};
> +v:const char *const *:stap_integer_suffix:::0:0::0:pstring_list (gdbarch->stap_integer_suffix)
>  
> -# Prefix used to mark a register name on the architecture's assembly.
> +# Prefix(es) used to mark a register name on the architecture's assembly.
>  # For example, on x86 the register name is written as:
>  #
>  #  \%eax ;; register eax
>  #
>  # in this case, this prefix would be the character \`\%\'.
> -v:const char *:stap_register_prefix:::0:0::0:pstring (gdbarch->stap_register_prefix)
> +#
> +# This variable must be declared as \`static const char *const var\[\]\',
> +# and must also be NUL-terminated, like the following example:
> +#
> +#   static const char *const example\[\] \= \{ "prefix1", "prefix2", NULL \};
> +v:const char *const *:stap_register_prefix:::0:0::0:pstring_list (gdbarch->stap_register_prefix)
>  
> -# Suffix used to mark a register name on the architecture's assembly
> -v:const char *:stap_register_suffix:::0:0::0:pstring (gdbarch->stap_register_suffix)
> +# Suffix(es) used to mark a register name on the architecture's assembly
> +#
> +# This variable must be declared as \`static const char *const var\[\]\',
> +# and must also be NUL-terminated, like the following example:
> +#
> +#   static const char *const example\[\] \= \{ "prefix1", "prefix2", NULL \};
> +v:const char *const *:stap_register_suffix:::0:0::0:pstring_list (gdbarch->stap_register_suffix)
>  
> -# Prefix used to mark a register indirection on the architecture's assembly.
> +# Prefix(es) used to mark a register indirection on the architecture's assembly.
>  # For example, on x86 the register indirection is written as:
>  #
>  #  \(\%eax\) ;; indirecting eax
> @@ -857,9 +877,14 @@ v:const char *:stap_register_suffix:::0:0::0:pstring (gdbarch->stap_register_suf
>  #
>  # Please note that we use the indirection prefix also for register
>  # displacement, e.g., \`4\(\%eax\)\' on x86.
> -v:const char *:stap_register_indirection_prefix:::0:0::0:pstring (gdbarch->stap_register_indirection_prefix)
> +#
> +# This variable must be declared as \`static const char *const var\[\]\',
> +# and must also be NUL-terminated, like the following example:
> +#
> +#   static const char *const example \= \{ "prefix1", "prefix2", NULL \};
> +v:const char *const *:stap_register_indirection_prefix:::0:0::0:pstring_list (gdbarch->stap_register_indirection_prefix)
>  
> -# Suffix used to mark a register indirection on the architecture's assembly.
> +# Suffix(es) used to mark a register indirection on the architecture's assembly.
>  # For example, on x86 the register indirection is written as:
>  #
>  #  \(\%eax\) ;; indirecting eax
> @@ -868,9 +893,14 @@ v:const char *:stap_register_indirection_prefix:::0:0::0:pstring (gdbarch->stap_
>  #
>  # Please note that we use the indirection suffix also for register
>  # displacement, e.g., \`4\(\%eax\)\' on x86.
> -v:const char *:stap_register_indirection_suffix:::0:0::0:pstring (gdbarch->stap_register_indirection_suffix)
> +#
> +# This variable must be declared as \`static const char *const var\[\]\',
> +# and must also be NUL-terminated, like the following example:
> +#
> +#   static const char *const example \= \{ "prefix1", "prefix2", NULL \};
> +v:const char *const *:stap_register_indirection_suffix:::0:0::0:pstring_list (gdbarch->stap_register_indirection_suffix)
>  
> -# Prefix used to name a register using GDB's nomenclature.
> +# Prefix(es) used to name a register using GDB's nomenclature.
>  #
>  # For example, on PPC a register is represented by a number in the assembly
>  # language (e.g., \`10\' is the 10th general-purpose register).  However,
> @@ -1481,6 +1511,29 @@ pstring (const char *string)
>    return string;
>  }
>  
> +static char *
> +pstring_list (const char *const *list)
> +{
> +  static char ret[100];
> +  const char *const *p;
> +  int offset = 0;
> +
> +  if (list == NULL)
> +    return "(null)";
> +
> +  ret[0] = '\0';
> +  for (p = list; *p != NULL && offset < sizeof (ret); ++p)
> +    {
> +      xsnprintf (ret + offset, sizeof (ret) - offset, "%s, ", *p);
> +      offset += 2 + strlen (*p);
> +    }
> +
> +  if (offset > 0)
> +    ret[offset - 2] = '\0';
> +
> +  return ret;
> +}
> +
>  EOF
>  
>  # gdbarch open the gdbarch object
> diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
> index a1a4453..c01c9c2 100644
> --- a/gdb/i386-tdep.c
> +++ b/gdb/i386-tdep.c
> @@ -3919,14 +3919,21 @@ i386_stap_parse_special_token (struct gdbarch *gdbarch,
>  void
>  i386_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>  {
> +  static const char *const stap_integer_prefix[] = { "$", NULL };
> +  static const char *const stap_register_prefix[] = { "%", NULL };
> +  static const char *const stap_register_indirection_prefix[] = { "(", NULL };
> +  static const char *const stap_register_indirection_suffix[] = { ")", NULL };
> +
>    /* We typically use stabs-in-ELF with the SVR4 register numbering.  */
>    set_gdbarch_stab_reg_to_regnum (gdbarch, i386_svr4_reg_to_regnum);
>  
>    /* Registering SystemTap handlers.  */
> -  set_gdbarch_stap_integer_prefix (gdbarch, "$");
> -  set_gdbarch_stap_register_prefix (gdbarch, "%");
> -  set_gdbarch_stap_register_indirection_prefix (gdbarch, "(");
> -  set_gdbarch_stap_register_indirection_suffix (gdbarch, ")");
> +  set_gdbarch_stap_integer_prefix (gdbarch, stap_integer_prefix);
> +  set_gdbarch_stap_register_prefix (gdbarch, stap_register_prefix);
> +  set_gdbarch_stap_register_indirection_prefix (gdbarch,
> +					    stap_register_indirection_prefix);
> +  set_gdbarch_stap_register_indirection_suffix (gdbarch,
> +					    stap_register_indirection_suffix);
>    set_gdbarch_stap_is_single_operand (gdbarch,
>  				      i386_stap_is_single_operand);
>    set_gdbarch_stap_parse_special_token (gdbarch,
> diff --git a/gdb/ia64-linux-tdep.c b/gdb/ia64-linux-tdep.c
> index d1eb529..b73a5fb 100644
> --- a/gdb/ia64-linux-tdep.c
> +++ b/gdb/ia64-linux-tdep.c
> @@ -135,6 +135,9 @@ static void
>  ia64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>  {
>    struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
> +  static const char *const stap_register_prefix[] = { "r", NULL };
> +  static const char *const stap_register_indirection_prefix[] = { "[", NULL };
> +  static const char *const stap_register_indirection_suffix[] = { "]", NULL };
>  
>    linux_init_abi (info, gdbarch);
>  
> @@ -157,9 +160,11 @@ ia64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>                                               svr4_fetch_objfile_link_map);
>  
>    /* SystemTap related.  */
> -  set_gdbarch_stap_register_prefix (gdbarch, "r");
> -  set_gdbarch_stap_register_indirection_prefix (gdbarch, "[");
> -  set_gdbarch_stap_register_indirection_suffix (gdbarch, "]");
> +  set_gdbarch_stap_register_prefix (gdbarch, stap_register_prefix);
> +  set_gdbarch_stap_register_indirection_prefix (gdbarch,
> +					    stap_register_indirection_prefix);
> +  set_gdbarch_stap_register_indirection_suffix (gdbarch,
> +					    stap_register_indirection_suffix);
>    set_gdbarch_stap_gdb_register_prefix (gdbarch, "r");
>    set_gdbarch_stap_is_single_operand (gdbarch,
>  				      ia64_linux_stap_is_single_operand);
> diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
> index fc09560..890e5e5 100644
> --- a/gdb/ppc-linux-tdep.c
> +++ b/gdb/ppc-linux-tdep.c
> @@ -1245,6 +1245,9 @@ ppc_linux_init_abi (struct gdbarch_info info,
>  {
>    struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
>    struct tdesc_arch_data *tdesc_data = (void *) info.tdep_info;
> +  static const char *const stap_integer_prefix[] = { "i", NULL };
> +  static const char *const stap_register_indirection_prefix[] = { "(", NULL };
> +  static const char *const stap_register_indirection_suffix[] = { ")", NULL };
>  
>    linux_init_abi (info, gdbarch);
>  
> @@ -1263,9 +1266,11 @@ ppc_linux_init_abi (struct gdbarch_info info,
>    set_gdbarch_get_syscall_number (gdbarch, ppc_linux_get_syscall_number);
>  
>    /* SystemTap functions.  */
> -  set_gdbarch_stap_integer_prefix (gdbarch, "i");
> -  set_gdbarch_stap_register_indirection_prefix (gdbarch, "(");
> -  set_gdbarch_stap_register_indirection_suffix (gdbarch, ")");
> +  set_gdbarch_stap_integer_prefix (gdbarch, stap_integer_prefix);
> +  set_gdbarch_stap_register_indirection_prefix (gdbarch,
> +					    stap_register_indirection_prefix);
> +  set_gdbarch_stap_register_indirection_suffix (gdbarch,
> +					    stap_register_indirection_suffix);
>    set_gdbarch_stap_gdb_register_prefix (gdbarch, "r");
>    set_gdbarch_stap_is_single_operand (gdbarch, ppc_stap_is_single_operand);
>    set_gdbarch_stap_parse_special_token (gdbarch,
> diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
> index cd41de5..d521c2e 100644
> --- a/gdb/s390-linux-tdep.c
> +++ b/gdb/s390-linux-tdep.c
> @@ -3026,6 +3026,9 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>    int have_linux_v1 = 0;
>    int have_linux_v2 = 0;
>    int first_pseudo_reg, last_pseudo_reg;
> +  static const char *const stap_register_prefix[] = { "%", NULL };
> +  static const char *const stap_register_indirection_prefix[] = { "(", NULL };
> +  static const char *const stap_register_indirection_suffix[] = { ")", NULL };
>  
>    /* Default ABI and register size.  */
>    switch (info.bfd_arch_info->mach)
> @@ -3358,9 +3361,11 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
>    set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type);
>  
>    /* SystemTap functions.  */
> -  set_gdbarch_stap_register_prefix (gdbarch, "%");
> -  set_gdbarch_stap_register_indirection_prefix (gdbarch, "(");
> -  set_gdbarch_stap_register_indirection_suffix (gdbarch, ")");
> +  set_gdbarch_stap_register_prefix (gdbarch, stap_register_prefix);
> +  set_gdbarch_stap_register_indirection_prefix (gdbarch,
> +					    stap_register_indirection_prefix);
> +  set_gdbarch_stap_register_indirection_suffix (gdbarch,
> +					    stap_register_indirection_suffix);
>    set_gdbarch_stap_is_single_operand (gdbarch, s390_stap_is_single_operand);
>  
>    return gdbarch;
> diff --git a/gdb/stap-probe.c b/gdb/stap-probe.c
> index 33d4569..625ec38 100644
> --- a/gdb/stap-probe.c
> +++ b/gdb/stap-probe.c
> @@ -346,6 +346,171 @@ stap_get_expected_argument_type (struct gdbarch *gdbarch,
>      }
>  }
>  
> +/* Helper function to check for a generic list of prefixes.  Return 1
> +   if any prefix has been found, zero otherwise.  */
> +
> +static int
> +stap_is_generic_prefix (struct gdbarch *gdbarch, const char *s,
> +			const char **r, const char *const *prefixes)
> +{
> +  const char *const *p;
> +
> +  if (prefixes == NULL)
> +    {
> +      if (r != NULL)
> +	*r = "";
> +
> +      return 1;
> +    }
> +
> +  for (p = prefixes; *p != NULL; ++p)
> +    {
> +      if (strncasecmp (s, *p, strlen (*p)) == 0)
> +	{
> +	  if (r != NULL)
> +	    *r = *p;
> +
> +	  return 1;
> +	}
> +    }
> +
> +  return 0;
> +}
> +
> +/* Return 1 if S points to a register prefix, zero otherwise.  */
> +
> +static int
> +stap_is_register_prefix (struct gdbarch *gdbarch, const char *s,
> +			 const char **r)
> +{
> +  const char *const *t = gdbarch_stap_register_prefix (gdbarch);
> +
> +  return stap_is_generic_prefix (gdbarch, s, r, t);
> +}
> +
> +/* Return 1 if S points to a register indirection prefix, zero
> +   otherwise.  */
> +
> +static int
> +stap_is_register_indirection_prefix (struct gdbarch *gdbarch, const char *s,
> +				     const char **r)
> +{
> +  const char *const *t = gdbarch_stap_register_indirection_prefix (gdbarch);
> +
> +  return stap_is_generic_prefix (gdbarch, s, r, t);
> +}
> +
> +/* Return 1 if S points to an integer prefix, zero otherwise.
> +
> +   This function takes care of analyzing whether we are dealing with
> +   an expected integer prefix, or, if there is no integer prefix to be
> +   expected, whether we are dealing with a digit.  */
> +
> +static int
> +stap_is_integer_prefix (struct gdbarch *gdbarch, const char *s,
> +			const char **r)
> +{
> +  const char *const *t = gdbarch_stap_integer_prefix (gdbarch);
> +  const char *const *p;
> +
> +  if (t == NULL)
> +    {
> +      /* A NULL value here means that integers do not have prefix.  We
> +	 just check for a digit then.  */
> +      if (r != NULL)
> +	*r = "";
> +
> +      return isdigit (*s);
> +    }
> +
> +  for (p = t; *p != NULL; ++p)
> +    {
> +      size_t len = strlen (*p);
> +
> +      if ((len == 0 && isdigit (*s))
> +	  || (len > 0 && strncasecmp (s, *p, len) == 0))
> +	{
> +	  /* Integers may or may not have a prefix.  The "len == 0"
> +	     check covers the case when integers do not have a prefix
> +	     (therefore, we just check if we have a digit).  The call
> +	     to "strncasecmp" covers the case when they have a
> +	     prefix.  */
> +	  if (r != NULL)
> +	    *r = *p;
> +
> +	  return 1;
> +	}
> +    }
> +
> +  return 0;
> +}
> +
> +/* Helper function to check for a generic list of suffixes.  If we are
> +   not expecting any suffixes, then it just returns 1.  If we are
> +   expecting at least one suffix, then it returns 1 if a suffix has
> +   been found, zero otherwise.  */
> +
> +static int
> +stap_generic_check_suffix (struct gdbarch *gdbarch, const char *s,
> +			   const char **r, const char *const *suffixes)
> +{
> +  const char *const *p;
> +  int found = 0;
> +
> +  if (suffixes == NULL)
> +    {
> +      if (r != NULL)
> +	*r = "";
> +
> +      return 1;
> +    }
> +
> +  for (p = suffixes; *p != NULL; ++p)
> +    if (strncasecmp (s, *p, strlen (*p)) == 0)
> +      {
> +	if (r != NULL)
> +	  *r = *p;
> +
> +	found = 1;
> +	break;
> +      }
> +
> +  return found;
> +}
> +
> +/* Return 1 if S points to an integer suffix, zero otherwise.  */
> +
> +static int
> +stap_check_integer_suffix (struct gdbarch *gdbarch, const char *s,
> +			   const char **r)
> +{
> +  const char *const *p = gdbarch_stap_integer_suffix (gdbarch);
> +
> +  return stap_generic_check_suffix (gdbarch, s, r, p);
> +}
> +
> +/* Return 1 if S points to a register suffix, zero otherwise.  */
> +
> +static int
> +stap_check_register_suffix (struct gdbarch *gdbarch, const char *s,
> +			    const char **r)
> +{
> +  const char *const *p = gdbarch_stap_register_suffix (gdbarch);
> +
> +  return stap_generic_check_suffix (gdbarch, s, r, p);
> +}
> +
> +/* Return 1 if S points to a register indirection suffix, zero otherwise.  */
> +
> +static int
> +stap_check_register_indirection_suffix (struct gdbarch *gdbarch, const char *s,
> +					const char **r)
> +{
> +  const char *const *p = gdbarch_stap_register_indirection_suffix (gdbarch);
> +
> +  return stap_generic_check_suffix (gdbarch, s, r, p);
> +}
> +
>  /* Function responsible for parsing a register operand according to
>     SystemTap parlance.  Assuming:
>  
> @@ -385,24 +550,14 @@ stap_parse_register_operand (struct stap_parse_info *p)
>    const char *start;
>    char *regname;
>    int len;
> -
> -  /* Prefixes for the parser.  */
> -  const char *reg_prefix = gdbarch_stap_register_prefix (gdbarch);
> -  const char *reg_ind_prefix
> -    = gdbarch_stap_register_indirection_prefix (gdbarch);
>    const char *gdb_reg_prefix = gdbarch_stap_gdb_register_prefix (gdbarch);
> -  int reg_prefix_len = reg_prefix ? strlen (reg_prefix) : 0;
> -  int reg_ind_prefix_len = reg_ind_prefix ? strlen (reg_ind_prefix) : 0;
>    int gdb_reg_prefix_len = gdb_reg_prefix ? strlen (gdb_reg_prefix) : 0;
> -
> -  /* Suffixes for the parser.  */
> -  const char *reg_suffix = gdbarch_stap_register_suffix (gdbarch);
> -  const char *reg_ind_suffix
> -    = gdbarch_stap_register_indirection_suffix (gdbarch);
>    const char *gdb_reg_suffix = gdbarch_stap_gdb_register_suffix (gdbarch);
> -  int reg_suffix_len = reg_suffix ? strlen (reg_suffix) : 0;
> -  int reg_ind_suffix_len = reg_ind_suffix ? strlen (reg_ind_suffix) : 0;
>    int gdb_reg_suffix_len = gdb_reg_suffix ? strlen (gdb_reg_suffix) : 0;
> +  const char *reg_prefix;
> +  const char *reg_ind_prefix;
> +  const char *reg_suffix;
> +  const char *reg_ind_suffix;
>  
>    /* Checking for a displacement argument.  */
>    if (*p->arg == '+')
> @@ -438,11 +593,10 @@ stap_parse_register_operand (struct stap_parse_info *p)
>      }
>  
>    /* Getting rid of register indirection prefix.  */
> -  if (reg_ind_prefix
> -      && strncmp (p->arg, reg_ind_prefix, reg_ind_prefix_len) == 0)
> +  if (stap_is_register_indirection_prefix (gdbarch, p->arg, &reg_ind_prefix))
>      {
>        indirect_p = 1;
> -      p->arg += reg_ind_prefix_len;
> +      p->arg += strlen (reg_ind_prefix);
>      }
>  
>    if (disp_p && !indirect_p)
> @@ -450,8 +604,8 @@ stap_parse_register_operand (struct stap_parse_info *p)
>  	   p->saved_arg);
>  
>    /* Getting rid of register prefix.  */
> -  if (reg_prefix && strncmp (p->arg, reg_prefix, reg_prefix_len) == 0)
> -    p->arg += reg_prefix_len;
> +  if (stap_is_register_prefix (gdbarch, p->arg, &reg_prefix))
> +    p->arg += strlen (reg_prefix);
>  
>    /* Now we should have only the register name.  Let's extract it and get
>       the associated number.  */
> @@ -509,23 +663,21 @@ stap_parse_register_operand (struct stap_parse_info *p)
>      }
>  
>    /* Getting rid of the register name suffix.  */
> -  if (reg_suffix)
> -    {
> -      if (strncmp (p->arg, reg_suffix, reg_suffix_len) != 0)
> -	error (_("Missing register name suffix `%s' on expression `%s'."),
> -	       reg_suffix, p->saved_arg);
> -
> -      p->arg += reg_suffix_len;
> -    }
> +  if (stap_check_register_suffix (gdbarch, p->arg, &reg_suffix))
> +    p->arg += strlen (reg_suffix);
> +  else
> +    error (_("Missing register name suffix on expression `%s'."),
> +	   p->saved_arg);
>  
>    /* Getting rid of the register indirection suffix.  */
> -  if (indirect_p && reg_ind_suffix)
> +  if (indirect_p)
>      {
> -      if (strncmp (p->arg, reg_ind_suffix, reg_ind_suffix_len) != 0)
> -	error (_("Missing indirection suffix `%s' on expression `%s'."),
> -	       reg_ind_suffix, p->saved_arg);
> -
> -      p->arg += reg_ind_suffix_len;
> +      if (stap_check_register_indirection_suffix (gdbarch, p->arg,
> +						  &reg_ind_suffix))
> +	p->arg += strlen (reg_ind_suffix);
> +      else
> +	error (_("Missing indirection suffix on expression `%s'."),
> +	       p->saved_arg);
>      }
>  }
>  
> @@ -548,19 +700,7 @@ static void
>  stap_parse_single_operand (struct stap_parse_info *p)
>  {
>    struct gdbarch *gdbarch = p->gdbarch;
> -
> -  /* Prefixes for the parser.  */
> -  const char *const_prefix = gdbarch_stap_integer_prefix (gdbarch);
> -  const char *reg_prefix = gdbarch_stap_register_prefix (gdbarch);
> -  const char *reg_ind_prefix
> -    = gdbarch_stap_register_indirection_prefix (gdbarch);
> -  int const_prefix_len = const_prefix ? strlen (const_prefix) : 0;
> -  int reg_prefix_len = reg_prefix ? strlen (reg_prefix) : 0;
> -  int reg_ind_prefix_len = reg_ind_prefix ? strlen (reg_ind_prefix) : 0;
> -
> -  /* Suffixes for the parser.  */
> -  const char *const_suffix = gdbarch_stap_integer_suffix (gdbarch);
> -  int const_suffix_len = const_suffix ? strlen (const_suffix) : 0;
> +  const char *int_prefix = NULL;
>  
>    /* We first try to parse this token as a "special token".  */
>    if (gdbarch_stap_parse_special_token_p (gdbarch))
> @@ -607,8 +747,7 @@ stap_parse_single_operand (struct stap_parse_info *p)
>  	  tmp = endp;
>  	}
>  
> -      if (!reg_ind_prefix
> -	  || strncmp (tmp, reg_ind_prefix, reg_ind_prefix_len) != 0)
> +      if (!stap_is_register_indirection_prefix (gdbarch, tmp, NULL))
>  	{
>  	  /* This is not a displacement.  We skip the operator, and deal
>  	     with it later.  */
> @@ -637,16 +776,23 @@ stap_parse_single_operand (struct stap_parse_info *p)
>        char *endp;
>        long number;
>  
> -      /* We can be dealing with a numeric constant (if `const_prefix' is
> -	 NULL), or with a register displacement.  */
> +      /* We can be dealing with a numeric constant, or with a register
> +	 displacement.  */
>        number = strtol (tmp, &endp, 10);
>        tmp = endp;
>  
>        if (p->inside_paren_p)
>  	tmp = skip_spaces_const (tmp);
> -      if (!const_prefix && reg_ind_prefix
> -	  && strncmp (tmp, reg_ind_prefix, reg_ind_prefix_len) != 0)
> +
> +      /* If "stap_is_integer_prefix" returns true, it means we can
> +	 accept integers without a prefix here.  But we also need to
> +	 check whether the next token (i.e., "tmp") is not a register
> +	 indirection prefix.  */
> +      if (stap_is_integer_prefix (gdbarch, p->arg, NULL)
> +	  && !stap_is_register_indirection_prefix (gdbarch, tmp, NULL))
>  	{
> +	  const char *int_suffix;
> +
>  	  /* We are dealing with a numeric constant.  */
>  	  write_exp_elt_opcode (OP_LONG);
>  	  write_exp_elt_type (builtin_type (gdbarch)->builtin_long);
> @@ -655,30 +801,26 @@ stap_parse_single_operand (struct stap_parse_info *p)
>  
>  	  p->arg = tmp;
>  
> -	  if (const_suffix)
> -	    {
> -	      if (strncmp (p->arg, const_suffix, const_suffix_len) == 0)
> -		p->arg += const_suffix_len;
> -	      else
> -		error (_("Invalid constant suffix on expression `%s'."),
> -		       p->saved_arg);
> -	    }
> +	  if (stap_check_integer_suffix (gdbarch, p->arg, &int_suffix))
> +	    p->arg += strlen (int_suffix);
> +	  else
> +	    error (_("Invalid constant suffix on expression `%s'."),
> +		   p->saved_arg);
>  	}
> -      else if (reg_ind_prefix
> -	       && strncmp (tmp, reg_ind_prefix, reg_ind_prefix_len) == 0)
> +      else if (stap_is_register_indirection_prefix (gdbarch, tmp, NULL))
>  	stap_parse_register_operand (p);
>        else
>  	error (_("Unknown numeric token on expression `%s'."),
>  	       p->saved_arg);
>      }
> -  else if (const_prefix
> -	   && strncmp (p->arg, const_prefix, const_prefix_len) == 0)
> +  else if (stap_is_integer_prefix (gdbarch, p->arg, &int_prefix))
>      {
>        /* We are dealing with a numeric constant.  */
>        long number;
>        char *endp;
> +      const char *int_suffix;
>  
> -      p->arg += const_prefix_len;
> +      p->arg += strlen (int_prefix);
>        number = strtol (p->arg, &endp, 10);
>        p->arg = endp;
>  
> @@ -687,19 +829,14 @@ stap_parse_single_operand (struct stap_parse_info *p)
>        write_exp_elt_longcst (number);
>        write_exp_elt_opcode (OP_LONG);
>  
> -      if (const_suffix)
> -	{
> -	  if (strncmp (p->arg, const_suffix, const_suffix_len) == 0)
> -	    p->arg += const_suffix_len;
> -	  else
> -	    error (_("Invalid constant suffix on expression `%s'."),
> -		   p->saved_arg);
> -	}
> +      if (stap_check_integer_suffix (gdbarch, p->arg, &int_suffix))
> +	p->arg += strlen (int_suffix);
> +      else
> +	error (_("Invalid constant suffix on expression `%s'."),
> +	       p->saved_arg);
>      }
> -  else if ((reg_prefix
> -	    && strncmp (p->arg, reg_prefix, reg_prefix_len) == 0)
> -	   || (reg_ind_prefix
> -	       && strncmp (p->arg, reg_ind_prefix, reg_ind_prefix_len) == 0))
> +  else if (stap_is_register_prefix (gdbarch, p->arg, NULL)
> +	   || stap_is_register_indirection_prefix (gdbarch, p->arg, NULL))
>      stap_parse_register_operand (p);
>    else
>      error (_("Operator `%c' not recognized on expression `%s'."),
> -- 
> 1.7.11.7

-- 
Sergio

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Extend SystemTap SDT probe argument parser
  2013-12-16 17:01 ` Sergio Durigan Junior
@ 2013-12-16 17:09   ` Mark Kettenis
  2013-12-16 17:16     ` Sergio Durigan Junior
  0 siblings, 1 reply; 10+ messages in thread
From: Mark Kettenis @ 2013-12-16 17:09 UTC (permalink / raw)
  To: sergiodj; +Cc: gdb-patches

> From: Sergio Durigan Junior <sergiodj@redhat.com>
> Date: Mon, 16 Dec 2013 15:01:38 -0200
> 
> On Wednesday, December 11 2013, I wrote:
> 
> > This patch extends the current generic parser for SystemTap SDT probe
> > arguments.  It can be almost considered a cleanup, but the main point of
> > it is actually to allow the generic parser to accept multiple prefixes
> > and suffixes for the its operands (i.e., integers, register names, and
> > register indirection).
> 
> Ping.

Can't say I like the added complexity, but the i386/amd64 are ok.

> > I have chosen to implement this as a list of const strings, which needs
> > to be declared as "static const char *const *", and is provided to
> > gdbarch on initialization.  I think it is cleaner to implement it this
> > way, but for a moment I wondered whether demanding the variables to be
> > declared as "static" is a good idea...  After some thought and
> > discussion, I decided to leave it as is.
> >
> > This patch is actually a preparation for an upcoming patch for ARM,
> > which implements the support for multiple integer prefixes (as defined
> > by ARM's asm spec).  And AArch64 will also need this, for the same
> > reason.
> >
> > This patch was regtested on all architectures that it touches (i.e.,
> > i386, x86_64, ARM, PPC/PPC64, s390x and IA-64).  No regressions were found.
> >
> > 2013-12-11  Sergio Durigan Junior  <sergiodj@redhat.com>
> >
> > 	* amd64-tdep.c (amd64_init_abi): Declare SystemTap SDT probe
> > 	argument prefixes and suffixes.  Initialize gdbarch with them.
> > 	* arm-linux-tdep.c (arm_linux_init_abi): Likewise.
> > 	* gdbarch.c: Regenerate.
> > 	* gdbarch.h: Regenerate.
> > 	* gdbarch.sh (stap_integer_prefix, stap_integer_suffix)
> > 	(stap_register_prefix, stap_register_suffix)
> > 	(stap_register_indirection_prefix)
> > 	(stap_register_indirection_suffix): Declare as "const char *const
> > 	*" instead of "const char *".  Adjust printing function.
> > 	(pstring_list): New function.
> > 	* i386-tdep.c (i386_elf_init_abi): Declare SystemTap SDT probe
> > 	argument prefixes and suffixes.  Initialize gdbarch with them.
> > 	* ia64-linux-tdep.c (ia64_linux_init_abi): Likewise.
> > 	* ppc-linux-tdep.c (ppc_linux_init_abi): Likewise.
> > 	* s390-linux-tdep.c (s390_gdbarch_init): Likewise.
> > 	* stap-probe.c (stap_is_generic_prefix): New function.
> > 	(stap_is_register_prefix): Likewise.
> > 	(stap_is_register_indirection_prefix): Likewise.
> > 	(stap_is_integer_prefix): Likewise.
> > 	(stap_generic_check_suffix): Likewise.
> > 	(stap_check_integer_suffix): Likewise.
> > 	(stap_check_register_suffix): Likewise.
> > 	(stap_check_register_indirection_suffix): Likewise.
> > 	(stap_parse_register_operand): Remove unecessary declarations for
> > 	variables holding prefix and suffix information.  Use the new
> > 	functions listed above for checking for prefixes and suffixes.
> > 	(stap_parse_single_operand): Likewise.
> > ---
> >  gdb/ChangeLog         |  31 ++++++
> >  gdb/amd64-tdep.c      |  14 ++-
> >  gdb/arm-linux-tdep.c  |  14 ++-
> >  gdb/gdbarch.c         |  71 +++++++-----
> >  gdb/gdbarch.h         |  76 +++++++++----
> >  gdb/gdbarch.sh        |  79 +++++++++++---
> >  gdb/i386-tdep.c       |  15 ++-
> >  gdb/ia64-linux-tdep.c |  11 +-
> >  gdb/ppc-linux-tdep.c  |  11 +-
> >  gdb/s390-linux-tdep.c |  11 +-
> >  gdb/stap-probe.c      | 291 +++++++++++++++++++++++++++++++++++++-------------

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Extend SystemTap SDT probe argument parser
  2013-12-16 17:09   ` Mark Kettenis
@ 2013-12-16 17:16     ` Sergio Durigan Junior
  0 siblings, 0 replies; 10+ messages in thread
From: Sergio Durigan Junior @ 2013-12-16 17:16 UTC (permalink / raw)
  To: Mark Kettenis; +Cc: gdb-patches

On Monday, December 16 2013, Mark Kettenis wrote:

>> From: Sergio Durigan Junior <sergiodj@redhat.com>
>> Date: Mon, 16 Dec 2013 15:01:38 -0200
>> 
>> On Wednesday, December 11 2013, I wrote:
>> 
>> > This patch extends the current generic parser for SystemTap SDT probe
>> > arguments.  It can be almost considered a cleanup, but the main point of
>> > it is actually to allow the generic parser to accept multiple prefixes
>> > and suffixes for the its operands (i.e., integers, register names, and
>> > register indirection).
>> 
>> Ping.
>
> Can't say I like the added complexity, but the i386/amd64 are ok.

Thanks for the approval.

I wonder what exactly you didn't like, and if you have some opinion on
how to improve it.

Thanks,

-- 
Sergio

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Extend SystemTap SDT probe argument parser
  2013-12-11  3:56 [PATCH] Extend SystemTap SDT probe argument parser Sergio Durigan Junior
  2013-12-16 17:01 ` Sergio Durigan Junior
@ 2013-12-17 11:03 ` Pedro Alves
  2013-12-17 17:28   ` Sergio Durigan Junior
  1 sibling, 1 reply; 10+ messages in thread
From: Pedro Alves @ 2013-12-17 11:03 UTC (permalink / raw)
  To: Sergio Durigan Junior; +Cc: GDB Patches

On 12/11/2013 03:55 AM, Sergio Durigan Junior wrote:
> I have chosen to implement this as a list of const strings, which needs
> to be declared as "static const char *const *", and is provided to
> gdbarch on initialization.  I think it is cleaner to implement it this
> way, but for a moment I wondered whether demanding the variables to be
> declared as "static" is a good idea...  After some thought and
> discussion, I decided to leave it as is.

AFAICS, nothing in the interface "demands" static.  What is required
is that the array outlives the gdbarch method call.  So usually,
you'll make the array either static global, or static to a function.
That is, this would work just as well with the same gdbarch interface:

--- a/gdb/amd64-tdep.c
+++ b/gdb/amd64-tdep.c
+const char *const stap_integer_prefix[] = { "$", NULL };
+const char *const stap_register_prefix[] = { "%", NULL };
+const char *const stap_register_indirection_prefix[] = { "(", NULL };
+const char *const stap_register_indirection_suffix[] = { ")", NULL };
+
 void
 amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   const struct target_desc *tdesc = info.target_desc;


Or even, allocating "stap_integer_prefix" etc. on the
heap (xmalloc, etc.).

"static" or not is a detail of the arch's gdbarch hook implementation.

> +	* gdbarch.sh (stap_integer_prefix, stap_integer_suffix)
> +	(stap_register_prefix, stap_register_suffix)
> +	(stap_register_indirection_prefix)
> +	(stap_register_indirection_suffix): Declare as "const char *const
> +	*" instead of "const char *".  Adjust printing function.

As we're touching all the hooks anyway, can we rename them to
the plural "prefixes" and "suffixes" ?  I'd find that clearer.

>
> +static char *
> +pstring_list (const char *const *list)

Please add an intro comment.

> +{
> +  static char ret[100];
> +  const char *const *p;
> +  int offset = 0;

size_t.

> +
> +  if (list == NULL)
> +    return "(null)";
> +
> +  ret[0] = '\0';
> +  for (p = list; *p != NULL && offset < sizeof (ret); ++p)
> +    {
> +      xsnprintf (ret + offset, sizeof (ret) - offset, "%s, ", *p);
> +      offset += 2 + strlen (*p);

You can use the return of xsnprintf instead of strlen.

> +    }
> +

Also, currently unlikely, but if this function ends up used
in the future with a bigger list, we'll get silent truncation.
I think we should assert instead that doesn't happen.

> +  if (offset > 0)
> +    ret[offset - 2] = '\0';
> +
> +  return ret;
> +}
> +

>  # in this case, this prefix would be the character \`\$\'.
> -v:const char *:stap_integer_prefix:::0:0::0:pstring (gdbarch->stap_integer_prefix)
> +#
> +# This variable must be declared as \`static const char *const var\[\]\',
> +# and must also be NUL-terminated, like the following example:
> +#

It's a NULL pointer, not NUL, the null character.  So, "NULL-terminated".

I'd remove the "must be" part, and just say:

-   Prefix used to mark an integer constant on the architecture's assembly
+   A NULL-terminated array of prefixes used to mark an integer constant on the architecture's assembly.
    For example, on x86 integer constants are written as:

( reindented, of course )


> +/* Helper function to check for a generic list of prefixes.  Return 1
> +   if any prefix has been found, zero otherwise.  */

Please describe the parameters and the contract.  Some of these
arguments can be NULL.  We do a case insensitive match.  Etc.
Likewise stap_generic_check_suffix and possibly others.  If
there's some central function that describes all this, then
you can point at it: "arguments are like foo", or some such.

> +
> +static int
> +stap_is_generic_prefix (struct gdbarch *gdbarch, const char *s,
> +			const char **r, const char *const *prefixes)
> +{

> +      /* A NULL value here means that integers do not have prefix.  We
> +	 just check for a digit then.  */

"have a prefix" ?

Otherwise looks good to me.

Thanks,
-- 
Pedro Alves

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Extend SystemTap SDT probe argument parser
  2013-12-17 11:03 ` Pedro Alves
@ 2013-12-17 17:28   ` Sergio Durigan Junior
  2013-12-17 19:46     ` Pedro Alves
  2013-12-19 20:58     ` Sergio Durigan Junior
  0 siblings, 2 replies; 10+ messages in thread
From: Sergio Durigan Junior @ 2013-12-17 17:28 UTC (permalink / raw)
  To: Pedro Alves; +Cc: GDB Patches

On Tuesday, December 17 2013, Pedro Alves wrote:

> On 12/11/2013 03:55 AM, Sergio Durigan Junior wrote:
>> I have chosen to implement this as a list of const strings, which needs
>> to be declared as "static const char *const *", and is provided to
>> gdbarch on initialization.  I think it is cleaner to implement it this
>> way, but for a moment I wondered whether demanding the variables to be
>> declared as "static" is a good idea...  After some thought and
>> discussion, I decided to leave it as is.
>
> AFAICS, nothing in the interface "demands" static.  What is required
> is that the array outlives the gdbarch method call.  So usually,
> you'll make the array either static global, or static to a function.
> That is, this would work just as well with the same gdbarch interface:
>
> --- a/gdb/amd64-tdep.c
> +++ b/gdb/amd64-tdep.c
> +const char *const stap_integer_prefix[] = { "$", NULL };
> +const char *const stap_register_prefix[] = { "%", NULL };
> +const char *const stap_register_indirection_prefix[] = { "(", NULL };
> +const char *const stap_register_indirection_suffix[] = { ")", NULL };
> +
>  void
>  amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
>  {
>    struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
>    const struct target_desc *tdesc = info.target_desc;
>
>
> Or even, allocating "stap_integer_prefix" etc. on the
> heap (xmalloc, etc.).
>
> "static" or not is a detail of the arch's gdbarch hook implementation.

Yes, I knew it, but I should have written it in a clear way.  Thanks for
expliciting this.

Anyway, I have chosen to keep the "static" there because I think it is
better.  But as you said, someone who implements the support for a new
target may choose whatever she wants.

BTW, I will fix the commit message to remove this confusing statement.

>> +	* gdbarch.sh (stap_integer_prefix, stap_integer_suffix)
>> +	(stap_register_prefix, stap_register_suffix)
>> +	(stap_register_indirection_prefix)
>> +	(stap_register_indirection_suffix): Declare as "const char *const
>> +	*" instead of "const char *".  Adjust printing function.
>
> As we're touching all the hooks anyway, can we rename them to
> the plural "prefixes" and "suffixes" ?  I'd find that clearer.

Done.

>>
>> +static char *
>> +pstring_list (const char *const *list)
>
> Please add an intro comment.

Done.

>> +{
>> +  static char ret[100];
>> +  const char *const *p;
>> +  int offset = 0;
>
> size_t.

Done.

>> +
>> +  if (list == NULL)
>> +    return "(null)";
>> +
>> +  ret[0] = '\0';
>> +  for (p = list; *p != NULL && offset < sizeof (ret); ++p)
>> +    {
>> +      xsnprintf (ret + offset, sizeof (ret) - offset, "%s, ", *p);
>> +      offset += 2 + strlen (*p);
>
> You can use the return of xsnprintf instead of strlen.

Done.

>> +    }
>> +
>
> Also, currently unlikely, but if this function ends up used
> in the future with a bigger list, we'll get silent truncation.
> I think we should assert instead that doesn't happen.

Done.

>> +  if (offset > 0)
>> +    ret[offset - 2] = '\0';
>> +
>> +  return ret;
>> +}
>> +
>
>>  # in this case, this prefix would be the character \`\$\'.
>> -v:const char *:stap_integer_prefix:::0:0::0:pstring (gdbarch->stap_integer_prefix)
>> +#
>> +# This variable must be declared as \`static const char *const var\[\]\',
>> +# and must also be NUL-terminated, like the following example:
>> +#
>
> It's a NULL pointer, not NUL, the null character.  So, "NULL-terminated".
>
> I'd remove the "must be" part, and just say:
>
> -   Prefix used to mark an integer constant on the architecture's assembly
> +   A NULL-terminated array of prefixes used to mark an integer constant on the architecture's assembly.
>     For example, on x86 integer constants are written as:
>
> ( reindented, of course )

Done.

>> +/* Helper function to check for a generic list of prefixes.  Return 1
>> +   if any prefix has been found, zero otherwise.  */
>
> Please describe the parameters and the contract.  Some of these
> arguments can be NULL.  We do a case insensitive match.  Etc.
> Likewise stap_generic_check_suffix and possibly others.  If
> there's some central function that describes all this, then
> you can point at it: "arguments are like foo", or some such.

Done.

>> +
>> +static int
>> +stap_is_generic_prefix (struct gdbarch *gdbarch, const char *s,
>> +			const char **r, const char *const *prefixes)
>> +{
>
>> +      /* A NULL value here means that integers do not have prefix.  We
>> +	 just check for a digit then.  */
>
> "have a prefix" ?

Fixed.

> Otherwise looks good to me.

Thanks.  I guess I will wait a little more until Mark K. replies to my
question, and then I will push the following version.

-- 
Sergio

2013-12-17  Sergio Durigan Junior  <sergiodj@redhat.com>

	* amd64-tdep.c (amd64_init_abi): Declare SystemTap SDT probe
	argument prefixes and suffixes.  Initialize gdbarch with them.
	* arm-linux-tdep.c (arm_linux_init_abi): Likewise.
	* gdbarch.c: Regenerate.
	* gdbarch.h: Regenerate.
	* gdbarch.sh (stap_integer_prefix, stap_integer_suffix)
	(stap_register_prefix, stap_register_suffix)
	(stap_register_indirection_prefix)
	(stap_register_indirection_suffix): Declare as "const char *const
	*" instead of "const char *".  Adjust printing function.  Rename
	to plural.
	(pstring_list): New function.
	* i386-tdep.c (i386_elf_init_abi): Declare SystemTap SDT probe
	argument prefixes and suffixes.  Initialize gdbarch with them.
	* ia64-linux-tdep.c (ia64_linux_init_abi): Likewise.
	* ppc-linux-tdep.c (ppc_linux_init_abi): Likewise.
	* s390-linux-tdep.c (s390_gdbarch_init): Likewise.
	* stap-probe.c (stap_is_generic_prefix): New function.
	(stap_is_register_prefix): Likewise.
	(stap_is_register_indirection_prefix): Likewise.
	(stap_is_integer_prefix): Likewise.
	(stap_generic_check_suffix): Likewise.
	(stap_check_integer_suffix): Likewise.
	(stap_check_register_suffix): Likewise.
	(stap_check_register_indirection_suffix): Likewise.
	(stap_parse_register_operand): Remove unecessary declarations for
	variables holding prefix and suffix information.  Use the new
	functions listed above for checking for prefixes and suffixes.
	(stap_parse_single_operand): Likewise.

diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
index 19968fc..9efefd2 100644
--- a/gdb/amd64-tdep.c
+++ b/gdb/amd64-tdep.c
@@ -2832,6 +2832,12 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   const struct target_desc *tdesc = info.target_desc;
+  static const char *const stap_integer_prefixes[] = { "$", NULL };
+  static const char *const stap_register_prefixes[] = { "%", NULL };
+  static const char *const stap_register_indirection_prefixes[] = { "(",
+								    NULL };
+  static const char *const stap_register_indirection_suffixes[] = { ")",
+								    NULL };
 
   /* AMD64 generally uses `fxsave' instead of `fsave' for saving its
      floating-point registers.  */
@@ -2944,10 +2950,12 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
   set_gdbarch_gen_return_address (gdbarch, amd64_gen_return_address);
 
   /* SystemTap variables and functions.  */
-  set_gdbarch_stap_integer_prefix (gdbarch, "$");
-  set_gdbarch_stap_register_prefix (gdbarch, "%");
-  set_gdbarch_stap_register_indirection_prefix (gdbarch, "(");
-  set_gdbarch_stap_register_indirection_suffix (gdbarch, ")");
+  set_gdbarch_stap_integer_prefixes (gdbarch, stap_integer_prefixes);
+  set_gdbarch_stap_register_prefixes (gdbarch, stap_register_prefixes);
+  set_gdbarch_stap_register_indirection_prefixes (gdbarch,
+					  stap_register_indirection_prefixes);
+  set_gdbarch_stap_register_indirection_suffixes (gdbarch,
+					  stap_register_indirection_suffixes);
   set_gdbarch_stap_is_single_operand (gdbarch,
 				      i386_stap_is_single_operand);
   set_gdbarch_stap_parse_special_token (gdbarch,
diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c
index 9deed10..0284f69 100644
--- a/gdb/arm-linux-tdep.c
+++ b/gdb/arm-linux-tdep.c
@@ -1235,6 +1235,12 @@ static void
 arm_linux_init_abi (struct gdbarch_info info,
 		    struct gdbarch *gdbarch)
 {
+  static const char *const stap_integer_prefixes[] = { "#", NULL };
+  static const char *const stap_register_prefixes[] = { "r", NULL };
+  static const char *const stap_register_indirection_prefixes[] = { "[",
+								    NULL };
+  static const char *const stap_register_indirection_suffixes[] = { "]",
+								    NULL };
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
 
   linux_init_abi (info, gdbarch);
@@ -1334,10 +1340,12 @@ arm_linux_init_abi (struct gdbarch_info info,
   set_gdbarch_process_record (gdbarch, arm_process_record);
 
   /* SystemTap functions.  */
-  set_gdbarch_stap_integer_prefix (gdbarch, "#");
-  set_gdbarch_stap_register_prefix (gdbarch, "r");
-  set_gdbarch_stap_register_indirection_prefix (gdbarch, "[");
-  set_gdbarch_stap_register_indirection_suffix (gdbarch, "]");
+  set_gdbarch_stap_integer_prefixes (gdbarch, stap_integer_prefixes);
+  set_gdbarch_stap_register_prefixes (gdbarch, stap_register_prefixes);
+  set_gdbarch_stap_register_indirection_prefixes (gdbarch,
+					  stap_register_indirection_prefixes);
+  set_gdbarch_stap_register_indirection_suffixes (gdbarch,
+					  stap_register_indirection_suffixes);
   set_gdbarch_stap_gdb_register_prefix (gdbarch, "r");
   set_gdbarch_stap_is_single_operand (gdbarch, arm_stap_is_single_operand);
   set_gdbarch_stap_parse_special_token (gdbarch,
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index fb3595f..f07b8c6 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -86,6 +86,33 @@ pstring (const char *string)
   return string;
 }
 
+/* Helper function to print a list of strings, represented as "const
+   char *const *".  The list is printed comma-separated.  */
+
+static char *
+pstring_list (const char *const *list)
+{
+  static char ret[100];
+  const char *const *p;
+  size_t offset = 0;
+
+  if (list == NULL)
+    return "(null)";
+
+  ret[0] = '\0';
+  for (p = list; *p != NULL && offset < sizeof (ret); ++p)
+    {
+      size_t s = xsnprintf (ret + offset, sizeof (ret) - offset, "%s, ", *p);
+      offset += 2 + s;
+    }
+
+  gdb_assert (offset - 2 < sizeof (ret));
+  if (offset > 0)
+    ret[offset - 2] = '\0';
+
+  return ret;
+}
+
 
 /* Maintain the struct gdbarch object.  */
 
@@ -265,12 +292,12 @@ struct gdbarch
   gdbarch_get_siginfo_type_ftype *get_siginfo_type;
   gdbarch_record_special_symbol_ftype *record_special_symbol;
   gdbarch_get_syscall_number_ftype *get_syscall_number;
-  const char * stap_integer_prefix;
-  const char * stap_integer_suffix;
-  const char * stap_register_prefix;
-  const char * stap_register_suffix;
-  const char * stap_register_indirection_prefix;
-  const char * stap_register_indirection_suffix;
+  const char *const * stap_integer_prefixes;
+  const char *const * stap_integer_suffixes;
+  const char *const * stap_register_prefixes;
+  const char *const * stap_register_suffixes;
+  const char *const * stap_register_indirection_prefixes;
+  const char *const * stap_register_indirection_suffixes;
   const char * stap_gdb_register_prefix;
   const char * stap_gdb_register_suffix;
   gdbarch_stap_is_single_operand_ftype *stap_is_single_operand;
@@ -438,12 +465,12 @@ struct gdbarch startup_gdbarch =
   0,  /* get_siginfo_type */
   0,  /* record_special_symbol */
   0,  /* get_syscall_number */
-  0,  /* stap_integer_prefix */
-  0,  /* stap_integer_suffix */
-  0,  /* stap_register_prefix */
-  0,  /* stap_register_suffix */
-  0,  /* stap_register_indirection_prefix */
-  0,  /* stap_register_indirection_suffix */
+  0,  /* stap_integer_prefixes */
+  0,  /* stap_integer_suffixes */
+  0,  /* stap_register_prefixes */
+  0,  /* stap_register_suffixes */
+  0,  /* stap_register_indirection_prefixes */
+  0,  /* stap_register_indirection_suffixes */
   0,  /* stap_gdb_register_prefix */
   0,  /* stap_gdb_register_suffix */
   0,  /* stap_is_single_operand */
@@ -744,12 +771,12 @@ verify_gdbarch (struct gdbarch *gdbarch)
   /* Skip verify of get_siginfo_type, has predicate.  */
   /* Skip verify of record_special_symbol, has predicate.  */
   /* Skip verify of get_syscall_number, has predicate.  */
-  /* Skip verify of stap_integer_prefix, invalid_p == 0 */
-  /* Skip verify of stap_integer_suffix, invalid_p == 0 */
-  /* Skip verify of stap_register_prefix, invalid_p == 0 */
-  /* Skip verify of stap_register_suffix, invalid_p == 0 */
-  /* Skip verify of stap_register_indirection_prefix, invalid_p == 0 */
-  /* Skip verify of stap_register_indirection_suffix, invalid_p == 0 */
+  /* Skip verify of stap_integer_prefixes, invalid_p == 0 */
+  /* Skip verify of stap_integer_suffixes, invalid_p == 0 */
+  /* Skip verify of stap_register_prefixes, invalid_p == 0 */
+  /* Skip verify of stap_register_suffixes, invalid_p == 0 */
+  /* Skip verify of stap_register_indirection_prefixes, invalid_p == 0 */
+  /* Skip verify of stap_register_indirection_suffixes, invalid_p == 0 */
   /* Skip verify of stap_gdb_register_prefix, invalid_p == 0 */
   /* Skip verify of stap_gdb_register_suffix, invalid_p == 0 */
   /* Skip verify of stap_is_single_operand, has predicate.  */
@@ -1351,11 +1378,11 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
                       "gdbarch_dump: stap_gdb_register_suffix = %s\n",
                       pstring (gdbarch->stap_gdb_register_suffix));
   fprintf_unfiltered (file,
-                      "gdbarch_dump: stap_integer_prefix = %s\n",
-                      pstring (gdbarch->stap_integer_prefix));
+                      "gdbarch_dump: stap_integer_prefixes = %s\n",
+                      pstring_list (gdbarch->stap_integer_prefixes));
   fprintf_unfiltered (file,
-                      "gdbarch_dump: stap_integer_suffix = %s\n",
-                      pstring (gdbarch->stap_integer_suffix));
+                      "gdbarch_dump: stap_integer_suffixes = %s\n",
+                      pstring_list (gdbarch->stap_integer_suffixes));
   fprintf_unfiltered (file,
                       "gdbarch_dump: gdbarch_stap_is_single_operand_p() = %d\n",
                       gdbarch_stap_is_single_operand_p (gdbarch));
@@ -1369,17 +1396,17 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
                       "gdbarch_dump: stap_parse_special_token = <%s>\n",
                       host_address_to_string (gdbarch->stap_parse_special_token));
   fprintf_unfiltered (file,
-                      "gdbarch_dump: stap_register_indirection_prefix = %s\n",
-                      pstring (gdbarch->stap_register_indirection_prefix));
+                      "gdbarch_dump: stap_register_indirection_prefixes = %s\n",
+                      pstring_list (gdbarch->stap_register_indirection_prefixes));
   fprintf_unfiltered (file,
-                      "gdbarch_dump: stap_register_indirection_suffix = %s\n",
-                      pstring (gdbarch->stap_register_indirection_suffix));
+                      "gdbarch_dump: stap_register_indirection_suffixes = %s\n",
+                      pstring_list (gdbarch->stap_register_indirection_suffixes));
   fprintf_unfiltered (file,
-                      "gdbarch_dump: stap_register_prefix = %s\n",
-                      pstring (gdbarch->stap_register_prefix));
+                      "gdbarch_dump: stap_register_prefixes = %s\n",
+                      pstring_list (gdbarch->stap_register_prefixes));
   fprintf_unfiltered (file,
-                      "gdbarch_dump: stap_register_suffix = %s\n",
-                      pstring (gdbarch->stap_register_suffix));
+                      "gdbarch_dump: stap_register_suffixes = %s\n",
+                      pstring_list (gdbarch->stap_register_suffixes));
   fprintf_unfiltered (file,
                       "gdbarch_dump: gdbarch_static_transform_name_p() = %d\n",
                       gdbarch_static_transform_name_p (gdbarch));
@@ -4004,106 +4031,106 @@ set_gdbarch_get_syscall_number (struct gdbarch *gdbarch,
   gdbarch->get_syscall_number = get_syscall_number;
 }
 
-const char *
-gdbarch_stap_integer_prefix (struct gdbarch *gdbarch)
+const char *const *
+gdbarch_stap_integer_prefixes (struct gdbarch *gdbarch)
 {
   gdb_assert (gdbarch != NULL);
-  /* Skip verify of stap_integer_prefix, invalid_p == 0 */
+  /* Skip verify of stap_integer_prefixes, invalid_p == 0 */
   if (gdbarch_debug >= 2)
-    fprintf_unfiltered (gdb_stdlog, "gdbarch_stap_integer_prefix called\n");
-  return gdbarch->stap_integer_prefix;
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_stap_integer_prefixes called\n");
+  return gdbarch->stap_integer_prefixes;
 }
 
 void
-set_gdbarch_stap_integer_prefix (struct gdbarch *gdbarch,
-                                 const char * stap_integer_prefix)
+set_gdbarch_stap_integer_prefixes (struct gdbarch *gdbarch,
+                                   const char *const * stap_integer_prefixes)
 {
-  gdbarch->stap_integer_prefix = stap_integer_prefix;
+  gdbarch->stap_integer_prefixes = stap_integer_prefixes;
 }
 
-const char *
-gdbarch_stap_integer_suffix (struct gdbarch *gdbarch)
+const char *const *
+gdbarch_stap_integer_suffixes (struct gdbarch *gdbarch)
 {
   gdb_assert (gdbarch != NULL);
-  /* Skip verify of stap_integer_suffix, invalid_p == 0 */
+  /* Skip verify of stap_integer_suffixes, invalid_p == 0 */
   if (gdbarch_debug >= 2)
-    fprintf_unfiltered (gdb_stdlog, "gdbarch_stap_integer_suffix called\n");
-  return gdbarch->stap_integer_suffix;
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_stap_integer_suffixes called\n");
+  return gdbarch->stap_integer_suffixes;
 }
 
 void
-set_gdbarch_stap_integer_suffix (struct gdbarch *gdbarch,
-                                 const char * stap_integer_suffix)
+set_gdbarch_stap_integer_suffixes (struct gdbarch *gdbarch,
+                                   const char *const * stap_integer_suffixes)
 {
-  gdbarch->stap_integer_suffix = stap_integer_suffix;
+  gdbarch->stap_integer_suffixes = stap_integer_suffixes;
 }
 
-const char *
-gdbarch_stap_register_prefix (struct gdbarch *gdbarch)
+const char *const *
+gdbarch_stap_register_prefixes (struct gdbarch *gdbarch)
 {
   gdb_assert (gdbarch != NULL);
-  /* Skip verify of stap_register_prefix, invalid_p == 0 */
+  /* Skip verify of stap_register_prefixes, invalid_p == 0 */
   if (gdbarch_debug >= 2)
-    fprintf_unfiltered (gdb_stdlog, "gdbarch_stap_register_prefix called\n");
-  return gdbarch->stap_register_prefix;
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_stap_register_prefixes called\n");
+  return gdbarch->stap_register_prefixes;
 }
 
 void
-set_gdbarch_stap_register_prefix (struct gdbarch *gdbarch,
-                                  const char * stap_register_prefix)
+set_gdbarch_stap_register_prefixes (struct gdbarch *gdbarch,
+                                    const char *const * stap_register_prefixes)
 {
-  gdbarch->stap_register_prefix = stap_register_prefix;
+  gdbarch->stap_register_prefixes = stap_register_prefixes;
 }
 
-const char *
-gdbarch_stap_register_suffix (struct gdbarch *gdbarch)
+const char *const *
+gdbarch_stap_register_suffixes (struct gdbarch *gdbarch)
 {
   gdb_assert (gdbarch != NULL);
-  /* Skip verify of stap_register_suffix, invalid_p == 0 */
+  /* Skip verify of stap_register_suffixes, invalid_p == 0 */
   if (gdbarch_debug >= 2)
-    fprintf_unfiltered (gdb_stdlog, "gdbarch_stap_register_suffix called\n");
-  return gdbarch->stap_register_suffix;
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_stap_register_suffixes called\n");
+  return gdbarch->stap_register_suffixes;
 }
 
 void
-set_gdbarch_stap_register_suffix (struct gdbarch *gdbarch,
-                                  const char * stap_register_suffix)
+set_gdbarch_stap_register_suffixes (struct gdbarch *gdbarch,
+                                    const char *const * stap_register_suffixes)
 {
-  gdbarch->stap_register_suffix = stap_register_suffix;
+  gdbarch->stap_register_suffixes = stap_register_suffixes;
 }
 
-const char *
-gdbarch_stap_register_indirection_prefix (struct gdbarch *gdbarch)
+const char *const *
+gdbarch_stap_register_indirection_prefixes (struct gdbarch *gdbarch)
 {
   gdb_assert (gdbarch != NULL);
-  /* Skip verify of stap_register_indirection_prefix, invalid_p == 0 */
+  /* Skip verify of stap_register_indirection_prefixes, invalid_p == 0 */
   if (gdbarch_debug >= 2)
-    fprintf_unfiltered (gdb_stdlog, "gdbarch_stap_register_indirection_prefix called\n");
-  return gdbarch->stap_register_indirection_prefix;
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_stap_register_indirection_prefixes called\n");
+  return gdbarch->stap_register_indirection_prefixes;
 }
 
 void
-set_gdbarch_stap_register_indirection_prefix (struct gdbarch *gdbarch,
-                                              const char * stap_register_indirection_prefix)
+set_gdbarch_stap_register_indirection_prefixes (struct gdbarch *gdbarch,
+                                                const char *const * stap_register_indirection_prefixes)
 {
-  gdbarch->stap_register_indirection_prefix = stap_register_indirection_prefix;
+  gdbarch->stap_register_indirection_prefixes = stap_register_indirection_prefixes;
 }
 
-const char *
-gdbarch_stap_register_indirection_suffix (struct gdbarch *gdbarch)
+const char *const *
+gdbarch_stap_register_indirection_suffixes (struct gdbarch *gdbarch)
 {
   gdb_assert (gdbarch != NULL);
-  /* Skip verify of stap_register_indirection_suffix, invalid_p == 0 */
+  /* Skip verify of stap_register_indirection_suffixes, invalid_p == 0 */
   if (gdbarch_debug >= 2)
-    fprintf_unfiltered (gdb_stdlog, "gdbarch_stap_register_indirection_suffix called\n");
-  return gdbarch->stap_register_indirection_suffix;
+    fprintf_unfiltered (gdb_stdlog, "gdbarch_stap_register_indirection_suffixes called\n");
+  return gdbarch->stap_register_indirection_suffixes;
 }
 
 void
-set_gdbarch_stap_register_indirection_suffix (struct gdbarch *gdbarch,
-                                              const char * stap_register_indirection_suffix)
+set_gdbarch_stap_register_indirection_suffixes (struct gdbarch *gdbarch,
+                                                const char *const * stap_register_indirection_suffixes)
 {
-  gdbarch->stap_register_indirection_suffix = stap_register_indirection_suffix;
+  gdbarch->stap_register_indirection_suffixes = stap_register_indirection_suffixes;
 }
 
 const char *
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index b58efc8..f37f44f 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -1034,37 +1034,42 @@ extern LONGEST gdbarch_get_syscall_number (struct gdbarch *gdbarch, ptid_t ptid)
 extern void set_gdbarch_get_syscall_number (struct gdbarch *gdbarch, gdbarch_get_syscall_number_ftype *get_syscall_number);
 
 /* SystemTap related fields and functions.
-   Prefix used to mark an integer constant on the architecture's assembly
+   A NULL-terminated array of prefixes used to mark an integer constant
+   on the architecture's assembly.
    For example, on x86 integer constants are written as:
   
     $10 ;; integer constant 10
   
    in this case, this prefix would be the character `$'. */
 
-extern const char * gdbarch_stap_integer_prefix (struct gdbarch *gdbarch);
-extern void set_gdbarch_stap_integer_prefix (struct gdbarch *gdbarch, const char * stap_integer_prefix);
+extern const char *const * gdbarch_stap_integer_prefixes (struct gdbarch *gdbarch);
+extern void set_gdbarch_stap_integer_prefixes (struct gdbarch *gdbarch, const char *const * stap_integer_prefixes);
 
-/* Suffix used to mark an integer constant on the architecture's assembly. */
+/* A NULL-terminated array of suffixes used to mark an integer constant
+   on the architecture's assembly. */
 
-extern const char * gdbarch_stap_integer_suffix (struct gdbarch *gdbarch);
-extern void set_gdbarch_stap_integer_suffix (struct gdbarch *gdbarch, const char * stap_integer_suffix);
+extern const char *const * gdbarch_stap_integer_suffixes (struct gdbarch *gdbarch);
+extern void set_gdbarch_stap_integer_suffixes (struct gdbarch *gdbarch, const char *const * stap_integer_suffixes);
 
-/* Prefix used to mark a register name on the architecture's assembly.
+/* A NULL-terminated array of prefixes used to mark a register name on
+   the architecture's assembly.
    For example, on x86 the register name is written as:
   
     %eax ;; register eax
   
    in this case, this prefix would be the character `%'. */
 
-extern const char * gdbarch_stap_register_prefix (struct gdbarch *gdbarch);
-extern void set_gdbarch_stap_register_prefix (struct gdbarch *gdbarch, const char * stap_register_prefix);
+extern const char *const * gdbarch_stap_register_prefixes (struct gdbarch *gdbarch);
+extern void set_gdbarch_stap_register_prefixes (struct gdbarch *gdbarch, const char *const * stap_register_prefixes);
 
-/* Suffix used to mark a register name on the architecture's assembly */
+/* A NULL-terminated array of suffixes used to mark a register name on
+   the architecture's assembly. */
 
-extern const char * gdbarch_stap_register_suffix (struct gdbarch *gdbarch);
-extern void set_gdbarch_stap_register_suffix (struct gdbarch *gdbarch, const char * stap_register_suffix);
+extern const char *const * gdbarch_stap_register_suffixes (struct gdbarch *gdbarch);
+extern void set_gdbarch_stap_register_suffixes (struct gdbarch *gdbarch, const char *const * stap_register_suffixes);
 
-/* Prefix used to mark a register indirection on the architecture's assembly.
+/* A NULL-terminated array of prefixes used to mark a register
+   indirection on the architecture's assembly.
    For example, on x86 the register indirection is written as:
   
     (%eax) ;; indirecting eax
@@ -1074,10 +1079,11 @@ extern void set_gdbarch_stap_register_suffix (struct gdbarch *gdbarch, const cha
    Please note that we use the indirection prefix also for register
    displacement, e.g., `4(%eax)' on x86. */
 
-extern const char * gdbarch_stap_register_indirection_prefix (struct gdbarch *gdbarch);
-extern void set_gdbarch_stap_register_indirection_prefix (struct gdbarch *gdbarch, const char * stap_register_indirection_prefix);
+extern const char *const * gdbarch_stap_register_indirection_prefixes (struct gdbarch *gdbarch);
+extern void set_gdbarch_stap_register_indirection_prefixes (struct gdbarch *gdbarch, const char *const * stap_register_indirection_prefixes);
 
-/* Suffix used to mark a register indirection on the architecture's assembly.
+/* A NULL-terminated array of suffixes used to mark a register
+   indirection on the architecture's assembly.
    For example, on x86 the register indirection is written as:
   
     (%eax) ;; indirecting eax
@@ -1087,10 +1093,10 @@ extern void set_gdbarch_stap_register_indirection_prefix (struct gdbarch *gdbarc
    Please note that we use the indirection suffix also for register
    displacement, e.g., `4(%eax)' on x86. */
 
-extern const char * gdbarch_stap_register_indirection_suffix (struct gdbarch *gdbarch);
-extern void set_gdbarch_stap_register_indirection_suffix (struct gdbarch *gdbarch, const char * stap_register_indirection_suffix);
+extern const char *const * gdbarch_stap_register_indirection_suffixes (struct gdbarch *gdbarch);
+extern void set_gdbarch_stap_register_indirection_suffixes (struct gdbarch *gdbarch, const char *const * stap_register_indirection_suffixes);
 
-/* Prefix used to name a register using GDB's nomenclature.
+/* Prefix(es) used to name a register using GDB's nomenclature.
   
    For example, on PPC a register is represented by a number in the assembly
    language (e.g., `10' is the 10th general-purpose register).  However,
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index a678a78..ca56d1a 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -826,29 +826,34 @@ M:LONGEST:get_syscall_number:ptid_t ptid:ptid
 
 # SystemTap related fields and functions.
 
-# Prefix used to mark an integer constant on the architecture's assembly
+# A NULL-terminated array of prefixes used to mark an integer constant
+# on the architecture's assembly.
 # For example, on x86 integer constants are written as:
 #
 #  \$10 ;; integer constant 10
 #
 # in this case, this prefix would be the character \`\$\'.
-v:const char *:stap_integer_prefix:::0:0::0:pstring (gdbarch->stap_integer_prefix)
+v:const char *const *:stap_integer_prefixes:::0:0::0:pstring_list (gdbarch->stap_integer_prefixes)
 
-# Suffix used to mark an integer constant on the architecture's assembly.
-v:const char *:stap_integer_suffix:::0:0::0:pstring (gdbarch->stap_integer_suffix)
+# A NULL-terminated array of suffixes used to mark an integer constant
+# on the architecture's assembly.
+v:const char *const *:stap_integer_suffixes:::0:0::0:pstring_list (gdbarch->stap_integer_suffixes)
 
-# Prefix used to mark a register name on the architecture's assembly.
+# A NULL-terminated array of prefixes used to mark a register name on
+# the architecture's assembly.
 # For example, on x86 the register name is written as:
 #
 #  \%eax ;; register eax
 #
 # in this case, this prefix would be the character \`\%\'.
-v:const char *:stap_register_prefix:::0:0::0:pstring (gdbarch->stap_register_prefix)
+v:const char *const *:stap_register_prefixes:::0:0::0:pstring_list (gdbarch->stap_register_prefixes)
 
-# Suffix used to mark a register name on the architecture's assembly
-v:const char *:stap_register_suffix:::0:0::0:pstring (gdbarch->stap_register_suffix)
+# A NULL-terminated array of suffixes used to mark a register name on
+# the architecture's assembly.
+v:const char *const *:stap_register_suffixes:::0:0::0:pstring_list (gdbarch->stap_register_suffixes)
 
-# Prefix used to mark a register indirection on the architecture's assembly.
+# A NULL-terminated array of prefixes used to mark a register
+# indirection on the architecture's assembly.
 # For example, on x86 the register indirection is written as:
 #
 #  \(\%eax\) ;; indirecting eax
@@ -857,9 +862,10 @@ v:const char *:stap_register_suffix:::0:0::0:pstring (gdbarch->stap_register_suf
 #
 # Please note that we use the indirection prefix also for register
 # displacement, e.g., \`4\(\%eax\)\' on x86.
-v:const char *:stap_register_indirection_prefix:::0:0::0:pstring (gdbarch->stap_register_indirection_prefix)
+v:const char *const *:stap_register_indirection_prefixes:::0:0::0:pstring_list (gdbarch->stap_register_indirection_prefixes)
 
-# Suffix used to mark a register indirection on the architecture's assembly.
+# A NULL-terminated array of suffixes used to mark a register
+# indirection on the architecture's assembly.
 # For example, on x86 the register indirection is written as:
 #
 #  \(\%eax\) ;; indirecting eax
@@ -868,9 +874,9 @@ v:const char *:stap_register_indirection_prefix:::0:0::0:pstring (gdbarch->stap_
 #
 # Please note that we use the indirection suffix also for register
 # displacement, e.g., \`4\(\%eax\)\' on x86.
-v:const char *:stap_register_indirection_suffix:::0:0::0:pstring (gdbarch->stap_register_indirection_suffix)
+v:const char *const *:stap_register_indirection_suffixes:::0:0::0:pstring_list (gdbarch->stap_register_indirection_suffixes)
 
-# Prefix used to name a register using GDB's nomenclature.
+# Prefix(es) used to name a register using GDB's nomenclature.
 #
 # For example, on PPC a register is represented by a number in the assembly
 # language (e.g., \`10\' is the 10th general-purpose register).  However,
@@ -1481,6 +1487,33 @@ pstring (const char *string)
   return string;
 }
 
+/* Helper function to print a list of strings, represented as "const
+   char *const *".  The list is printed comma-separated.  */
+
+static char *
+pstring_list (const char *const *list)
+{
+  static char ret[100];
+  const char *const *p;
+  size_t offset = 0;
+
+  if (list == NULL)
+    return "(null)";
+
+  ret[0] = '\0';
+  for (p = list; *p != NULL && offset < sizeof (ret); ++p)
+    {
+      size_t s = xsnprintf (ret + offset, sizeof (ret) - offset, "%s, ", *p);
+      offset += 2 + s;
+    }
+
+  gdb_assert (offset - 2 < sizeof (ret));
+  if (offset > 0)
+    ret[offset - 2] = '\0';
+
+  return ret;
+}
+
 EOF
 
 # gdbarch open the gdbarch object
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index a1a4453..d0e1d8b 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -3919,14 +3919,23 @@ i386_stap_parse_special_token (struct gdbarch *gdbarch,
 void
 i386_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
+  static const char *const stap_integer_prefixes[] = { "$", NULL };
+  static const char *const stap_register_prefixes[] = { "%", NULL };
+  static const char *const stap_register_indirection_prefixes[] = { "(",
+								    NULL };
+  static const char *const stap_register_indirection_suffixes[] = { ")",
+								    NULL };
+
   /* We typically use stabs-in-ELF with the SVR4 register numbering.  */
   set_gdbarch_stab_reg_to_regnum (gdbarch, i386_svr4_reg_to_regnum);
 
   /* Registering SystemTap handlers.  */
-  set_gdbarch_stap_integer_prefix (gdbarch, "$");
-  set_gdbarch_stap_register_prefix (gdbarch, "%");
-  set_gdbarch_stap_register_indirection_prefix (gdbarch, "(");
-  set_gdbarch_stap_register_indirection_suffix (gdbarch, ")");
+  set_gdbarch_stap_integer_prefixes (gdbarch, stap_integer_prefixes);
+  set_gdbarch_stap_register_prefixes (gdbarch, stap_register_prefixes);
+  set_gdbarch_stap_register_indirection_prefixes (gdbarch,
+					  stap_register_indirection_prefixes);
+  set_gdbarch_stap_register_indirection_suffixes (gdbarch,
+					  stap_register_indirection_suffixes);
   set_gdbarch_stap_is_single_operand (gdbarch,
 				      i386_stap_is_single_operand);
   set_gdbarch_stap_parse_special_token (gdbarch,
diff --git a/gdb/ia64-linux-tdep.c b/gdb/ia64-linux-tdep.c
index d1eb529..9756a67 100644
--- a/gdb/ia64-linux-tdep.c
+++ b/gdb/ia64-linux-tdep.c
@@ -135,6 +135,11 @@ static void
 ia64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  static const char *const stap_register_prefixes[] = { "r", NULL };
+  static const char *const stap_register_indirection_prefixes[] = { "[",
+								    NULL };
+  static const char *const stap_register_indirection_suffixes[] = { "]",
+								    NULL };
 
   linux_init_abi (info, gdbarch);
 
@@ -157,9 +162,11 @@ ia64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
                                              svr4_fetch_objfile_link_map);
 
   /* SystemTap related.  */
-  set_gdbarch_stap_register_prefix (gdbarch, "r");
-  set_gdbarch_stap_register_indirection_prefix (gdbarch, "[");
-  set_gdbarch_stap_register_indirection_suffix (gdbarch, "]");
+  set_gdbarch_stap_register_prefixes (gdbarch, stap_register_prefixes);
+  set_gdbarch_stap_register_indirection_prefixes (gdbarch,
+					  stap_register_indirection_prefixes);
+  set_gdbarch_stap_register_indirection_suffixes (gdbarch,
+					    stap_register_indirection_suffixes);
   set_gdbarch_stap_gdb_register_prefix (gdbarch, "r");
   set_gdbarch_stap_is_single_operand (gdbarch,
 				      ia64_linux_stap_is_single_operand);
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
index fc09560..62a1386 100644
--- a/gdb/ppc-linux-tdep.c
+++ b/gdb/ppc-linux-tdep.c
@@ -1245,6 +1245,11 @@ ppc_linux_init_abi (struct gdbarch_info info,
 {
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   struct tdesc_arch_data *tdesc_data = (void *) info.tdep_info;
+  static const char *const stap_integer_prefixes[] = { "i", NULL };
+  static const char *const stap_register_indirection_prefixes[] = { "(",
+								    NULL };
+  static const char *const stap_register_indirection_suffixes[] = { ")",
+								    NULL };
 
   linux_init_abi (info, gdbarch);
 
@@ -1263,9 +1268,11 @@ ppc_linux_init_abi (struct gdbarch_info info,
   set_gdbarch_get_syscall_number (gdbarch, ppc_linux_get_syscall_number);
 
   /* SystemTap functions.  */
-  set_gdbarch_stap_integer_prefix (gdbarch, "i");
-  set_gdbarch_stap_register_indirection_prefix (gdbarch, "(");
-  set_gdbarch_stap_register_indirection_suffix (gdbarch, ")");
+  set_gdbarch_stap_integer_prefixes (gdbarch, stap_integer_prefixes);
+  set_gdbarch_stap_register_indirection_prefixes (gdbarch,
+					  stap_register_indirection_prefixes);
+  set_gdbarch_stap_register_indirection_suffixes (gdbarch,
+					  stap_register_indirection_suffixes);
   set_gdbarch_stap_gdb_register_prefix (gdbarch, "r");
   set_gdbarch_stap_is_single_operand (gdbarch, ppc_stap_is_single_operand);
   set_gdbarch_stap_parse_special_token (gdbarch,
diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c
index cd41de5..07237ad 100644
--- a/gdb/s390-linux-tdep.c
+++ b/gdb/s390-linux-tdep.c
@@ -3026,6 +3026,11 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   int have_linux_v1 = 0;
   int have_linux_v2 = 0;
   int first_pseudo_reg, last_pseudo_reg;
+  static const char *const stap_register_prefixes[] = { "%", NULL };
+  static const char *const stap_register_indirection_prefixes[] = { "(",
+								    NULL };
+  static const char *const stap_register_indirection_suffixes[] = { ")",
+								    NULL };
 
   /* Default ABI and register size.  */
   switch (info.bfd_arch_info->mach)
@@ -3358,9 +3363,11 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_get_siginfo_type (gdbarch, linux_get_siginfo_type);
 
   /* SystemTap functions.  */
-  set_gdbarch_stap_register_prefix (gdbarch, "%");
-  set_gdbarch_stap_register_indirection_prefix (gdbarch, "(");
-  set_gdbarch_stap_register_indirection_suffix (gdbarch, ")");
+  set_gdbarch_stap_register_prefixes (gdbarch, stap_register_prefixes);
+  set_gdbarch_stap_register_indirection_prefixes (gdbarch,
+					  stap_register_indirection_prefixes);
+  set_gdbarch_stap_register_indirection_suffixes (gdbarch,
+					  stap_register_indirection_suffixes);
   set_gdbarch_stap_is_single_operand (gdbarch, s390_stap_is_single_operand);
 
   return gdbarch;
diff --git a/gdb/stap-probe.c b/gdb/stap-probe.c
index 33d4569..1d94255 100644
--- a/gdb/stap-probe.c
+++ b/gdb/stap-probe.c
@@ -346,6 +346,191 @@ stap_get_expected_argument_type (struct gdbarch *gdbarch,
     }
 }
 
+/* Helper function to check for a generic list of prefixes.  GDBARCH
+   is the current gdbarch being used.  S is the expression being
+   analyzed.  If R is not NULL, it will be used to return the found
+   prefix.  PREFIXES is the list of expected prefixes.
+
+   This function does a case-insensitive match.
+
+   Return 1 if any prefix has been found, zero otherwise.  */
+
+static int
+stap_is_generic_prefix (struct gdbarch *gdbarch, const char *s,
+			const char **r, const char *const *prefixes)
+{
+  const char *const *p;
+
+  if (prefixes == NULL)
+    {
+      if (r != NULL)
+	*r = "";
+
+      return 1;
+    }
+
+  for (p = prefixes; *p != NULL; ++p)
+    {
+      if (strncasecmp (s, *p, strlen (*p)) == 0)
+	{
+	  if (r != NULL)
+	    *r = *p;
+
+	  return 1;
+	}
+    }
+
+  return 0;
+}
+
+/* Return 1 if S points to a register prefix, zero otherwise.  For a
+   description of the arguments, look at stap_is_generic_prefix.  */
+
+static int
+stap_is_register_prefix (struct gdbarch *gdbarch, const char *s,
+			 const char **r)
+{
+  const char *const *t = gdbarch_stap_register_prefixes (gdbarch);
+
+  return stap_is_generic_prefix (gdbarch, s, r, t);
+}
+
+/* Return 1 if S points to a register indirection prefix, zero
+   otherwise.  For a description of the arguments, look at
+   stap_is_generic_prefix.  */
+
+static int
+stap_is_register_indirection_prefix (struct gdbarch *gdbarch, const char *s,
+				     const char **r)
+{
+  const char *const *t = gdbarch_stap_register_indirection_prefixes (gdbarch);
+
+  return stap_is_generic_prefix (gdbarch, s, r, t);
+}
+
+/* Return 1 if S points to an integer prefix, zero otherwise.  For a
+   description of the arguments, look at stap_is_generic_prefix.
+
+   This function takes care of analyzing whether we are dealing with
+   an expected integer prefix, or, if there is no integer prefix to be
+   expected, whether we are dealing with a digit.  It does a
+   case-insensitive match.  */
+
+static int
+stap_is_integer_prefix (struct gdbarch *gdbarch, const char *s,
+			const char **r)
+{
+  const char *const *t = gdbarch_stap_integer_prefixes (gdbarch);
+  const char *const *p;
+
+  if (t == NULL)
+    {
+      /* A NULL value here means that integers do not have a prefix.
+	 We just check for a digit then.  */
+      if (r != NULL)
+	*r = "";
+
+      return isdigit (*s);
+    }
+
+  for (p = t; *p != NULL; ++p)
+    {
+      size_t len = strlen (*p);
+
+      if ((len == 0 && isdigit (*s))
+	  || (len > 0 && strncasecmp (s, *p, len) == 0))
+	{
+	  /* Integers may or may not have a prefix.  The "len == 0"
+	     check covers the case when integers do not have a prefix
+	     (therefore, we just check if we have a digit).  The call
+	     to "strncasecmp" covers the case when they have a
+	     prefix.  */
+	  if (r != NULL)
+	    *r = *p;
+
+	  return 1;
+	}
+    }
+
+  return 0;
+}
+
+/* Helper function to check for a generic list of suffixes.  If we are
+   not expecting any suffixes, then it just returns 1.  If we are
+   expecting at least one suffix, then it returns 1 if a suffix has
+   been found, zero otherwise.  GDBARCH is the current gdbarch being
+   used.  S is the expression being analyzed.  If R is not NULL, it
+   will be used to return the found suffix.  SUFFIXES is the list of
+   expected suffixes.  This function does a case-insensitive
+   match.  */
+
+static int
+stap_generic_check_suffix (struct gdbarch *gdbarch, const char *s,
+			   const char **r, const char *const *suffixes)
+{
+  const char *const *p;
+  int found = 0;
+
+  if (suffixes == NULL)
+    {
+      if (r != NULL)
+	*r = "";
+
+      return 1;
+    }
+
+  for (p = suffixes; *p != NULL; ++p)
+    if (strncasecmp (s, *p, strlen (*p)) == 0)
+      {
+	if (r != NULL)
+	  *r = *p;
+
+	found = 1;
+	break;
+      }
+
+  return found;
+}
+
+/* Return 1 if S points to an integer suffix, zero otherwise.  For a
+   description of the arguments, look at
+   stap_generic_check_suffix.  */
+
+static int
+stap_check_integer_suffix (struct gdbarch *gdbarch, const char *s,
+			   const char **r)
+{
+  const char *const *p = gdbarch_stap_integer_suffixes (gdbarch);
+
+  return stap_generic_check_suffix (gdbarch, s, r, p);
+}
+
+/* Return 1 if S points to a register suffix, zero otherwise.  For a
+   description of the arguments, look at
+   stap_generic_check_suffix.  */
+
+static int
+stap_check_register_suffix (struct gdbarch *gdbarch, const char *s,
+			    const char **r)
+{
+  const char *const *p = gdbarch_stap_register_suffixes (gdbarch);
+
+  return stap_generic_check_suffix (gdbarch, s, r, p);
+}
+
+/* Return 1 if S points to a register indirection suffix, zero
+   otherwise.  For a description of the arguments, look at
+   stap_generic_check_suffix.  */
+
+static int
+stap_check_register_indirection_suffix (struct gdbarch *gdbarch, const char *s,
+					const char **r)
+{
+  const char *const *p = gdbarch_stap_register_indirection_suffixes (gdbarch);
+
+  return stap_generic_check_suffix (gdbarch, s, r, p);
+}
+
 /* Function responsible for parsing a register operand according to
    SystemTap parlance.  Assuming:
 
@@ -385,24 +570,14 @@ stap_parse_register_operand (struct stap_parse_info *p)
   const char *start;
   char *regname;
   int len;
-
-  /* Prefixes for the parser.  */
-  const char *reg_prefix = gdbarch_stap_register_prefix (gdbarch);
-  const char *reg_ind_prefix
-    = gdbarch_stap_register_indirection_prefix (gdbarch);
   const char *gdb_reg_prefix = gdbarch_stap_gdb_register_prefix (gdbarch);
-  int reg_prefix_len = reg_prefix ? strlen (reg_prefix) : 0;
-  int reg_ind_prefix_len = reg_ind_prefix ? strlen (reg_ind_prefix) : 0;
   int gdb_reg_prefix_len = gdb_reg_prefix ? strlen (gdb_reg_prefix) : 0;
-
-  /* Suffixes for the parser.  */
-  const char *reg_suffix = gdbarch_stap_register_suffix (gdbarch);
-  const char *reg_ind_suffix
-    = gdbarch_stap_register_indirection_suffix (gdbarch);
   const char *gdb_reg_suffix = gdbarch_stap_gdb_register_suffix (gdbarch);
-  int reg_suffix_len = reg_suffix ? strlen (reg_suffix) : 0;
-  int reg_ind_suffix_len = reg_ind_suffix ? strlen (reg_ind_suffix) : 0;
   int gdb_reg_suffix_len = gdb_reg_suffix ? strlen (gdb_reg_suffix) : 0;
+  const char *reg_prefix;
+  const char *reg_ind_prefix;
+  const char *reg_suffix;
+  const char *reg_ind_suffix;
 
   /* Checking for a displacement argument.  */
   if (*p->arg == '+')
@@ -438,11 +613,10 @@ stap_parse_register_operand (struct stap_parse_info *p)
     }
 
   /* Getting rid of register indirection prefix.  */
-  if (reg_ind_prefix
-      && strncmp (p->arg, reg_ind_prefix, reg_ind_prefix_len) == 0)
+  if (stap_is_register_indirection_prefix (gdbarch, p->arg, &reg_ind_prefix))
     {
       indirect_p = 1;
-      p->arg += reg_ind_prefix_len;
+      p->arg += strlen (reg_ind_prefix);
     }
 
   if (disp_p && !indirect_p)
@@ -450,8 +624,8 @@ stap_parse_register_operand (struct stap_parse_info *p)
 	   p->saved_arg);
 
   /* Getting rid of register prefix.  */
-  if (reg_prefix && strncmp (p->arg, reg_prefix, reg_prefix_len) == 0)
-    p->arg += reg_prefix_len;
+  if (stap_is_register_prefix (gdbarch, p->arg, &reg_prefix))
+    p->arg += strlen (reg_prefix);
 
   /* Now we should have only the register name.  Let's extract it and get
      the associated number.  */
@@ -509,23 +683,21 @@ stap_parse_register_operand (struct stap_parse_info *p)
     }
 
   /* Getting rid of the register name suffix.  */
-  if (reg_suffix)
-    {
-      if (strncmp (p->arg, reg_suffix, reg_suffix_len) != 0)
-	error (_("Missing register name suffix `%s' on expression `%s'."),
-	       reg_suffix, p->saved_arg);
-
-      p->arg += reg_suffix_len;
-    }
+  if (stap_check_register_suffix (gdbarch, p->arg, &reg_suffix))
+    p->arg += strlen (reg_suffix);
+  else
+    error (_("Missing register name suffix on expression `%s'."),
+	   p->saved_arg);
 
   /* Getting rid of the register indirection suffix.  */
-  if (indirect_p && reg_ind_suffix)
+  if (indirect_p)
     {
-      if (strncmp (p->arg, reg_ind_suffix, reg_ind_suffix_len) != 0)
-	error (_("Missing indirection suffix `%s' on expression `%s'."),
-	       reg_ind_suffix, p->saved_arg);
-
-      p->arg += reg_ind_suffix_len;
+      if (stap_check_register_indirection_suffix (gdbarch, p->arg,
+						  &reg_ind_suffix))
+	p->arg += strlen (reg_ind_suffix);
+      else
+	error (_("Missing indirection suffix on expression `%s'."),
+	       p->saved_arg);
     }
 }
 
@@ -548,19 +720,7 @@ static void
 stap_parse_single_operand (struct stap_parse_info *p)
 {
   struct gdbarch *gdbarch = p->gdbarch;
-
-  /* Prefixes for the parser.  */
-  const char *const_prefix = gdbarch_stap_integer_prefix (gdbarch);
-  const char *reg_prefix = gdbarch_stap_register_prefix (gdbarch);
-  const char *reg_ind_prefix
-    = gdbarch_stap_register_indirection_prefix (gdbarch);
-  int const_prefix_len = const_prefix ? strlen (const_prefix) : 0;
-  int reg_prefix_len = reg_prefix ? strlen (reg_prefix) : 0;
-  int reg_ind_prefix_len = reg_ind_prefix ? strlen (reg_ind_prefix) : 0;
-
-  /* Suffixes for the parser.  */
-  const char *const_suffix = gdbarch_stap_integer_suffix (gdbarch);
-  int const_suffix_len = const_suffix ? strlen (const_suffix) : 0;
+  const char *int_prefix = NULL;
 
   /* We first try to parse this token as a "special token".  */
   if (gdbarch_stap_parse_special_token_p (gdbarch))
@@ -607,8 +767,7 @@ stap_parse_single_operand (struct stap_parse_info *p)
 	  tmp = endp;
 	}
 
-      if (!reg_ind_prefix
-	  || strncmp (tmp, reg_ind_prefix, reg_ind_prefix_len) != 0)
+      if (!stap_is_register_indirection_prefix (gdbarch, tmp, NULL))
 	{
 	  /* This is not a displacement.  We skip the operator, and deal
 	     with it later.  */
@@ -637,16 +796,23 @@ stap_parse_single_operand (struct stap_parse_info *p)
       char *endp;
       long number;
 
-      /* We can be dealing with a numeric constant (if `const_prefix' is
-	 NULL), or with a register displacement.  */
+      /* We can be dealing with a numeric constant, or with a register
+	 displacement.  */
       number = strtol (tmp, &endp, 10);
       tmp = endp;
 
       if (p->inside_paren_p)
 	tmp = skip_spaces_const (tmp);
-      if (!const_prefix && reg_ind_prefix
-	  && strncmp (tmp, reg_ind_prefix, reg_ind_prefix_len) != 0)
+
+      /* If "stap_is_integer_prefix" returns true, it means we can
+	 accept integers without a prefix here.  But we also need to
+	 check whether the next token (i.e., "tmp") is not a register
+	 indirection prefix.  */
+      if (stap_is_integer_prefix (gdbarch, p->arg, NULL)
+	  && !stap_is_register_indirection_prefix (gdbarch, tmp, NULL))
 	{
+	  const char *int_suffix;
+
 	  /* We are dealing with a numeric constant.  */
 	  write_exp_elt_opcode (OP_LONG);
 	  write_exp_elt_type (builtin_type (gdbarch)->builtin_long);
@@ -655,30 +821,26 @@ stap_parse_single_operand (struct stap_parse_info *p)
 
 	  p->arg = tmp;
 
-	  if (const_suffix)
-	    {
-	      if (strncmp (p->arg, const_suffix, const_suffix_len) == 0)
-		p->arg += const_suffix_len;
-	      else
-		error (_("Invalid constant suffix on expression `%s'."),
-		       p->saved_arg);
-	    }
+	  if (stap_check_integer_suffix (gdbarch, p->arg, &int_suffix))
+	    p->arg += strlen (int_suffix);
+	  else
+	    error (_("Invalid constant suffix on expression `%s'."),
+		   p->saved_arg);
 	}
-      else if (reg_ind_prefix
-	       && strncmp (tmp, reg_ind_prefix, reg_ind_prefix_len) == 0)
+      else if (stap_is_register_indirection_prefix (gdbarch, tmp, NULL))
 	stap_parse_register_operand (p);
       else
 	error (_("Unknown numeric token on expression `%s'."),
 	       p->saved_arg);
     }
-  else if (const_prefix
-	   && strncmp (p->arg, const_prefix, const_prefix_len) == 0)
+  else if (stap_is_integer_prefix (gdbarch, p->arg, &int_prefix))
     {
       /* We are dealing with a numeric constant.  */
       long number;
       char *endp;
+      const char *int_suffix;
 
-      p->arg += const_prefix_len;
+      p->arg += strlen (int_prefix);
       number = strtol (p->arg, &endp, 10);
       p->arg = endp;
 
@@ -687,19 +849,14 @@ stap_parse_single_operand (struct stap_parse_info *p)
       write_exp_elt_longcst (number);
       write_exp_elt_opcode (OP_LONG);
 
-      if (const_suffix)
-	{
-	  if (strncmp (p->arg, const_suffix, const_suffix_len) == 0)
-	    p->arg += const_suffix_len;
-	  else
-	    error (_("Invalid constant suffix on expression `%s'."),
-		   p->saved_arg);
-	}
+      if (stap_check_integer_suffix (gdbarch, p->arg, &int_suffix))
+	p->arg += strlen (int_suffix);
+      else
+	error (_("Invalid constant suffix on expression `%s'."),
+	       p->saved_arg);
     }
-  else if ((reg_prefix
-	    && strncmp (p->arg, reg_prefix, reg_prefix_len) == 0)
-	   || (reg_ind_prefix
-	       && strncmp (p->arg, reg_ind_prefix, reg_ind_prefix_len) == 0))
+  else if (stap_is_register_prefix (gdbarch, p->arg, NULL)
+	   || stap_is_register_indirection_prefix (gdbarch, p->arg, NULL))
     stap_parse_register_operand (p);
   else
     error (_("Operator `%c' not recognized on expression `%s'."),

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Extend SystemTap SDT probe argument parser
  2013-12-17 17:28   ` Sergio Durigan Junior
@ 2013-12-17 19:46     ` Pedro Alves
  2013-12-17 21:06       ` Sergio Durigan Junior
  2013-12-19 20:58     ` Sergio Durigan Junior
  1 sibling, 1 reply; 10+ messages in thread
From: Pedro Alves @ 2013-12-17 19:46 UTC (permalink / raw)
  To: Sergio Durigan Junior; +Cc: GDB Patches

On 12/17/2013 05:27 PM, Sergio Durigan Junior wrote:
> +/* Helper function to print a list of strings, represented as "const
> +   char *const *".  The list is printed comma-separated.  */
> +
> +static char *
> +pstring_list (const char *const *list)
> +{
> +  static char ret[100];
> +  const char *const *p;
> +  size_t offset = 0;
> +
> +  if (list == NULL)
> +    return "(null)";
> +
> +  ret[0] = '\0';
> +  for (p = list; *p != NULL && offset < sizeof (ret); ++p)
> +    {
> +      size_t s = xsnprintf (ret + offset, sizeof (ret) - offset, "%s, ", *p);
> +      offset += 2 + s;
> +    }
> +
> +  gdb_assert (offset - 2 < sizeof (ret));

Note this will assert if the list is empty (but not NULL), i.e., { NULL },
because offset will be 0, and "offset - 2" will wrap around
(offset is unsigned size_t.)  I suggest either moving the assert within
the if below, or handle that case especially, printing "(empty)"
or some such.

> +  if (offset > 0)
> +    ret[offset - 2] = '\0';
> +
> +  return ret;

I have no further comments.

Thanks,
-- 
Pedro Alves

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Extend SystemTap SDT probe argument parser
  2013-12-17 19:46     ` Pedro Alves
@ 2013-12-17 21:06       ` Sergio Durigan Junior
  0 siblings, 0 replies; 10+ messages in thread
From: Sergio Durigan Junior @ 2013-12-17 21:06 UTC (permalink / raw)
  To: Pedro Alves; +Cc: GDB Patches

On Tuesday, December 17 2013, Pedro Alves wrote:

> On 12/17/2013 05:27 PM, Sergio Durigan Junior wrote:
>> +/* Helper function to print a list of strings, represented as "const
>> +   char *const *".  The list is printed comma-separated.  */
>> +
>> +static char *
>> +pstring_list (const char *const *list)
>> +{
>> +  static char ret[100];
>> +  const char *const *p;
>> +  size_t offset = 0;
>> +
>> +  if (list == NULL)
>> +    return "(null)";
>> +
>> +  ret[0] = '\0';
>> +  for (p = list; *p != NULL && offset < sizeof (ret); ++p)
>> +    {
>> +      size_t s = xsnprintf (ret + offset, sizeof (ret) - offset, "%s, ", *p);
>> +      offset += 2 + s;
>> +    }
>> +
>> +  gdb_assert (offset - 2 < sizeof (ret));
>
> Note this will assert if the list is empty (but not NULL), i.e., { NULL },
> because offset will be 0, and "offset - 2" will wrap around
> (offset is unsigned size_t.)  I suggest either moving the assert within
> the if below, or handle that case especially, printing "(empty)"
> or some such.

Thanks, nice catch.  I moved the assert within the "if".

-- 
Sergio

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Extend SystemTap SDT probe argument parser
  2013-12-17 17:28   ` Sergio Durigan Junior
  2013-12-17 19:46     ` Pedro Alves
@ 2013-12-19 20:58     ` Sergio Durigan Junior
  2013-12-19 21:09       ` Mark Kettenis
  1 sibling, 1 reply; 10+ messages in thread
From: Sergio Durigan Junior @ 2013-12-19 20:58 UTC (permalink / raw)
  To: Pedro Alves; +Cc: GDB Patches

On Tuesday, December 17 2013, I wrote:

>> Otherwise looks good to me.
>
> Thanks.  I guess I will wait a little more until Mark K. replies to my
> question, and then I will push the following version.

I decided to push the patch, because I want the AArch64 support to go in
before we branch 7.7.

Checked-in:

<https://sourceware.org/ml/gdb-cvs/2013-12/msg00102.html>

Thanks,

-- 
Sergio

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH] Extend SystemTap SDT probe argument parser
  2013-12-19 20:58     ` Sergio Durigan Junior
@ 2013-12-19 21:09       ` Mark Kettenis
  0 siblings, 0 replies; 10+ messages in thread
From: Mark Kettenis @ 2013-12-19 21:09 UTC (permalink / raw)
  To: sergiodj; +Cc: palves, gdb-patches

> From: Sergio Durigan Junior <sergiodj@redhat.com>
> Date: Thu, 19 Dec 2013 18:58:44 -0200
> 
> On Tuesday, December 17 2013, I wrote:
> 
> >> Otherwise looks good to me.
> >
> > Thanks.  I guess I will wait a little more until Mark K. replies to my
> > question, and then I will push the following version.
> 
> I decided to push the patch, because I want the AArch64 support to go in
> before we branch 7.7.

Sorry.  My reply was intended as an ok.  My solution for fixing the
problem involves time travel and physical violence ;).

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2013-12-19 21:09 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-12-11  3:56 [PATCH] Extend SystemTap SDT probe argument parser Sergio Durigan Junior
2013-12-16 17:01 ` Sergio Durigan Junior
2013-12-16 17:09   ` Mark Kettenis
2013-12-16 17:16     ` Sergio Durigan Junior
2013-12-17 11:03 ` Pedro Alves
2013-12-17 17:28   ` Sergio Durigan Junior
2013-12-17 19:46     ` Pedro Alves
2013-12-17 21:06       ` Sergio Durigan Junior
2013-12-19 20:58     ` Sergio Durigan Junior
2013-12-19 21:09       ` Mark Kettenis

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).