1
0
mirror of https://gitlab.com/libvirt/libvirt.git synced 2024-12-22 17:34:18 +03:00

src: rewrite systemtap function generator in Python

As part of a goal to eliminate Perl from libvirt build tools,
rewrite the gensystemtap.pl tool in Python.

This was a straight conversion, manually going line-by-line to
change the syntax from Perl to Python. Thus the overall structure
of the file and approach is the same.

Tested-by: Cole Robinson <crobinso@redhat.com>
Reviewed-by: Ján Tomko <jtomko@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
Daniel P. Berrangé 2019-08-30 13:22:54 +01:00
parent 952c018efe
commit 6f4f52d05f
6 changed files with 189 additions and 199 deletions

View File

@ -51,6 +51,7 @@ EXTRA_DIST = \
scripts/check-symfile.py \
scripts/check-symsorting.py \
scripts/dtrace2systemtap.py \
scripts/gensystemtap.py \
scripts/header-ifdef.py \
scripts/minimize-po.py \
scripts/mock-noinline.py \

View File

@ -479,6 +479,7 @@ sc_prohibit_risky_id_promotion:
# since gnulib has more guarantees for snprintf portability
sc_prohibit_sprintf:
@prohibit='\<[s]printf\>' \
in_vc_files='\.[ch]$$' \
halt='use g_snprintf, not sprintf' \
$(_sc_search_regexp)
@ -2279,9 +2280,6 @@ exclude_file_name_regexp--sc_prohibit_readlink = \
exclude_file_name_regexp--sc_prohibit_setuid = ^src/util/virutil\.c|tools/virt-login-shell\.c$$
exclude_file_name_regexp--sc_prohibit_sprintf = \
^(build-aux/syntax-check\.mk|docs/hacking\.html\.in|.*\.stp|.*\.pl)$$
exclude_file_name_regexp--sc_prohibit_snprintf = \
^(build-aux/syntax-check\.mk|docs/hacking\.html\.in|tools/virt-login-shell\.c)$$

184
scripts/gensystemtap.py Executable file
View File

@ -0,0 +1,184 @@
#!/usr/bin/env python
#
# Copyright (C) 2011-2019 Red Hat, Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library. If not, see
# <http://www.gnu.org/licenses/>.
#
# Generate a set of systemtap functions for translating various
# RPC enum values into strings
#
# python gensystemtap.py */*.x > libvirt_functions.stp
#
from __future__ import print_function
import re
import sys
funcs = {}
types = {}
status = {}
auth = {}
def load_file(fh):
instatus = False
intype = False
inauth = False
for line in fh:
if re.search(r'''enum\s+virNetMessageType''', line):
intype = True
elif re.search(r'''enum\s+virNetMessageStatus''', line):
instatus = True
elif re.search(r'''enum remote_auth_type''', line):
inauth = True
elif line.find("}") != -1:
intype = False
instatus = False
inauth = False
elif instatus:
m = re.search(r'''^\s+VIR_NET_(\w+)\s*=\s*(\d+),?$''', line)
if m is not None:
status[m.group(2)] = m.group(1).lower()
elif intype:
m = re.search(r'''^\s+VIR_NET_(\w+)\s*=\s*(\d+),?$''', line)
if m is not None:
types[m.group(2)] = m.group(1).lower()
elif inauth:
m = re.search(r'''^\s+REMOTE_AUTH_(\w+)\s*=\s*(\d+),?$''', line)
if m is not None:
auth[m.group(2)] = m.group(1).lower()
else:
m = re.search(r'''(?:VIR_)?(\w+?)(?:_PROTOCOL)?''' +
r'''_PROGRAM\s*=\s*0x([a-fA-F0-9]+)\s*;''', line)
if m is not None:
funcs[m.group(1).lower()] = {
"id": int(m.group(2), 16),
"version": None,
"progs": []
}
continue
m = re.search(r'''(?:VIR_)?(\w+?)(?:_PROTOCOL)?_''' +
r'''(?:PROGRAM|PROTOCOL)_VERSION\s*=\s*(\d+)\s*;''',
line)
if m is not None:
funcs[m.group(1).lower()]["version"] = m.group(2)
continue
m = re.search(r'''(?:VIR_)?(\w+?)(?:_PROTOCOL)?''' +
r'''_PROC_(.*?)\s+=\s+(\d+)''', line)
if m is not None:
funcs[m.group(1).lower()]["progs"].insert(
int(m.group(3)), m.group(2).lower())
for file in sys.argv[1:]:
with open(file, "r") as fh:
load_file(fh)
def genfunc(name, varname, types):
print("function %s(%s, verbose)" % (name, varname))
print("{")
first = True
for typename in sorted(types.keys()):
cond = "} else if"
if first:
cond = "if"
first = False
print(" %s (%s == %s) {" % (cond, varname, typename))
print(" %sstr = \"%s\"" % (varname, types[typename]))
print(" } else {")
print(" %sstr = \"unknown\";" % varname)
print(" verbose = 1;")
print(" }")
print(" if (verbose) {")
print(" %sstr = %sstr . sprintf(\":%%d\", %s)" %
(varname, varname, varname))
print(" }")
print(" return %sstr;" % varname)
print("}")
genfunc("libvirt_rpc_auth_name", "type", auth)
genfunc("libvirt_rpc_type_name", "type", types)
genfunc("libvirt_rpc_status_name", "status", status)
print("function libvirt_rpc_program_name(program, verbose)")
print("{")
first = True
for funcname in sorted(funcs.keys()):
cond = "} else if"
if first:
cond = "if"
first = False
print(" %s (program == %s) {" % (cond, funcs[funcname]["id"]))
print(" programstr = \"%s\"" % funcname)
print(" } else {")
print(" programstr = \"unknown\";")
print(" verbose = 1;")
print(" }")
print(" if (verbose) {")
print(" programstr = programstr . sprintf(\":%d\", program)")
print(" }")
print(" return programstr;")
print("}")
print("function libvirt_rpc_procedure_name(program, version, proc, verbose)")
print("{")
first = True
for prog in sorted(funcs.keys()):
cond = "} else if"
if first:
cond = "if"
first = False
print(" %s (program == %s && version == %s) {" %
(cond, funcs[prog]["id"], funcs[prog]["version"]))
pfirst = True
for id in range(len(funcs[prog]["progs"])):
pcond = "} else if"
if pfirst:
pcond = "if"
pfirst = False
print(" %s (proc == %s) {" % (pcond, id + 1))
print(" procstr = \"%s\";" % funcs[prog]["progs"][id])
print(" } else {")
print(" procstr = \"unknown\";")
print(" verbose = 1;")
print(" }")
print(" } else {")
print(" procstr = \"unknown\";")
print(" verbose = 1;")
print(" }")
print(" if (verbose) {")
print(" procstr = procstr . sprintf(\":%d\", proc)")
print(" }")
print(" return procstr;")
print("}")

View File

@ -558,8 +558,9 @@ RPC_PROBE_FILES += $(srcdir)/rpc/virnetprotocol.x \
$(srcdir)/remote/qemu_protocol.x \
$(srcdir)/admin/admin_protocol.x
libvirt_functions.stp: $(RPC_PROBE_FILES) $(srcdir)/rpc/gensystemtap.pl
$(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gensystemtap.pl $(RPC_PROBE_FILES) > $@
libvirt_functions.stp: $(RPC_PROBE_FILES) $(top_srcdir)/scripts/gensystemtap.py
$(AM_V_GEN)$(RUNUTF8) $(PYTHON) $(top_srcdir)/scripts/gensystemtap.py \
$(RPC_PROBE_FILES) > $@
%_probes.stp: %_probes.d $(top_srcdir)/scripts/dtrace2systemtap.py \
$(top_builddir)/config.status

View File

@ -3,7 +3,6 @@
EXTRA_DIST += \
rpc/gendispatch.pl \
rpc/genprotocol.pl \
rpc/gensystemtap.pl \
rpc/virnetprotocol.x \
rpc/virkeepaliveprotocol.x \
$(NULL)

View File

@ -1,193 +0,0 @@
#!/usr/bin/env perl
#
# Copyright (C) 2011-2012 Red Hat, Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library. If not, see
# <http://www.gnu.org/licenses/>.
#
# Generate a set of systemtap functions for translating various
# RPC enum values into strings
#
# perl gensystemtap.pl */*.x > libvirt_functions.stp
#
use strict;
my %funcs;
my %type;
my %status;
my %auth;
my $instatus = 0;
my $intype = 0;
my $inauth = 0;
while (<>) {
if (/enum\s+virNetMessageType/) {
$intype = 1;
} elsif (/enum\s+virNetMessageStatus/) {
$instatus = 1;
} elsif (/enum remote_auth_type/) {
$inauth = 1;
} elsif (/}/) {
$instatus = $intype = $inauth = 0;
} elsif ($instatus) {
if (/^\s+VIR_NET_(\w+)\s*=\s*(\d+),?$/) {
$status{$2} = lc $1;
}
} elsif ($intype) {
if (/^\s+VIR_NET_(\w+)\s*=\s*(\d+),?$/) {
$type{$2} = lc $1;
}
} elsif ($inauth) {
if (/^\s+REMOTE_AUTH_(\w+)\s*=\s*(\d+),?$/) {
$auth{$2} = lc $1;
}
} else {
if (/(?:VIR_)?(\w+?)(?:_PROTOCOL)?_PROGRAM\s*=\s*0x([a-fA-F0-9]+)\s*;/) {
$funcs{lc $1} = { id => hex($2), version => undef, progs => [] };
} elsif (/(?:VIR_)?(\w+?)(?:_PROTOCOL)?_(?:PROGRAM|PROTOCOL)_VERSION\s*=\s*(\d+)\s*;/) {
$funcs{lc $1}->{version} = $2;
} elsif (/(?:VIR_)?(\w+?)(?:_PROTOCOL)?_PROC_(.*?)\s+=\s+(\d+)/) {
$funcs{lc $1}->{progs}->[$3] = lc $2;
}
}
}
print <<EOF;
function libvirt_rpc_auth_name(type, verbose)
{
EOF
my $first = 1;
foreach my $type (sort(keys %auth)) {
my $cond = $first ? "if" : "} else if";
$first = 0;
print " $cond (type == ", $type, ") {\n";
print " typestr = \"", $auth{$type}, "\"\n";
}
print <<EOF;
} else {
typestr = "unknown";
verbose = 1;
}
if (verbose) {
typestr = typestr . sprintf(":%d", type)
}
return typestr;
}
EOF
print <<EOF;
function libvirt_rpc_type_name(type, verbose)
{
EOF
$first = 1;
foreach my $type (sort(keys %type)) {
my $cond = $first ? "if" : "} else if";
$first = 0;
print " $cond (type == ", $type, ") {\n";
print " typestr = \"", $type{$type}, "\"\n";
}
print <<EOF;
} else {
typestr = "unknown";
verbose = 1;
}
if (verbose) {
typestr = typestr . sprintf(":%d", type)
}
return typestr;
}
EOF
print <<EOF;
function libvirt_rpc_status_name(status, verbose)
{
EOF
$first = 1;
foreach my $status (sort(keys %status)) {
my $cond = $first ? "if" : "} else if";
$first = 0;
print " $cond (status == ", $status, ") {\n";
print " statusstr = \"", $status{$status}, "\"\n";
}
print <<EOF;
} else {
statusstr = "unknown";
verbose = 1;
}
if (verbose) {
statusstr = statusstr . sprintf(":%d", status)
}
return statusstr;
}
EOF
print <<EOF;
function libvirt_rpc_program_name(program, verbose)
{
EOF
$first = 1;
foreach my $prog (sort(keys %funcs)) {
my $cond = $first ? "if" : "} else if";
$first = 0;
print " $cond (program == ", $funcs{$prog}->{id}, ") {\n";
print " programstr = \"", $prog, "\"\n";
}
print <<EOF;
} else {
programstr = "unknown";
verbose = 1;
}
if (verbose) {
programstr = programstr . sprintf(":%d", program)
}
return programstr;
}
EOF
print <<EOF;
function libvirt_rpc_procedure_name(program, version, proc, verbose)
{
EOF
$first = 1;
foreach my $prog (sort(keys %funcs)) {
my $cond = $first ? "if" : "} else if";
$first = 0;
print " $cond (program == ", $funcs{$prog}->{id}, " && version == ", $funcs{$prog}->{version}, ") {\n";
my $pfirst = 1;
for (my $id = 1 ; $id <= $#{$funcs{$prog}->{progs}} ; $id++) {
my $cond = $pfirst ? "if" : "} else if";
$pfirst = 0;
print " $cond (proc == $id) {\n";
print " procstr = \"", $funcs{$prog}->{progs}->[$id], "\";\n";
}
print " } else {\n";
print " procstr = \"unknown\";\n";
print " verbose = 1;\n";
print " }\n";
}
print <<EOF;
} else {
procstr = "unknown";
verbose = 1;
}
if (verbose) {
procstr = procstr . sprintf(":%d", proc)
}
return procstr;
}
EOF