summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--main.cxx14
-rw-r--r--parse.cxx19
-rw-r--r--session.h1
-rw-r--r--stap.1.in6
-rwxr-xr-xtestsuite/parseko/preprocess17.stp3
-rwxr-xr-xtestsuite/parseok/twenty.stp3
6 files changed, 40 insertions, 6 deletions
diff --git a/main.cxx b/main.cxx
index 06f9c296..28d3bc8a 100644
--- a/main.cxx
+++ b/main.cxx
@@ -152,6 +152,9 @@ usage (systemtap_session& s, int exitcode)
#endif
// Formerly present --ignore-{vmlinux,dwarf} options are for testsuite use
// only, and don't belong in the eyesight of a plain user.
+ << " --compatible=VERSION" << endl
+ << " suppress incompatible language/tapset changes beyond VERSION," << endl
+ << " instead of " << s.compatible << endl
<< " --skip-badvars" << endl
<< " substitute zero for bad context $variables" << endl
<< endl
@@ -609,6 +612,7 @@ main (int argc, char * const argv [])
s.skip_badvars = false;
s.unprivileged = false;
s.omit_werror = false;
+ s.compatible = VERSION; // XXX: perhaps also process GIT_SHAID if available?
bool client_options = false;
string client_options_disallowed;
@@ -699,6 +703,7 @@ main (int argc, char * const argv [])
#define LONG_OPT_DISABLE_CACHE 11
#define LONG_OPT_POISON_CACHE 12
#define LONG_OPT_CLEAN_CACHE 13
+#define LONG_OPT_COMPATIBLE 14
// NB: also see find_hash(), usage(), switch stmt below, stap.1 man page
static struct option long_options[] = {
{ "kelf", 0, &long_opt, LONG_OPT_KELF },
@@ -720,6 +725,7 @@ main (int argc, char * const argv [])
{ "disable-cache", 0, &long_opt, LONG_OPT_DISABLE_CACHE },
{ "poison-cache", 0, &long_opt, LONG_OPT_POISON_CACHE },
{ "clean-cache", 0, &long_opt, LONG_OPT_CLEAN_CACHE },
+ { "compatible", 1, &long_opt, LONG_OPT_COMPATIBLE },
{ NULL, 0, NULL, 0 }
};
int grc = getopt_long (argc, argv, "hVvtp:I:e:o:R:r:a:m:kgPc:x:D:bs:uqwl:d:L:FS:B:W",
@@ -1038,12 +1044,20 @@ main (int argc, char * const argv [])
clean_cache(s);
exit(0);
+ case LONG_OPT_COMPATIBLE:
+ s.compatible = optarg;
+ break;
+
default:
+ // NOTREACHED unless one added a getopt option but not a corresponding switch/case:
+ cerr << "Unhandled long argument id " << long_opt << endl;
exit(1);
}
break;
default:
+ // NOTREACHED unless one added a getopt option but not a corresponding switch/case:
+ cerr << "Unhandled argument code " << (char)grc << endl;
exit(1);
break;
}
diff --git a/parse.cxx b/parse.cxx
index 6cdf76d9..72bfdd96 100644
--- a/parse.cxx
+++ b/parse.cxx
@@ -183,6 +183,7 @@ bool eval_comparison (const OPERAND& lhs, const token* op, const OPERAND& rhs)
// The basic form is %( CONDITION %? THEN-TOKENS %: ELSE-TOKENS %)
// where CONDITION is: kernel_v[r] COMPARISON-OP "version-string"
// or: arch COMPARISON-OP "arch-string"
+// or: systemtap_v COMPARISON-OP "version-string"
// or: CONFIG_foo COMPARISON-OP "config-string"
// or: CONFIG_foo COMPARISON-OP number
// or: CONFIG_foo COMPARISON-OP CONFIG_bar
@@ -202,17 +203,21 @@ bool eval_pp_conditional (systemtap_session& s,
const token* l, const token* op, const token* r)
{
if (l->type == tok_identifier && (l->content == "kernel_v" ||
- l->content == "kernel_vr"))
+ l->content == "kernel_vr" ||
+ l->content == "systemtap_v"))
{
+ if (! (r->type == tok_string))
+ throw parse_error ("expected string literal", r);
+
string target_kernel_vr = s.kernel_release;
string target_kernel_v = s.kernel_base_release;
+ string target;
- if (! (r->type == tok_string))
- throw parse_error ("expected string literal", r);
+ if (l->content == "kernel_v") target = target_kernel_v;
+ else if (l->content == "kernel_vr") target = target_kernel_vr;
+ else if (l->content == "systemtap_v") target = s.compatible;
+ else assert (0);
- string target = (l->content == "kernel_vr" ?
- target_kernel_vr.c_str() :
- target_kernel_v.c_str());
string query = r->content;
bool rhs_wildcard = (strpbrk (query.c_str(), "*?[") != 0);
@@ -2471,6 +2476,8 @@ expression* parser::parse_symbol ()
if (name == "@cast" || (name.size()>0 && name[0] == '$'))
return parse_target_symbol (t);
+ // NB: PR11343: @defined() is not incompatible with earlier versions
+ // of stap, so no need to check session.compatible for 1.2
if (name == "@defined")
return parse_defined_op (t);
diff --git a/session.h b/session.h
index f53de57c..ee1762a2 100644
--- a/session.h
+++ b/session.h
@@ -100,6 +100,7 @@ struct systemtap_session
std::string output_file;
std::string size_option;
std::string cmd;
+ std::string compatible; // use (strverscmp(s.compatible.c_str(), "N.M") >= 0)
int target_pid;
int last_pass;
unsigned perpass_verbose[5];
diff --git a/stap.1.in b/stap.1.in
index 01fb9aba..0fc052ff 100644
--- a/stap.1.in
+++ b/stap.1.in
@@ -249,6 +249,12 @@ output files exceed
.B \-\-skip\-badvars
Ignore out of context variables and substitute with literal 0.
+.TP
+.BI \-\-compatible VERSION
+Suppress recent script language or tapset changes which are incompatible
+with given older version of systemtap. This may be useful if a much older
+systemtap script fails to run.
+
.SH ARGUMENTS
Any additional arguments on the command line are passed to the script
diff --git a/testsuite/parseko/preprocess17.stp b/testsuite/parseko/preprocess17.stp
new file mode 100755
index 00000000..b447776d
--- /dev/null
+++ b/testsuite/parseko/preprocess17.stp
@@ -0,0 +1,3 @@
+#! /bin/sh
+
+stap --compatible=1.0 -p1 -e 'global %( systemtap_v >= "1.2" %? PASS %: "FAIL" %)'
diff --git a/testsuite/parseok/twenty.stp b/testsuite/parseok/twenty.stp
index d474ad5d..f03ae267 100755
--- a/testsuite/parseok/twenty.stp
+++ b/testsuite/parseok/twenty.stp
@@ -10,3 +10,6 @@ global
%( $# != 2 && @# < "1" && @# == "0" && $# >= 3 %?
%( $2 >= "12" %? $3 FAIL2 %: $2 FAIL3 %) #This line must not be evaluated
%: PASS2 %)
+
+global
+%( systemtap_v >= "1.2" %? PASS3 %: "FAIL" %)