- add netmap-libpcap
- add netmap (FreeBSD header files need to be updated with this) - move prototype perl scripts to prototype/ folder - create basic structure for sipcap app (no code yet)
This commit is contained in:
3
netmap/LINUX/scripts/help
Executable file
3
netmap/LINUX/scripts/help
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
|
||||
sed -n 's/^## \?//p' $1 | fmt
|
82
netmap/LINUX/scripts/linux-pktgen.sh
Executable file
82
netmap/LINUX/scripts/linux-pktgen.sh
Executable file
@ -0,0 +1,82 @@
|
||||
#!/bin/sh
|
||||
|
||||
#set -x
|
||||
|
||||
|
||||
function pgset()
|
||||
{
|
||||
local result
|
||||
|
||||
echo $1 > ${PGDEV}
|
||||
|
||||
result=$(cat $PGDEV | fgrep "Result: OK:")
|
||||
if [ "$result" = "" ]; then
|
||||
cat $PGDEV | fgrep "Result:"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
##################### Script configuration ######################
|
||||
N="$1" # number of TX kthreads minus one
|
||||
if [ -z "$1" ]; then
|
||||
N=0
|
||||
fi
|
||||
NCPUS="7" # number of CPUs on your machine minus one
|
||||
IF="enp1s0f1" # network interface to test
|
||||
DST_IP="10.216.8.1" # destination IP address
|
||||
DST_MAC="00:1b:21:80:e7:d9" # destination MAC address
|
||||
PKT_SIZE="60" # packet size
|
||||
PKT_COUNT="10000000" # number of packets to send
|
||||
CLONE_SKB="10000" # how many times a sk_buff is recycled
|
||||
|
||||
|
||||
# Load pktgen kernel module
|
||||
modprobe pktgen
|
||||
|
||||
|
||||
# Clean the configuration for all the CPU-kthread (from 0 to ${NCPUS})
|
||||
IDX=$(seq 0 1 ${NCPUS})
|
||||
for cpu in ${IDX}; do
|
||||
PGDEV="/proc/net/pktgen/kpktgend_${cpu}"
|
||||
echo "Removing all devices (${cpu})"
|
||||
pgset "rem_device_all"
|
||||
done
|
||||
|
||||
IDX=$(seq 0 1 ${N})
|
||||
for cpu in ${IDX}; do
|
||||
# kthread-device configuration
|
||||
PGDEV="/proc/net/pktgen/kpktgend_${cpu}"
|
||||
echo "Configuring $PGDEV"
|
||||
echo "Adding ${IF}@${cpu}"
|
||||
pgset "add_device ${IF}@${cpu}"
|
||||
|
||||
# Packets/mode configuration
|
||||
PGDEV="/proc/net/pktgen/${IF}@${cpu}"
|
||||
echo "Configuring $PGDEV"
|
||||
pgset "count ${PKT_COUNT}"
|
||||
pgset "clone_skb ${CLONE_SKB}"
|
||||
pgset "pkt_size ${PKT_SIZE}"
|
||||
pgset "delay 0"
|
||||
pgset "dst $DST_IP"
|
||||
pgset "dst_mac $DST_MAC"
|
||||
pgset "flag QUEUE_MAP_CPU"
|
||||
|
||||
echo ""
|
||||
done
|
||||
|
||||
|
||||
# Run
|
||||
PGDEV="/proc/net/pktgen/pgctrl"
|
||||
echo "Running... Ctrl-C to stop"
|
||||
pgset "start"
|
||||
echo "Done."
|
||||
|
||||
# Show results
|
||||
NUMS=""
|
||||
for cpu in ${IDX}; do
|
||||
TMP=$(cat /proc/net/pktgen/${IF}@${cpu} | grep -o "[0-9]\+pps" | grep -o "[0-9]\+")
|
||||
echo "$cpu $TMP"
|
||||
NUMS="${NUMS} ${TMP}"
|
||||
done
|
||||
|
||||
echo "Total TX rate: $(echo $NUMS | tr ' ' '+' | bc)"
|
428
netmap/LINUX/scripts/np
Executable file
428
netmap/LINUX/scripts/np
Executable file
@ -0,0 +1,428 @@
|
||||
#!/bin/bash
|
||||
## Manage linux driver patches for netmap.
|
||||
## usage (from the dir containing the Makefile):
|
||||
##
|
||||
## scripts/np <action> [args...]
|
||||
##
|
||||
## where <action> is any of the functions below.
|
||||
##
|
||||
|
||||
[ -f scripts/conf ] && source scripts/conf
|
||||
|
||||
## The following enviroment variables must be set:
|
||||
##
|
||||
## GITDIR: the absolute path of the netmap linux
|
||||
## git repository, containing all the required netmap-*
|
||||
## branches.
|
||||
[ -n "$GITDIR" -a -d "$GITDIR/.git" ] || {
|
||||
echo "GITDIR not set or not valid" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
NETMAP_BRANCH=${NETMAP_BRANCH:-master}
|
||||
|
||||
function error {
|
||||
echo "$@" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
function get-params {
|
||||
local params=$1; shift
|
||||
err_msg="$PROGNAME $COMMAND $(echo $params| perl -pe 's/\S+/<$&>/g')"
|
||||
local param
|
||||
for param in $params; do
|
||||
[[ -z "$@" ]] && error "$err_msg"
|
||||
pname=$(echo -n $param | perl -pe 's/\W/_/g')
|
||||
eval $pname="$1"
|
||||
shift
|
||||
done
|
||||
[[ -n "$@" ]] && error "$err_msg"
|
||||
}
|
||||
|
||||
##
|
||||
## LINUX_SOURCES: the absolute path of a
|
||||
## directory used to store all required linux-* source trees
|
||||
## (The script will extract linux-x.y.z from GITDIR if it needs
|
||||
## it and $LINUX_SOURCES does not already contain it).
|
||||
##
|
||||
## LINUX_CONFIGS: the absolute path of a
|
||||
## directory containing the configuration files for
|
||||
## the linux kernel. The file for version x must be named
|
||||
## config-x. config-all can be used as a default.
|
||||
##
|
||||
## The configuration variables can be put in scripts/conf.
|
||||
##
|
||||
|
||||
##
|
||||
## Available actions:
|
||||
##
|
||||
|
||||
##
|
||||
## driver-path <driver> <version>
|
||||
## retrieves the path of <driver> in the linux sources
|
||||
## for version <version>. The path is output to stdout.
|
||||
## It uses a local cache to minimize the expensive
|
||||
## file system search.
|
||||
function driver-path()
|
||||
{
|
||||
get-params "driver version" "$@"
|
||||
|
||||
cat cache/$version/$driver/path 2>/dev/null && return
|
||||
local kern=$(get-kernel $version)
|
||||
mkdir -p cache/$version/$driver
|
||||
(
|
||||
cd $kern
|
||||
find drivers/net -name $driver
|
||||
) | tee cache/$version/$driver/path
|
||||
}
|
||||
|
||||
|
||||
##
|
||||
## get-patch [-c] <driver> <version>
|
||||
## extract the netmap patch for the given <driver> and the
|
||||
## given kernel <version>. The patch is stored in tmp-patches
|
||||
## and the name of the patch is output to stdout.
|
||||
## If a patch with the same name already exists in tmp-patches
|
||||
## it is overwritten, unless the -c option is used,
|
||||
## in which case the existing patch is kept (the patch name is still output).
|
||||
function get-patch()
|
||||
{
|
||||
local use_cache
|
||||
[ "$1" = -c ] && { use_cache=1; shift; }
|
||||
|
||||
get-params "driver version" "$@"
|
||||
|
||||
# convert kernel version to fixed notation
|
||||
local v1=$(scripts/vers $version -c)
|
||||
# compute next kernel version (in fixed notation)
|
||||
local v2=$(scripts/vers $version -i -c)
|
||||
local patchname=diff--$driver--$v1--$v2
|
||||
local out=tmp-patches/$patchname
|
||||
[ -n "$use_cache" -a -s $out ] && { echo $out; return; }
|
||||
local drvpath=$(driver-path $driver $version)
|
||||
[ -n "$drvpath" ] || return
|
||||
local drvdir=$(dirname $drvpath)
|
||||
(
|
||||
cd $GITDIR
|
||||
git diff --relative=$drvdir v$version..netmap-$version -- $drvpath
|
||||
) > $out
|
||||
# an empty patch means no netmap support for this driver
|
||||
[ -s $out ] || { rm $out; return 1; }
|
||||
echo $out
|
||||
return 0;
|
||||
}
|
||||
|
||||
##
|
||||
## get-range <driver> <version1> <version2>
|
||||
## extracts the netmap patches for the given <driver> for
|
||||
## all the kernel versions from <version1> (included) to
|
||||
## <version2> (excluded). All patches are stored in tmp-patches
|
||||
## and their names are output to stdout.
|
||||
function get-range()
|
||||
{
|
||||
get-params "driver version1 version2" "$@"
|
||||
|
||||
local v=$version1
|
||||
# while version is less than $version2
|
||||
while scripts/vers -b $v $version2 -L; do
|
||||
get-patch $driver $v
|
||||
# compute next version
|
||||
v=$(scripts/vers $v -i)
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
##
|
||||
## get-src <driver> <version> <dest>
|
||||
## copies the original sources of the given <driver>,
|
||||
## from the given kernel <version> to the given <dest>
|
||||
## directory.
|
||||
## It uses a local cache to minimize the expensive
|
||||
## checkouts in GITDIR.
|
||||
function get-src()
|
||||
{
|
||||
get-params "driver version dest" "$@"
|
||||
|
||||
local kern=$(get-kernel $version)
|
||||
local src=$(driver-path $driver $version)
|
||||
cp -r $kern/$src $dest
|
||||
}
|
||||
|
||||
|
||||
##
|
||||
## extend <patch> <version>
|
||||
## checks wether the range of applicability of the
|
||||
## given <patch> can be extented to include <version>.
|
||||
## It returns 0 on success and 1 on failure.
|
||||
function extend()
|
||||
{
|
||||
get-params "patch version" "$@"
|
||||
|
||||
local _patch=$(realpath $patch)
|
||||
# extract the driver name from the patch name
|
||||
local driver=$(scripts/vers $_patch -s -p -p)
|
||||
local tmpdir1=$(mktemp -d)
|
||||
local tmpdir2=$(mktemp -d)
|
||||
trap "rm -rf $tmpdir1 $tmpdir2" 0
|
||||
# we get the driver sources for the given <version> and
|
||||
# we apply two patches separately:
|
||||
# i) the given <patch>;
|
||||
# ii) the proper patch from GITDIR.
|
||||
# We declare <patch> to be extendable if
|
||||
# - it is still applicable AND
|
||||
# - we obtain the same files from i) and ii) (ignoring whitespace)
|
||||
get-src $driver $version $tmpdir1
|
||||
get-src $driver $version $tmpdir2
|
||||
(
|
||||
cd $tmpdir1
|
||||
patch --no-backup-if-mismatch -p1 < $_patch >/dev/null 2>&1
|
||||
) || return 1
|
||||
local patch2=$(get-patch -c $driver $version)
|
||||
patch2=$(realpath $patch2)
|
||||
(
|
||||
cd $tmpdir2
|
||||
patch -p1 < $patch2 >/dev/null 2>&1
|
||||
) # this will certainly apply
|
||||
diff -qbBr $tmpdir1 $tmpdir2 >/dev/null || return 1
|
||||
return 0
|
||||
}
|
||||
|
||||
##
|
||||
## minimize <driver>
|
||||
## tries to minimize the number of patch files for the given
|
||||
## <driver>. It uses the patches currently found in tmp-patches
|
||||
## and stores the resulting patches in final-patches.
|
||||
## If final-patches already contained patches for <driver>,
|
||||
## they are deleted first.
|
||||
function minimize()
|
||||
{
|
||||
get-params "driver" "$@"
|
||||
|
||||
mkdir -p final-patches
|
||||
local drv=$(basename $driver)
|
||||
local patches=$(ls tmp-patches/diff--$drv--* 2>/dev/null)
|
||||
[ -n "$patches" ] || return 1
|
||||
# put the patch names in $1, $2, ...
|
||||
set $patches
|
||||
rm -f final-patches/diff--$drv--*
|
||||
# the original patches (in tmp-patches) are ordered by version number.
|
||||
# We consider one patch in turn (the 'pivot') and try
|
||||
# to extend its range to cover the range of the next
|
||||
# patch. If this succedes, the merged patch is the new
|
||||
# pivot, otherwise the current pivot is output and the
|
||||
# next patch becomes the new pivot. The process
|
||||
# is repeated until there are no more patches to consider.
|
||||
local pivot=$1
|
||||
[ -n "$pivot" -a -e "$pivot" ] || return 1
|
||||
# extract the left end and right end of the pivot's range
|
||||
local ple=$(scripts/vers $pivot -s -p -C)
|
||||
local pre=$(scripts/vers $pivot -s -C)
|
||||
while [ -n "$pivot" ]; do
|
||||
shift
|
||||
if [ -n "$1" ]; then
|
||||
# extract the left end and right end of the next patch
|
||||
local nle=$(scripts/vers $1 -s -p -C)
|
||||
local nre=$(scripts/vers $1 -s -C)
|
||||
# we admit no gaps in the range
|
||||
if [ $pre = $nle ] && extend $pivot $nle; then
|
||||
pre=$nre
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
# either out of patches or failed merge.
|
||||
# Compute the file name of the current pivot and store
|
||||
# the patch in its final location
|
||||
out=$(scripts/vers diff $drv $ple -c $pre -c -S4)
|
||||
cp $pivot final-patches/$out
|
||||
# the new pivot becames the next patch (if any)
|
||||
pivot=$1
|
||||
pre=$nre
|
||||
ple=$nle
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
##
|
||||
## infty <driver> <version>
|
||||
## if final-patches contains a patch for <driver> with a range
|
||||
## ending in <version>, extend it to infinity.
|
||||
## Do nothing otherwise.
|
||||
function infty()
|
||||
{
|
||||
get-params "driver version" "$@"
|
||||
|
||||
local drv=$(basename $driver)
|
||||
# convert kernel version to fixed notation
|
||||
local v=$(scripts/vers $version -c)
|
||||
local last=$(ls final-patches/diff--$drv--*--$v 2>/dev/null|tail -n1)
|
||||
[ -n "$last" ] || return 1
|
||||
mv -n $last $(scripts/vers $last -s -p 99999 -S4) 2>/dev/null
|
||||
}
|
||||
|
||||
function get-kernel()
|
||||
{
|
||||
get-params "version" "$@"
|
||||
|
||||
local dst="$(realpath $LINUX_SOURCES)/linux-$version"
|
||||
|
||||
[ -d $dst ] && { echo $dst; return; }
|
||||
|
||||
mkdir -p $dst
|
||||
|
||||
(
|
||||
cd $GITDIR
|
||||
git archive v$v | tar xf - -C $dst
|
||||
)
|
||||
echo $dst
|
||||
}
|
||||
|
||||
|
||||
##
|
||||
## build-prep <version>
|
||||
## prepare the linux tree for <version> to be ready
|
||||
## for external modules compilation.
|
||||
## The tree is put in $LINUX_SOURCES/linux-<version> and the
|
||||
## configuration is obtained from $LINUX_CONFIGS/config-<version>
|
||||
## (or $LINUX_CONFIGS/config-all by default).
|
||||
## Errors are logged to $LINUX_CONFIGS/linux-<version>.log.
|
||||
## If $LINUX_SOURCES/linux-<version> already exists,
|
||||
## nothing is done.
|
||||
## In all cases, the absolute path of linux-<version> is
|
||||
## output.
|
||||
function build-prep()
|
||||
{
|
||||
get-params "version" "$@"
|
||||
|
||||
local dst=$(get-kernel $version)
|
||||
|
||||
exec 3>&1 4>&2 >$dst.log 2>&1
|
||||
cp $LINUX_CONFIGS/config-$v $dst/.config 2>/dev/null ||
|
||||
cp $LINUX_CONFIGS/config-all $dst/.config
|
||||
(
|
||||
cd $dst
|
||||
yes '' | make oldconfig
|
||||
make modules_prepare
|
||||
)
|
||||
exec 1>&3 2>&4
|
||||
echo $dst
|
||||
}
|
||||
|
||||
##
|
||||
## check-patch <patch>
|
||||
## check that the given <patch> applies and compiles without
|
||||
## error for all its declared range of applicability.
|
||||
## Errors are logged to log/<patch>.
|
||||
function check-patch()
|
||||
{
|
||||
get-params "patch" "$@"
|
||||
|
||||
# extract the left version
|
||||
local v1=$(scripts/vers $patch -s -p -C)
|
||||
# extract the right version
|
||||
local v2=$(scripts/vers $patch -s -C)
|
||||
# extract the driver name
|
||||
local driver=$(scripts/vers $patch -s -p -p)
|
||||
local p=$(realpath $patch)
|
||||
mkdir -p log
|
||||
local log="$(realpath log)/$(basename $patch)"
|
||||
local nmcommit=$(cd ..; git show-ref -s heads/$NETMAP_BRANCH)
|
||||
|
||||
echo -n $patch...
|
||||
|
||||
while scripts/vers -b $v1 $v2 -L; do
|
||||
# cache lookup
|
||||
local cache=cache/$v1/$driver
|
||||
local cpatch=$cache/patch
|
||||
local cnmcommit=$cache/nmcommit
|
||||
local cstatus=$cache/status
|
||||
local clog=$cache/log
|
||||
if [ -f $cpatch ] &&
|
||||
cmp -s $cpatch $patch &&
|
||||
[ "$nmcommit" = "$(cat $cnmcommit)" ]; then
|
||||
cp $clog $log
|
||||
ok=$(cat $cstatus)
|
||||
else
|
||||
# update cache
|
||||
cp $patch $cpatch
|
||||
echo $nmcommit > $cnmcommit
|
||||
|
||||
local ksrc=$(build-prep $v1)
|
||||
local tmpdir=$(mktemp -d)
|
||||
trap "rm -rf $tmpdir" 0
|
||||
(cd ..; git archive $NETMAP_BRANCH | tar xf - -C $tmpdir )
|
||||
pushd $tmpdir/LINUX >/dev/null
|
||||
mkdir single-patch
|
||||
rm patches
|
||||
ln -s single-patch patches
|
||||
cp $p single-patch
|
||||
ok=false
|
||||
make KSRC=$ksrc >$log 2>&1 && ok=true
|
||||
popd >/dev/null
|
||||
cp $log $clog
|
||||
fi
|
||||
[ $ok = true ] || { echo FAILED; echo false > $cstatus; return 1; }
|
||||
echo true > $cstatus
|
||||
rm -rf $tmpdir
|
||||
# compute next version
|
||||
v1=$(scripts/vers $v1 -i)
|
||||
done
|
||||
echo OK
|
||||
}
|
||||
|
||||
##
|
||||
## build-check <driver>
|
||||
## do a check-patch for all the patches of <driver> that are
|
||||
## currently in tmp-patches. Patches that fail the check
|
||||
## are moved to failed-patches.
|
||||
function build-check()
|
||||
{
|
||||
get-params "driver" "$@"
|
||||
|
||||
mkdir -p failed-patches
|
||||
local drv=$(basename $driver)
|
||||
local patches=$(ls tmp-patches/diff--$drv--* 2>/dev/null)
|
||||
local p
|
||||
for p in $patches; do
|
||||
check-patch $p || mv $p failed-patches
|
||||
done
|
||||
}
|
||||
|
||||
##
|
||||
## forall <cmd> [args...]
|
||||
## exec <cmd> <driver> [args...] for all known drivers.
|
||||
function forall()
|
||||
{
|
||||
local cmd=$1
|
||||
shift
|
||||
# we obtain the value of DRIVER_SRC from the makefile
|
||||
# (the +% target is defined in our Makefile and prints
|
||||
# the contents of variable %)
|
||||
local driver_srcs=$(make +DRIVER_SRCS)
|
||||
|
||||
local driver
|
||||
for driver in $driver_srcs; do
|
||||
$cmd $(basename $driver) "$@"
|
||||
done
|
||||
}
|
||||
|
||||
mkdir -p tmp-patches
|
||||
|
||||
PROGNAME=$0
|
||||
|
||||
[ -n "$1" ] || {
|
||||
scripts/help $PROGNAME;
|
||||
exit 1
|
||||
}
|
||||
|
||||
COMMAND=$1; shift
|
||||
case $COMMAND in
|
||||
*-all)
|
||||
forall ${COMMAND%-all} "$@"
|
||||
;;
|
||||
-[hH]|--help|-help|help)
|
||||
scripts/help $PROGNAME
|
||||
;;
|
||||
*)
|
||||
$COMMAND "$@"
|
||||
;;
|
||||
esac
|
162
netmap/LINUX/scripts/vers
Executable file
162
netmap/LINUX/scripts/vers
Executable file
@ -0,0 +1,162 @@
|
||||
#!/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";
|
Reference in New Issue
Block a user