wireshark/epan/wslua/make-taps.pl
Silvio Gissi 59add43eec Lua: Add "tonumber" method to NSTime
Absolute and Relative time fields could not be converted to seconds
without converting to string and parsing to number.

Fixed conversion in generated code that was subject to precision loss

Usage:
f=Field.new("frame.delta_time")
delta=f().value:tonumber()

Change-Id: I6ef91c6238a6c2ed9adf6cae03f8913f0a09332e
Reviewed-on: https://code.wireshark.org/review/22316
Petri-Dish: Stig Bjørlykke <stig@bjorlykke.org>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Guy Harris <guy@alum.mit.edu>
2017-06-21 23:50:27 +00:00

235 lines
5.7 KiB
Perl
Executable file

#!/usr/bin/perl
#
# make-taps.pl
# Extract structs from C headers to generate a function that
# pushes a lua table into the stack containing the elements of
# the struct.
#
# (c) 2006 Luis E. Garcia Ontanon <luis@ontanon.org>
#
# Wireshark - Network traffic analyzer
# By Gerald Combs <gerald@wireshark.org>
# Copyright 2006 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;
my %types = %{{
'gchar[]' => 'lua_pushstring(L,(const char*)v->STR);',
'gchar*' => 'lua_pushstring(L,(const char*)v->STR);',
'guint' => 'lua_pushnumber(L,(lua_Number)v->STR);',
'guint8' => 'lua_pushnumber(L,(lua_Number)v->STR);',
'guint16' => 'lua_pushnumber(L,(lua_Number)v->STR);',
'guint32' => 'lua_pushnumber(L,(lua_Number)v->STR);',
'gint' => 'lua_pushnumber(L,(lua_Number)v->STR);',
'gint8' => 'lua_pushnumber(L,(lua_Number)v->STR);',
'gint16' => 'lua_pushnumber(L,(lua_Number)v->STR);',
'gint32' => 'lua_pushnumber(L,(lua_Number)v->STR);',
'gboolean' => 'lua_pushboolean(L,(int)v->STR);',
'address' => '{ Address a = (Address)g_malloc(sizeof(address)); copy_address(a, &(v->STR)); pushAddress(L,a); }',
'address*' => '{ Address a = (Address)g_malloc(sizeof(address)); copy_address(a, v->STR); pushAddress(L,a); }',
'int' => 'lua_pushnumber(L,(lua_Number)v->STR);',
'nstime_t' => 'lua_pushnumber(L,(lua_Number)nstime_to_sec(&(v->STR)));',
'nstime_t*' => 'lua_pushnumber(L,(lua_Number)nstime_to_sec(v->STR));'
}};
my %comments = %{{
'gchar[]' => 'string',
'gchar*' => 'string',
'guint' => 'number',
'guint8' => 'number',
'guint16' => 'number',
'guint32' => 'number',
'gint' => 'number',
'gint8' => 'number',
'gint16' => 'number',
'gint32' => 'number',
'gboolean' => 'boolean',
'address' => 'Address',
'address*' => 'Address',
'int' => 'number',
'nstime_t' => 'number (seconds, since 1-1-1970 if absolute)',
'nstime_t*' => 'number (seconds, since 1-1-1970 if absolute)',
}};
my %functs = ();
my %enums = ();
sub dotap {
my ($tname,$fname,$sname,@enums) = @_;
my $buf = '';
open FILE, "< $fname";
while(<FILE>) {
$buf .= $_;
}
close FILE;
$buf =~ s@/\*.*?\*/@@;
for my $ename (@enums) {
$enums{$ename} = [];
my $a = $enums{$ename};
my $enumre = "typedef\\s+enum[^{]*{([^}]*)}[\\s\\n]*" . ${ename} . "[\\s\\n]*;";
if ($buf =~ s/$enumre//ms ) {
$types{$ename} = "lua_pushnumber(L,(lua_Number)v->STR); /* $ename */";
my $ebody = $1;
$ebody =~ s/\s+//msg;
$comments{$ename} = "$ename: { $ebody }";
$comments{$ename} =~ s/,/|/g;
for (split /,/, $ebody) {
push @{$a}, $_;
}
}
}
my $re = "typedef\\s+struct.*?{([^}]*)}[\\s\\n]*($sname)[\\s\\n]*;";
my $body;
while ($buf =~ s/$re//ms) {
$body = $1;
}
die "could not find typedef $sname in $fname" if not defined $body and $sname ne "void";
my %elems = ();
while($body =~ s/\s*(.*?)([\w\d_]+)\s*\[\s*\d+\s*\]\s*;//) {
my ($k,$v) = ($2,$1 . "[]");
$v =~ s/const //g;
$v =~ s/\s+//g;
$elems{$k} = $v;
}
while($body =~ s/\s*(.*?)([\w\d_]+)\s*;//) {
my ($k,$v) = ($2,$1);
$v =~ s/const //g;
$v =~ s/\s+//g;
$elems{$k} = $v;
}
my $code = "static void wslua_${tname}_to_table(lua_State* L, const void* p) {\n\tconst $sname* v;\n\n\tv = (const $sname*)p;\n\tlua_newtable(L);\n\n";
my $doc = "Tap: $tname\n";
for my $n (sort keys %elems) {
my $fmt = $types{$elems{$n}};
my $lua_type;
if ($fmt) {
$code .= "\tlua_pushstring(L,\"$n\");\n\t";
($lua_type = $fmt) =~ s/\bSTR\b/$n/g;
$code .= $lua_type;
$code .= "\n\tlua_settable(L,-3);\n";
$doc .= "\t$n: $comments{$elems{$n}}\n";
}
}
$code .= "}\n\n";
$doc .= "\n";
$functs{$tname} = "wslua_${tname}_to_table";
return ($code,$doc);
}
open TAPSFILE, "< $ARGV[0]";
open CFILE, "> $ARGV[1]";
open DOCFILE, "> $ARGV[2]";
my $srcdir = $ARGV[3];
print CFILE <<"HEADER";
/* This file is autogenerated from ./taps by ./make-taps.pl */
/* DO NOT EDIT! */
#include "config.h"
#include "wslua.h"
#include <wsutil/nstime.h>
HEADER
print DOCFILE "\n";
while (<TAPSFILE>) {
s@#.*@@;
next if /^\s*$/;
my ($tname,$fname,$sname,@enums) = split /\s+/;
my ($c,$doc) = dotap($tname,$srcdir . "/" . $fname,$sname,@enums);
print CFILE "#include \"$fname\"\n";
print CFILE $c;
print DOCFILE $doc;
}
print CFILE <<"TBLHDR";
static tappable_t tappables[] = {
TBLHDR
for my $tname (sort keys %functs) {
print CFILE <<"TBLELEM";
{"$tname", $functs{$tname} },
TBLELEM
}
print CFILE <<"TBLFTR";
{"frame",NULL},
{NULL,NULL}
};
int wslua_set_tap_enums(lua_State* L) {
TBLFTR
for my $ename (sort keys %enums) {
print CFILE "\n\t/*\n\t * $ename\n\t */\n\tlua_newtable(L);\n";
for my $a (@{$enums{$ename}}) {
print CFILE <<"ENUMELEM";
lua_pushnumber(L,(lua_Number)$a);
lua_setglobal(L,"$a");
lua_pushnumber(L,(lua_Number)$a);
lua_pushstring(L,"$a");
lua_settable(L,-3);
ENUMELEM
}
print CFILE "\tlua_setglobal(L,\"$ename\");\n";
}
print CFILE <<"TAIL";
return 0;
}
tap_extractor_t wslua_get_tap_extractor(const gchar* name) {
tappable_t* t;
for(t = tappables; t->name; t++ ) {
if (g_str_equal(t->name,name)) return t->extractor;
}
return NULL;
}
TAIL
exit 0;