163 lines
3.1 KiB
Plaintext
163 lines
3.1 KiB
Plaintext
|
#!/usr/bin/perl
|
||
|
## Simple stack-based RPN calculator for linux version numbers.
|
||
|
## Usage:
|
||
|
##
|
||
|
## scripts/vers [operand|operation ...]
|
||
|
##
|
||
|
## Operations all start with '-', everything else is an operand
|
||
|
## and is pushed on the stack as-is.
|
||
|
## When all arguments have been processed, the content of the
|
||
|
## top of the stack is printed on stdout and the script ends.
|
||
|
##
|
||
|
## Available operations:
|
||
|
|
||
|
sub badversion
|
||
|
{
|
||
|
my $v = shift;
|
||
|
die "Bad version $v";
|
||
|
}
|
||
|
|
||
|
sub conv
|
||
|
{
|
||
|
my $v = shift;
|
||
|
|
||
|
return sprintf "%x%02x%02x", (split /\./, $v);
|
||
|
}
|
||
|
|
||
|
|
||
|
sub rconv
|
||
|
{
|
||
|
my $v = shift;
|
||
|
|
||
|
$v =~ /(.*)(..)(..)$/;
|
||
|
if ($1 > 2 && (hex $3) == 0) {
|
||
|
return sprintf "%d.%d", (hex $1), (hex $2);
|
||
|
}
|
||
|
return sprintf "%d.%d.%d", (hex $1), (hex $2), (hex $3);
|
||
|
}
|
||
|
|
||
|
sub next
|
||
|
{
|
||
|
my $v = shift;
|
||
|
my ($may, $min, $sub) = split /\./, $v;
|
||
|
|
||
|
if ($may < 2 || ($may == 2 && $min != 6)) {
|
||
|
&badversion($v);
|
||
|
}
|
||
|
if ($may == 2) {
|
||
|
if ($sub < 39) {
|
||
|
return "2.6." . ($sub + 1);
|
||
|
} elsif ($sub == 39) {
|
||
|
return "3.0";
|
||
|
} else {
|
||
|
&badversion($v);
|
||
|
}
|
||
|
} else {
|
||
|
return "$may." . ($min + 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@ARGV or do { system("scripts/help $0"); exit 1; };
|
||
|
|
||
|
for (@ARGV) {
|
||
|
##
|
||
|
## -b (nullary) suppress normal output. On exit, return 1
|
||
|
## if stack top is "false", 0 otherwise.
|
||
|
/^-b$/ && do {
|
||
|
$silent=1;
|
||
|
next;
|
||
|
};
|
||
|
##
|
||
|
## -c (unary) convert from dot to fixed notation
|
||
|
/^-c$/ && do {
|
||
|
$v = pop @stack;
|
||
|
push @stack, &conv($v);
|
||
|
next;
|
||
|
};
|
||
|
##
|
||
|
## -C (unary) convert from fixed to dot notation
|
||
|
/^-C$/ && do {
|
||
|
$v = pop @stack;
|
||
|
push @stack, &rconv($v);
|
||
|
next;
|
||
|
};
|
||
|
##
|
||
|
## -i (unary) increment version number
|
||
|
## (must be in dot notation)
|
||
|
/^-i$/ && do {
|
||
|
$v = pop @stack;
|
||
|
push @stack, &next($v);
|
||
|
next;
|
||
|
};
|
||
|
##
|
||
|
## -s (unary) assume the stack top is a
|
||
|
## string containing several fields separated
|
||
|
## by '--'. Replace the stack top with these
|
||
|
## fields (last on top)
|
||
|
/^-s$/ && do {
|
||
|
$v = pop @stack;
|
||
|
push @stack, split /--/, $v;
|
||
|
next;
|
||
|
};
|
||
|
##
|
||
|
## -SN (N-ary) pop N elements from the stack,
|
||
|
## join them using '--' as a separator
|
||
|
## (top as last) and push the resulting
|
||
|
## string
|
||
|
/^-S(\d+)$/ && do {
|
||
|
$n = $1;
|
||
|
@t = @stack[-$n..-1];
|
||
|
while ($n--) {
|
||
|
pop @stack;
|
||
|
}
|
||
|
push @stack, (join '--', @t);
|
||
|
next;
|
||
|
};
|
||
|
##
|
||
|
## -p (unary) pop
|
||
|
/^-p$/ && do {
|
||
|
pop @stack;
|
||
|
next;
|
||
|
};
|
||
|
##
|
||
|
## -l (binary) push "true" if first version
|
||
|
## number is stricly less then second version
|
||
|
## number (versions in fixed notation)
|
||
|
##
|
||
|
## -L (binary) like -l, but for version numbers
|
||
|
## in dot notation
|
||
|
/^-[lL]$/ && do {
|
||
|
$v1 = pop @stack;
|
||
|
$v2 = pop @stack;
|
||
|
/^-L$/ && do {
|
||
|
$v1 = &conv($v1);
|
||
|
$v2 = &conv($v2);
|
||
|
};
|
||
|
push @stack, (($v2 lt $v1) ? "true" : "false");
|
||
|
next;
|
||
|
};
|
||
|
##
|
||
|
## -a (binary) logical and. Arguments must be
|
||
|
## either "true" or "false".
|
||
|
/^-a$/ && do {
|
||
|
$v1 = pop @stack;
|
||
|
$v2 = pop @stack;
|
||
|
push @stack, (($v1 eq "true" && $v2 eq "true") ? "true" : "false");
|
||
|
next;
|
||
|
};
|
||
|
##
|
||
|
## -n (unary) logical not. Argument must be
|
||
|
## either "true" or "false".
|
||
|
/^-n$/ && do {
|
||
|
$v1 = pop @stack;
|
||
|
push @stack, (($v1 eq "true") ? "false" : "true");
|
||
|
next;
|
||
|
};
|
||
|
push @stack, $_;
|
||
|
}
|
||
|
$v = pop @stack;
|
||
|
if ($silent) {
|
||
|
exit ($v eq "false");
|
||
|
}
|
||
|
print "$v\n";
|