aboutsummaryrefslogtreecommitdiffstats
path: root/tools/convert_expert_add_info_format.pl
diff options
context:
space:
mode:
authorMichael Mann <mmann78@netscape.net>2013-08-24 01:42:43 +0000
committerMichael Mann <mmann78@netscape.net>2013-08-24 01:42:43 +0000
commitdf309c6c27c7765125e0756ea942d7f45c7e5aab (patch)
tree175cc42bb593349eb06d28a0a3276fbddf7578e1 /tools/convert_expert_add_info_format.pl
parente123d27ca9db105a2af361d34dcd3285789bcd81 (diff)
Tool to help convert current expert_add_info_format() calls into filterable expert info API. It's not as helpful as convert_proto_tree_add_text.pl because the expert string is usually too long to take the ei_ variable name or display filter string as is, but it does do the batch "search and replace" nicely and makes finding common expert info easier.
svn path=/trunk/; revision=51506
Diffstat (limited to 'tools/convert_expert_add_info_format.pl')
-rwxr-xr-xtools/convert_expert_add_info_format.pl427
1 files changed, 427 insertions, 0 deletions
diff --git a/tools/convert_expert_add_info_format.pl b/tools/convert_expert_add_info_format.pl
new file mode 100755
index 0000000000..b54d2ff446
--- /dev/null
+++ b/tools/convert_expert_add_info_format.pl
@@ -0,0 +1,427 @@
+#!/usr/bin/env perl
+#
+# Copyright 2013 Michael Mann (see AUTHORS file)
+#
+# A program to help convert expert_add_info_format calls into filterable "items" that
+# use the other expert API calls. The program requires 2 passes. "Pass 1" (generate) collects
+# the eligible expert_add_info_format calls and outputs the necessary data into a delimited
+# file. "Pass 2" (fix-all) takes the data from the delimited file and replaces the
+# expert_add_info_format calls with filterable "expert info" calls as well as
+# generating a separate files for the ei variable declarations and array data.
+# The ei "file" can be copy/pasted into the dissector where appropriate
+#
+# Note that the output from "Pass 1" won't always be a perfect conversion for "Pass 2", so
+# "human interaction" is needed as an intermediary to verify and update the delimited file
+# before "Pass 2" is done.
+#
+# Delimited file field format:
+# <convert expert_add_info_format_call[1-4]><add ei variable[0|1]><ei var><[GROUP]><[SEVERITY]><[FIELDNAME]><[EXPERTABBREV]>
+# <pinfo var><proto_item var><tvb var><offset><length><params>
+#
+# convert proto_tree_add_text_call enumerations:
+# 1 - expert_add_info
+# 2 - expert_add_info_format_text
+# 3 - proto_tree_add_expert
+# 4 - proto_tree_add_expert_format
+#
+# Usage: convert_expert_add_info_format.pl action=<generate|fix-all> <file or files>
+#
+# Based off of convert_proto_tree_add_text.pl
+#
+# $Id$
+#
+# Wireshark - Network traffic analyzer
+# By Gerald Combs <gerald@wireshark.org>
+# Copyright 1998 Gerald Combs
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+
+use strict;
+use warnings;
+
+use Getopt::Long;
+
+my %EXPERT_SEVERITY = ('PI_COMMENT' => "PI_COMMENT",
+ 'PI_CHAT' => "PI_CHAT",
+ 'PI_NOTE' => "PI_NOTE",
+ 'PI_WARN' => "PI_WARN",
+ 'PI_ERROR' => "PI_ERROR");
+
+my %EXPERT_GROUPS = ('PI_CHECKSUM' => "PI_CHECKSUM",
+ 'PI_SEQUENCE' => "PI_SEQUENCE",
+ 'PI_RESPONSE_CODE' => "PI_RESPONSE_CODE",
+ 'PI_REQUEST_CODE' => "PI_REQUEST_CODE",
+ 'PI_UNDECODED' => "PI_UNDECODED",
+ 'PI_REASSEMBLE' => "PI_REASSEMBLE",
+ 'PI_MALFORMED' => "PI_MALFORMED",
+ 'PI_DEBUG' => "PI_DEBUG",
+ 'PI_PROTOCOL' => "PI_PROTOCOL",
+ 'PI_SECURITY' => "PI_SECURITY",
+ 'PI_COMMENTS_GROUP' => "PI_COMMENTS_GROUP");
+
+my @expert_list;
+my $protabbrev = "";
+
+# Perl trim function to remove whitespace from the start and end of the string
+sub trim($)
+{
+ my $string = shift;
+ $string =~ s/^\s+//;
+ $string =~ s/\s+$//;
+ return $string;
+}
+
+# ---------------------------------------------------------------------
+#
+# MAIN
+#
+my $helpFlag = '';
+my $action = 'generate';
+my $register = '';
+
+my $result = GetOptions(
+ 'action=s' => \$action,
+ 'register' => \$register,
+ 'help|?' => \$helpFlag
+ );
+
+if (!$result || $helpFlag || !$ARGV[0]) {
+ usage();
+}
+
+sub usage {
+ print "\nUsage: $0 [--action=generate|fix-all|find-all] FILENAME [...]\n\n";
+ print " --action = generate (default)\n";
+ print " generate - create a delimited file (FILENAME.expert_add_info_input) with\n";
+ print " expert_add_info_format fields in FILENAME(s)\n";
+ print " fix-all - Use delimited file (FILENAME.expert_add_info_input) to convert\n";
+ print " expert_add_info_format to \"filterable\" expert API\n";
+ print " Also generates FILENAME.ei to be copy/pasted into\n";
+ print " the dissector where appropriate\n\n";
+ print " --register = generate ei_register_info and expert register function calls\n\n";
+
+ exit(1);
+}
+
+#
+# XXX Outline general algorithm here
+#
+my $found_total = 0;
+my $protabbrev_index;
+my $line_number = 0;
+
+while (my $fileName = $ARGV[0]) {
+ shift;
+ my $fileContents = '';
+
+ die "No such file: \"$fileName\"\n" if (! -e $fileName);
+
+ # delete leading './'
+ $fileName =~ s{ ^ \. / } {}xo;
+
+ #determine PROTABBREV for dissector based on file name format of (dirs)/packet-PROTABBREV.c
+ $protabbrev_index = rindex($fileName, "packet-");
+ if ($protabbrev_index == -1) {
+ print "$fileName doesn't fit format of packet-PROTABBREV.c\n";
+ next;
+ }
+
+ $protabbrev = substr($fileName, $protabbrev_index+length("packet-"));
+ $protabbrev_index = rindex($protabbrev, ".");
+ if ($protabbrev_index == -1) {
+ print "$fileName doesn't fit format of packet-PROTABBREV.c\n";
+ next;
+ }
+ $protabbrev = lc(substr($protabbrev, 0, $protabbrev_index));
+
+ # Read in the file (ouch, but it's easier that way)
+ open(FCI, "<", $fileName) || die("Couldn't open $fileName");
+ while (<FCI>) {
+ $fileContents .= $_;
+ }
+ close(FCI);
+
+ if ($action eq "generate") {
+ generate_eis(\$fileContents, $fileName);
+ }
+
+ if ($action eq "fix-all") {
+ # Read in the ei "input" file
+ $line_number = 0;
+ my $errors = 0;
+ open(FCI, "<", $fileName . ".expert_add_info_input") || die("Couldn't open $fileName.expert_add_info_input");
+ while(my $line=<FCI>){
+ my @expert_item = split(/;|\n/, $line);
+
+ $line_number++;
+ $errors += verify_line(@expert_item);
+
+ push(@expert_list, \@expert_item);
+ }
+ close(FCI);
+
+ if ($errors > 0) {
+ print "Aborting conversion.\n";
+ exit(-1);
+ }
+
+ fix_expert_add_info_format(\$fileContents, $fileName);
+
+ # Write out the ei data
+ output_ei_data($fileName);
+
+ # Write out the changed version to a file
+ open(FCO, ">", $fileName . ".expert_add_info_format");
+ print FCO "$fileContents";
+ close(FCO);
+ }
+
+} # while
+
+exit $found_total;
+
+# ---------------------------------------------------------------------
+# Sanity check the data in the .proto_tree_input file
+sub verify_line {
+ my( @expert_item) = @_;
+ my $errors = 0;
+
+ #do some basic error checking of the file
+ if (($expert_item[0] eq "1") ||
+ ($expert_item[0] eq "2") ||
+ ($expert_item[0] eq "3") ||
+ ($expert_item[0] eq "4")) {
+ #expert info conversions
+ if (!($expert_item[2] =~ /^ei_/)) {
+ print "$line_number: Poorly formed ei_ variable ($expert_item[2])!\n";
+ $errors++;
+ }
+ } else {
+ print "$line_number: Bad conversion value!\n";
+ $errors++;
+ }
+
+ if ($expert_item[1] eq "1") {
+ if (!($expert_item[2] =~ /^ei_/)) {
+ print "$line_number: Poorly formed ei_ variable ($expert_item[2])!\n";
+ $errors++;
+ }
+ if (!exists($EXPERT_SEVERITY{$expert_item[4]})) {
+ print "$line_number: Expert severity value '$expert_item[5]' unknown!\n";
+ $errors++;
+ }
+ if (!exists($EXPERT_GROUPS{$expert_item[3]})) {
+ print "$line_number: Expert group value '$expert_item[4]' unknown!\n";
+ $errors++;
+ }
+
+ } elsif ($expert_item[1] ne "0") {
+ print "$line_number: Bad ei variable generation value!\n";
+ $errors++;
+ }
+
+ return $errors;
+}
+
+sub generate_eis {
+ my( $fileContentsRef, $fileName) = @_;
+ my @args;
+ my $num_items = 0;
+ my @temp;
+ my $str_temp;
+ my $pat;
+
+ $pat = qr /
+ (
+ (?:expert_add_info_format)\s* \(
+ (([^[\,;])*\,){4,}
+ [^;]*
+ \s* \) \s* ;
+ )
+ /xs;
+
+ while ($$fileContentsRef =~ / $pat /xgso) {
+
+ my @expert_item = (1, 1, "ei_name", "GROUP", "SEVERITY", "fieldfullname", "fieldabbrevname",
+ "pinfo", "item", "tvb", "offset", "length", "params");
+ my $arg_loop = 5;
+ my $str = "${1}\n";
+ $str =~ tr/\t\n\r/ /d;
+ $str =~ s/ \s+ / /xg;
+ #print "$fileName: $str\n";
+
+ @args = split(/,/, $str);
+ #printf "ARGS(%d): %s\n", scalar @args, join("# ", @args);
+ $args[0] =~ s/expert_add_info_format\s*\(\s*//;
+
+ $expert_item[7] = $args[0]; #pinfo
+ $expert_item[8] = trim($args[1]); #item
+ $expert_item[3] = trim($args[2]); #GROUP
+ $expert_item[4] = trim($args[3]); #SEVERITY
+ $expert_item[5] = trim($args[4]); #fieldfullname
+ $expert_item[5] =~ s/\"//;
+
+ #XXX - conditional?
+ $expert_item[5] =~ s/\"\s*\)\s*;$//;
+
+ #params
+ $expert_item[12] = "";
+ while ($arg_loop < scalar @args) {
+ $expert_item[12] .= trim($args[$arg_loop]);
+ if ($arg_loop+1 < scalar @args) {
+ $expert_item[12] .= ", ";
+ }
+ $arg_loop += 1;
+ }
+ $expert_item[12] =~ s/\s*\)\s*;$//;
+
+ #ei variable name
+ $expert_item[2] = sprintf("ei_%s_%s", $protabbrev, lc($expert_item[5]));
+ $expert_item[2] =~ s/\s+|-|:/_/g;
+
+ #field abbreviated name
+ $expert_item[6] = sprintf("%s.%s", $protabbrev, lc($expert_item[5]));
+ $expert_item[6] =~ s/\s+|-|:/_/g;
+
+ push(@expert_list, \@expert_item);
+
+ $num_items += 1;
+ }
+
+ if ($num_items > 0) {
+ open(FCO, ">", $fileName . ".expert_add_info_input");
+ for my $item (@expert_list) {
+ print FCO join(";", @{$item}), "\n";
+ }
+ close(FCO);
+ }
+}
+
+# ---------------------------------------------------------------------
+# Find all expert_add_info_format calls and replace them with the data
+# found in expert_list
+sub fix_expert_add_info_format {
+ my( $fileContentsRef, $fileName) = @_;
+ my $found = 0;
+ my $pat;
+
+ $pat = qr /
+ (
+ (?:expert_add_info_format)\s* \(
+ (([^[\,;])*\,){4,}
+ [^;]*
+ \s* \) \s* ;
+ )
+ /xs;
+
+ $$fileContentsRef =~ s/ $pat /patsub($found, $1)/xges;
+}
+
+# ---------------------------------------------------------------------
+# Format expert info functions with expert_list data
+sub patsub {
+ my $item_str;
+
+ #print $expert_list[$_[0]][2] . " = ";
+ #print $#{$expert_list[$_[0]]}+1;
+ #print "\n";
+
+ if ($expert_list[$_[0]][0] eq "1") {
+ $item_str = sprintf("expert_add_info(%s, %s, &%s);",
+ $expert_list[$_[0]][7], $expert_list[$_[0]][8], $expert_list[$_[0]][2]);
+ } elsif ($expert_list[$_[0]][0] eq "2") {
+ $item_str = sprintf("expert_add_info_format_text(%s, %s, &%s, \"%s\"",
+ $expert_list[$_[0]][7], $expert_list[$_[0]][8],
+ $expert_list[$_[0]][2], $expert_list[$_[0]][5]);
+ if (($#{$expert_list[$_[0]]}+1 > 12 ) && ($expert_list[$_[0]][12] ne "")) {
+ $item_str .= ", $expert_list[$_[0]][12]";
+ }
+ $item_str .= ");";
+ } elsif ($expert_list[$_[0]][0] eq "3") {
+ $item_str = sprintf("proto_tree_add_expert(%s, %s, &%s, %s, %s, %s);",
+ $expert_list[$_[0]][8], $expert_list[$_[0]][7],
+ $expert_list[$_[0]][2], $expert_list[$_[0]][9],
+ $expert_list[$_[0]][10], $expert_list[$_[0]][11]);
+ } elsif ($expert_list[$_[0]][0] eq "4") {
+ $item_str = sprintf("proto_tree_add_expert_format(%s, %s, &%s, %s, %s, %s, \"%s\"",
+ $expert_list[$_[0]][8], $expert_list[$_[0]][7], $expert_list[$_[0]][2],
+ $expert_list[$_[0]][9], $expert_list[$_[0]][10],
+ $expert_list[$_[0]][11], $expert_list[$_[0]][5]);
+ if (($#{$expert_list[$_[0]]}+1 > 12) && ($expert_list[$_[0]][12] ne "")) {
+ $item_str .= ", $expert_list[$_[0]][12]";
+ }
+ $item_str .= ");";
+ }
+
+ $_[0] += 1;
+
+ return $item_str;
+}
+
+# ---------------------------------------------------------------------
+# Output the ei variable declarations and expert array. For now, write them to a file.
+# XXX - Eventually find the right place to add it to the modified dissector file
+sub output_ei_data {
+ my( $fileName) = @_;
+ my %eis = ();
+ my $index;
+ my $key;
+
+ #add ei to hash table to prevent against (accidental) duplicates
+ for ($index=0;$index<@expert_list;$index++) {
+ if ($expert_list[$index][1] eq "1") {
+ $eis{$expert_list[$index][2]} = $expert_list[$index][2];
+ }
+ }
+
+ open(FCO, ">", $fileName . ".ei");
+
+ print FCO "/* Generated from convert_expert_add_info_format.pl */\n";
+
+ foreach $key (keys %eis) {
+ print FCO "static expert_field $key = EI_INIT;\n";
+ }
+ print FCO "\n\n";
+
+ if ($register ne "") {
+ print FCO " static ei_register_info ei[] = {\n";
+ }
+
+ %eis = ();
+ for ($index=0;$index<@expert_list;$index++) {
+ if ($expert_list[$index][1] eq "1") {
+ if (exists($eis{$expert_list[$index][2]})) {
+ print "duplicate ei entry '$expert_list[$index][2]' found! Aborting conversion.\n";
+ exit(-1);
+ }
+ $eis{$expert_list[$index][2]} = $expert_list[$index][2];
+
+ print FCO " { &$expert_list[$index][2], { \"$expert_list[$index][6]\", $expert_list[$index][3], ";
+ print FCO "$expert_list[$index][4], \"$expert_list[$index][5]\", EXPFILL }},\r\n";
+ }
+ }
+
+ if ($register ne "") {
+ print FCO " };\n\n\n";
+ print FCO " expert_module_t* expert_$protabbrev;\n\n";
+
+ print FCO " expert_$protabbrev = expert_register_protocol(proto_$protabbrev);\n";
+ print FCO " expert_register_field_array(expert_$protabbrev, ei, array_length(ei));\n\n";
+ }
+
+
+ close(FCO);
+}