--- /dev/null
+#!/bin/awk -f
+
+BEGIN {
+ isfunc = 0
+ block = 0
+ embedded = 0
+}
+
+# print the function prototype, all on one line.
+/^function/ {
+ if (block != 0 || embedded != 0) {
+ printf "Unterminated block at: %s: %d %d\n",$0,block,embedded > "/dev/stderr"
+ exit 1
+ }
+ isfunc = 1
+ unprivileged = -1
+ myproc_unprivileged = -1
+}
+
+/^function/,/\)/ {
+ # Strip characters after the ')'.
+ temp = $0
+ sub("\\).*", ")", temp)
+# print "after stripping trailing chars: " temp
+
+ # Strip the the return type.
+ temp = gensub("^function[[:space:]]*([\\$_[:alpha:]][\\$_[:alnum:]]*)[[:space:]]*:[[:space:]]*[[:alpha:]]*",
+ "function \\1", 1, temp)
+# print "after stripping return type: " temp
+
+ # Strip the 'function'.
+ temp = gensub("^function[[:space:]]*", "", 1, temp)
+# print "after stripping function: " temp
+
+ # Add the default type where it has been omitted.
+ do {
+ temp1 = temp
+ temp = gensub("([(,][[:space:]]*[\\$_[:alpha:]][\\$_[:alnum:]]*)[[:space:]]*([,)])",
+ "\\1:long\\2", "g", temp)
+# print "after adding a default type: " temp
+ } while (temp != temp1)
+
+ # Strip paramater names.
+ temp = gensub("[\\$_[:alpha:]][\\$_[:alnum:]]*[[:space:]]*:[[:space:]]*([[:alpha:]])",
+ "\\1", "g", temp)
+# print "after stripping parm names: "
+
+ printf "%s",temp
+ fflush()
+}
+
+# Beginning of an embedded C block
+(! /^.*\/\/.*%{/) && /%{/ {
+ block += 1
+ embedded += 1
+# printf "%s",$0
+# print ": embedded start:" block " " embedded
+}
+
+# Beginning of a preprocessor block
+(! /^.*\/\/.*%\(/) && /%\(/ {
+ block += 1
+# printf "%s",$0
+# print ": preprocessor start:" block " " embedded
+}
+
+# Beginning of a code block
+/^{/ {
+ block += 1
+# printf "%s",$0
+# print ": block start:" block " " embedded
+}
+(! /^.*\/\/.*{/) && /[^%]{/ {
+ block += 1
+# printf "%s",$0
+# print ": block start:" block " " embedded
+}
+
+# unprivileged?
+/\/\* unprivileged \*\// {
+ if (embedded && unprivileged != 0)
+ unprivileged = 1
+}
+/\/\* myproc-unprivileged \*\// {
+ if (embedded && myproc_unprivileged != 0)
+ myproc_unprivileged = 1
+}
+
+# Process the end of a tapset function.
+function finish_function() {
+ if (block == 0 && isfunc) {
+ if (unprivileged == 1)
+ print " ; unprivileged"
+ else if (myproc_unprivileged == 1)
+ print " ;myproc-unprivileged"
+ else if (unprivileged != -1 || myproc_unprivileged != -1)
+ print " ;privileged"
+ else
+ print " ;no embedded C"
+ fflush()
+ isfunc = 0
+ }
+}
+
+# End of an embedded C block
+(! /^.*\/\/.*%}/) && /%}/ {
+ embedded -= 1
+ block -= 1
+ if (unprivileged == -1)
+ unprivileged = 0
+ if (myproc_unprivileged == -1)
+ myproc_unprivileged = 0
+# printf "%s",$0
+# print ": embedded end:" block " " embedded
+ finish_function()
+}
+
+# End of a preprocessor C block
+(! /^.*\/\/.*%\)/) && /%\)/ {
+ block -= 1
+# printf "%s",$0
+# print ": embedded end:" block " " embedded
+ finish_function()
+}
+
+# End of a code block
+/^}/ {
+ block -= 1
+# printf "%s",$0
+# print ": block end:" block " " embedded
+ finish_function()
+}
+(! /^.*\/\/.*}/) && /[^%]}/ {
+ block -= 1
+# printf "%s",$0
+# print ": block end:" block " " embedded
+ finish_function()
+}
+
+END {
+ if (block != 0 || embedded != 0) {
+ printf "Unterminated block at EOF: %d %d\n",block,embedded > "/dev/stderr"
+ exit 1
+ }
+}
\ No newline at end of file
--- /dev/null
+set test "unprivileged embedded C"
+
+# Add arguments to a probe type template.
+proc add_args { prototype } {
+ set call "$prototype"
+
+ # Replace long with 0
+ regsub -all "(\[(,]\[\[:space:]]*)long" $call "\\10" call
+
+ # Replace string with "0"
+ regsub -all "(\[(,]\[\[:space:]]*)string" $call "\\1\"0\"" call
+
+ return "$call"
+}
+
+# Test valid probe types
+proc test_embedded_C { use_wrapper } {
+ global prototype_info test
+
+ if { $use_wrapper } {
+ set with_wrapper " with wrapper"
+ } else {
+ set with_wrapper ""
+ }
+
+ foreach info $prototype_info {
+ verbose -log "testing $info"
+
+ # Separate the prototype and its status.
+ set tokens [split $info ";"]
+ set prototype [lindex $tokens 0]
+ set status [lindex $tokens 1]
+
+ # Test calling the function. If successful, the stap rc will be 0.
+ set call [add_args $prototype]
+ set cmd [concat [list stap -p2 --unprivileged -e "probe begin { $call }"]]
+ verbose -log "eval exec $cmd"
+ set rc [catch {eval exec $cmd} res_stap]
+ verbose -log $res_stap
+
+ # Look for a message saying that the function is not allowed for unprivileged users.
+ regexp "(\[^\[:space:](]*).*" $prototype match funcname
+ verbose -log "funcname is $funcname"
+
+ # The function '_wait_status_str' is not allowed for unprivileged but it fails with a
+ # reference to the function '_signal_name' which it calls and which is checked first.
+ if {"$funcname" == "_wait_status_str"} {
+ set funcname "_signal_name"
+ }
+ set emsg1 "semantic error: function may not be used when --unprivileged is specified: identifier '$funcname'"
+ set emsg2 "semantic error: embedded expression may not be used when --unprivileged is specified"
+ set found [expr [regexp ".*$emsg1.*" $res_stap] || [regexp ".*$emsg2.*" $res_stap]]
+
+ # Evaluate the result based upon the function's status
+ switch $status {
+ unprivileged -
+ myproc-unprivileged -
+ "no embedded C"
+ {
+ # There should be no message excluding this function
+ set passed [expr ! $found]
+ }
+ privileged
+ {
+ # There should be a message excluding this function
+ set passed $found
+ }
+ }
+
+ if {$passed} {
+ pass "$test: $status: $prototype"
+ } else {
+ fail "$test: $status: $prototype"
+ }
+ }
+}
+
+# Obtain the prototypes of all tapset functions containing embedded C code.
+set tapsetdir "$srcdir/../tapset"
+verbose -log "Looking for tapset scripts in $tapsetdir"
+set files [glob -nocomplain $tapsetdir/*.stp]
+verbose -log "Looking for tapset scripts in $tapsetdir/[exec uname -i]"
+set files [concat $files [glob -nocomplain $tapsetdir/[exec uname -i]/*.stp]]
+
+verbose -log "eval exec $srcdir/$subdir/embeddedc.awk [join $files]"
+catch {eval exec $srcdir/$subdir/embeddedc.awk [join $files]} res_stap
+set prototype_info [split $res_stap "\n"]
+
+verbose -log "prototype_info contains [llength prototype_info] items"
+if {[llength prototype_info] > 0} {
+ pass "$test: Obtain list tapset functions containing embedded C"
+} else {
+ fail "$test: Obtain list tapset functions containing embedded C"
+ untested "$test"
+ return
+}
+
+# Now run the tests
+test_embedded_C 0