summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog10
-rw-r--r--parse.cxx23
-rw-r--r--stap.1.in14
-rw-r--r--tapset/context.stp51
-rw-r--r--tapset/conversions.stp10
-rw-r--r--tapset/logging.stp28
-rw-r--r--tapset/timestamp.stp4
-rwxr-xr-xtestsuite/parseok/twelve.stp2
-rwxr-xr-xtestsuite/semko/nineteen.stp2
-rwxr-xr-xtestsuite/semko/twenty.stp7
-rwxr-xr-xtestsuite/semok/seven.stp4
11 files changed, 85 insertions, 70 deletions
diff --git a/ChangeLog b/ChangeLog
index 5c24750b..32364afa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2005-09-03 Frank Ch. Eigler <fche@elastic.org>
+
+ PR 1292, by popular request.
+ * parse.cxx (parse_functiondecl): Allow optional value/param type
+ declarations.
+ * stap.1.in: Document this.
+ * tapset/*.stp: Convert most functions accordingly.
+ * testsuite/parseok/twelve.stp, semok/seven.stp,
+ semko/twenty.stp: Test this.
+
2005-09-02 Frank Ch. Eigler <fche@redhat.com>
* translate.cxx (varlock): Use trylock only for write locks.
diff --git a/parse.cxx b/parse.cxx
index c4f028b7..a1a54011 100644
--- a/parse.cxx
+++ b/parse.cxx
@@ -774,6 +774,18 @@ parser::parse_functiondecl (std::vector<functiondecl*>& functions)
fd->tok = t;
t = next ();
+ if (t->type == tok_operator && t->content == ":")
+ {
+ t = next ();
+ if (t->type == tok_identifier && t->content == "string")
+ fd->type = pe_string;
+ else if (t->type == tok_identifier && t->content == "long")
+ fd->type = pe_long;
+ else throw parse_error ("expected 'string' or 'long'");
+
+ t = next ();
+ }
+
if (! (t->type == tok_operator && t->content == "("))
throw parse_error ("expected '('");
@@ -792,6 +804,17 @@ parser::parse_functiondecl (std::vector<functiondecl*>& functions)
fd->formal_args.push_back (vd);
t = next ();
+ if (t->type == tok_operator && t->content == ":")
+ {
+ t = next ();
+ if (t->type == tok_identifier && t->content == "string")
+ vd->type = pe_string;
+ else if (t->type == tok_identifier && t->content == "long")
+ vd->type = pe_long;
+ else throw parse_error ("expected 'string' or 'long'");
+
+ t = next ();
+ }
if (t->type == tok_operator && t->content == ")")
break;
if (t->type == tok_operator && t->content == ",")
diff --git a/stap.1.in b/stap.1.in
index 12fcad52..13f02e13 100644
--- a/stap.1.in
+++ b/stap.1.in
@@ -315,8 +315,18 @@ function thisfn (arg1, arg2) {
return arg1 + arg2
}
.ESAMPLE
-Note the usual absence of type declarations, which are instead
-inferred by the translator. Functions may call others or themselves
+Note the general absence of type declarations, which are instead
+inferred by the translator. However, if desired, a function
+definition may include explicit type declarations for its return value
+and/or its arguments. This is especially helpful for embedded-C
+functions. In the following example, the type inference engine need
+only infer type type of arg2 (a string).
+.SAMPLE
+function thatfn:string (arg1:long, arg2) {
+ return string(arg1) . arg2
+}
+.ESAMPLE
+Functions may call others or themselves
recursively, up to a fixed nesting limit. This limit is defined by
a macro in the translated C code and is in the neighbourhood of 30.
diff --git a/tapset/context.stp b/tapset/context.stp
index 7ed693b8..32b009bf 100644
--- a/tapset/context.stp
+++ b/tapset/context.stp
@@ -1,94 +1,82 @@
-function _print_regs () %{
- if (CONTEXT && CONTEXT->regs) {
+function print_regs () %{
+ if (CONTEXT->regs) {
_stp_print_regs (CONTEXT->regs);
}
%}
-function print_regs(){_print_regs()}
-function _print_backtrace () %{
- if (CONTEXT && CONTEXT->regs) {
+function print_backtrace () %{
+ if (CONTEXT->regs) {
_stp_stack_print(CONTEXT->regs);
}
%}
-function print_backtrace(){_print_backtrace()}
-
-function _backtrace () %{
- if (CONTEXT && CONTEXT->regs) {
+function backtrace () %{
+ if (CONTEXT->regs) {
String str = _stp_string_init (0);
_stp_stack_sprint (str, CONTEXT->regs, 0);
strlcpy (THIS->__retvalue, _stp_string_ptr(str), MAXSTRINGLEN);
} else
strlcpy (THIS->__retvalue, "", MAXSTRINGLEN);
%}
-function backtrace(){return "" . _backtrace()}
-function _execname () %{
- if(unlikely(in_interrupt()))
+function execname:string () %{
+ if (unlikely(in_interrupt()))
strlcpy (THIS->__retvalue, "<unknown>", MAXSTRINGLEN);
else
- strlcpy (THIS->__retvalue, current->comm, MAXSTRINGLEN);
+ strlcpy (THIS->__retvalue, current->comm, MAXSTRINGLEN);
%}
-function execname(){return ""._execname()}
-function _pid() %{
- if(unlikely(in_interrupt()))
+function pid:long () %{
+ if (unlikely(in_interrupt()))
THIS->__retvalue = 0;
else
THIS->__retvalue = current->pid;
%}
-function pid(){return 0+_pid()}
-function _ppid() %{
- if(unlikely(in_interrupt() || !current->parent))
+function ppid:long () %{
+ if (unlikely(in_interrupt() || !current->parent))
THIS->__retvalue = 0;
else
THIS->__retvalue = current->parent->pid;
%}
-function ppid(){return 0+_ppid()}
-function _pexecname() %{
+function pexecname:string () %{
if(unlikely(in_interrupt() || !current->parent || !current->parent->comm))
strlcpy (THIS->__retvalue, "<unknown>", MAXSTRINGLEN);
else
strlcpy (THIS->__retvalue, current->parent->comm, MAXSTRINGLEN);
%}
-function pexecname(){return ""._pexecname()}
-function _gid() %{
+function gid:long () %{
if(unlikely(in_interrupt()))
THIS->__retvalue = 0;
else
THIS->__retvalue = current->gid;
%}
-function gid(){return 0+_gid()}
-function _egid() %{
+function egid:long () %{
if(unlikely(in_interrupt()))
THIS->__retvalue = 0;
else
THIS->__retvalue = current->egid;
%}
-function egid(){return 0+_egid()}
-function _uid() %{
+function uid:long () %{
if(unlikely(in_interrupt()))
THIS->__retvalue = 0;
else
THIS->__retvalue = current->uid;
%}
-function uid(){return 0+_uid()}
-function _euid() %{
+function euid:long () %{
if(unlikely(in_interrupt()))
THIS->__retvalue = 0;
else
THIS->__retvalue = current->euid;
%}
-function euid(){return 0+_euid()}
-function _print_stack(stk) %{
+function print_stack(stk:string) %{
char *ptr = THIS->stk;
char *tok = strsep(&ptr, " ");
_stp_printf ("trace for %d (%s)\n", current->pid, current->comm);
@@ -99,4 +87,3 @@ function _print_stack(stk) %{
tok = strsep(&ptr, " ");
}
%}
-function print_stack (stk) {_print_stack("".stk)}
diff --git a/tapset/conversions.stp b/tapset/conversions.stp
index 5c0230d4..901f26a4 100644
--- a/tapset/conversions.stp
+++ b/tapset/conversions.stp
@@ -1,14 +1,8 @@
-function _hexstring (num) %{
+function hexstring:string (num:long) %{
sprintf (THIS->__retvalue, "0x%llx", (long long) THIS->num);
%}
-function hexstring (num) {
- return "" . _hexstring (num + 0)
-}
-function _string (num) %{
+function string:string (num:long) %{
sprintf (THIS->__retvalue, "%lld", (long long) THIS->num);
%}
-function string (num) {
- return "" . _string (num + 0)
-}
diff --git a/tapset/logging.stp b/tapset/logging.stp
index a2abf922..eff7b555 100644
--- a/tapset/logging.stp
+++ b/tapset/logging.stp
@@ -1,44 +1,28 @@
# This file contains simple bridging functions to the runtime
-function _print (msg) %{
+function print (msg:string) %{
_stp_print (THIS->msg);
%}
-function print (msg) {
- _print (msg . "\n")
-}
-
-// same as print
+// almost the same as print
function log (msg) {
- _print (msg . "\n")
+ print (msg . "\n")
}
-function _printk (msg) %{
+function printk (msg:string) %{
printk (KERN_INFO "%s\n", THIS->msg);
%}
-function printk (msg) {
- _printk (msg . "")
-}
-
-function _warn (msg) %{
+function warn (msg:string) %{
_stp_warn ("%s", THIS->msg);
%}
-function warn (msg) {
- _warn (msg . "")
-}
-
// NB: exit() does *not* cause immediate return from current function/probe
function exit () %{
_stp_exit ();
%}
-function _error (msg) %{
+function error (msg:string) %{
CONTEXT->last_error = "called error()"; /* kill current probe */
_stp_error ("%s", THIS->msg); /* implies _stp_exit */
%}
-
-function error (msg) {
- _error (msg . "")
-}
diff --git a/tapset/timestamp.stp b/tapset/timestamp.stp
index f8e1ea4e..b71841d4 100644
--- a/tapset/timestamp.stp
+++ b/tapset/timestamp.stp
@@ -3,14 +3,14 @@
%}
// return in milliseconds since epoch
-function gettimeofday_ms () %{
+function gettimeofday_ms:long () %{
struct timeval tm;
do_gettimeofday (& tm);
THIS->__retvalue = (tm.tv_sec * 1000) + (tm.tv_usec / 1000);
%}
// return in seconds since epoch
-function gettimeofday_s () %{
+function gettimeofday_s:long () %{
struct timeval tm;
do_gettimeofday (& tm);
THIS->__retvalue = tm.tv_sec;
diff --git a/testsuite/parseok/twelve.stp b/testsuite/parseok/twelve.stp
index d5029d1a..2e20da18 100755
--- a/testsuite/parseok/twelve.stp
+++ b/testsuite/parseok/twelve.stp
@@ -6,7 +6,7 @@
/* hello world */
%}
-function foo (p1, p2) %{
+function foo:long (p1:string, p2:long, p3) %{
/* goodbye world */
%}
diff --git a/testsuite/semko/nineteen.stp b/testsuite/semko/nineteen.stp
index 04a9af20..bd8a4129 100755
--- a/testsuite/semko/nineteen.stp
+++ b/testsuite/semko/nineteen.stp
@@ -1,4 +1,4 @@
-#! stap -p4
+#! stap -p2
# PR 1155: should start working when we can resolve the parameters of
# the inlines.
diff --git a/testsuite/semko/twenty.stp b/testsuite/semko/twenty.stp
new file mode 100755
index 00000000..899efdc1
--- /dev/null
+++ b/testsuite/semko/twenty.stp
@@ -0,0 +1,7 @@
+#! stap -p2
+
+function a:string () { }
+
+probe begin {
+ a() + 1
+}
diff --git a/testsuite/semok/seven.stp b/testsuite/semok/seven.stp
index 73264923..f0b248bd 100755
--- a/testsuite/semok/seven.stp
+++ b/testsuite/semok/seven.stp
@@ -2,8 +2,8 @@
global ar1, ar2
-function string (v) { num=v+0; return "stringify me" } # to become a built-in
-function printk (s) { str=s.""; return 0 } # to become a built-in
+function string:string (v:long) { } # to become a built-in
+function printk (s:string) { return 0 } # to become a built-in
function search (key)
{