mariadb/scripts/dheadgen.pl
Terje Rosten 5d4cfb30e5 BUG#25719975 SHEBANG HARD CODED AS /USR/BIN/PERL IN SCRIPTS, BREAKS ON FREEBSD
Use cmake variable to adjust shebang to platform.
2017-03-28 13:22:32 +02:00

332 lines
7.1 KiB
Perl

# Copyright (c) 2008, 2017, Oracle and/or its affiliates. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# * Neither the name of the above-listed copyright holders nor the names
# of its contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
# OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
# ident "@(#)dheadgen.pl 1.4 07/06/24 SMI"
#
# DTrace Header Generator
# -----------------------
#
# This script is meant to mimic the output of dtrace(1M) with the -h
# (headergen) flag on system that lack native support for DTrace. This script
# is intended to be integrated into projects that use DTrace's static tracing
# facilities (USDT), and invoked as part of the build process to have a
# common build process on all target systems. To facilitate this, this script
# is licensed under a BSD license. On system with native DTrace support, the
# dtrace(1M) command will be invoked to create the full header file; on other
# systems, this script will generated a stub header file.
#
# Normally, generated macros take the form PROVIDER_PROBENAME(). It may be
# desirable to customize the output of this script and of dtrace(1M) to
# tailor the precise macro name. To do this, edit the emit_dtrace() subroutine
# to pattern match for the lines you want to customize.
#
use strict;
my @lines;
my @tokens = ();
my $lineno = 0;
my $newline = 1;
my $eof = 0;
my $infile;
my $outfile;
my $force = 0;
sub emit_dtrace {
my ($line) = @_;
#
# Insert customization here. For example, if you want to change the
# name of the macros you may do something like this:
#
# $line =~ s/(\s)[A-Z]+_/\1TRACE_MOZILLA_/;
#
print $line;
}
#
# The remaining code deals with parsing D provider definitions and emitting
# the stub header file. There should be no need to edit this absent a bug.
#
#
# Emit the two relevant macros for each probe in the given provider:
# PROVIDER_PROBENAME(<args>)
# PROVIDER_PROBENAME_ENABLED() (0)
#
sub emit_provider {
my ($provname, @probes) = @_;
$provname = uc($provname);
foreach my $probe (@probes) {
my $probename = uc($$probe{'name'});
my $argc = $$probe{'argc'};
my $line;
$probename =~ s/__/_/g;
$line = "#define\t${provname}_${probename}(";
for (my $i = 0; $i < $argc; $i++) {
$line .= ($i == 0 ? '' : ', ');
$line .= "arg$i";
}
$line .= ")\n";
emit_dtrace($line);
$line = "#define\t${provname}_${probename}_ENABLED() (0)\n";
emit_dtrace($line);
}
emit_dtrace("\n");
}
sub emit_prologue {
my ($filename) = @_;
$filename =~ s/.*\///g;
$filename = uc($filename);
$filename =~ s/\./_/g;
emit_dtrace <<"EOF";
/*
* Generated by dheadgen(1).
*/
#ifndef\t_${filename}
#define\t_${filename}
#ifdef\t__cplusplus
extern "C" {
#endif
EOF
}
sub emit_epilogue {
my ($filename) = @_;
$filename =~ s/.*\///g;
$filename = uc($filename);
$filename =~ s/\./_/g;
emit_dtrace <<"EOF";
#ifdef __cplusplus
}
#endif
#endif /* _$filename */
EOF
}
#
# Get the next token from the file keeping track of the line number.
#
sub get_token {
my ($eof_ok) = @_;
my $tok;
while (1) {
while (scalar(@tokens) == 0) {
if (scalar(@lines) == 0) {
$eof = 1;
return if ($eof_ok);
die "expected more data at line $lineno";
}
$lineno++;
push(@tokens, split(/(\s+|\n|[(){},#;]|\/\*|\*\/)/,
shift(@lines)));
}
$tok = shift(@tokens);
next if ($tok eq '');
next if ($tok =~ /^[ \t]+$/);
return ($tok);
}
}
#
# Ignore newlines, comments and typedefs
#
sub next_token {
my ($eof_ok) = @_;
my $tok;
while (1) {
$tok = get_token($eof_ok);
return if ($eof_ok && $eof);
if ($tok eq "typedef" or $tok =~ /^#/) {
while (1) {
$tok = get_token(0);
last if ($tok eq "\n");
}
next;
} elsif ($tok eq '/*') {
while (get_token(0) ne '*/') {
next;
}
next;
} elsif ($tok eq "\n") {
next;
}
last;
}
return ($tok);
}
sub expect_token {
my ($t) = @_;
my $tok;
while (($tok = next_token(0)) eq "\n") {
next;
}
die "expected '$t' at line $lineno rather than '$tok'" if ($t ne $tok);
}
sub get_args {
expect_token('(');
my $tok = next_token(0);
my @args = ();
return (@args) if ($tok eq ')');
if ($tok eq 'void') {
expect_token(')');
return (@args);
}
my $arg = $tok;
while (1) {
$tok = next_token(0);
if ($tok eq ',' || $tok eq ')') {
push(@args, $arg);
$arg = '';
last if ($tok eq ')');
} else {
$arg = "$arg $tok";
}
}
return (@args);
}
sub usage {
die "usage: $0 [-f] <filename.d>\n";
}
usage() if (scalar(@ARGV) < 1);
if ($ARGV[0] eq '-f') {
usage() if (scalar(@ARGV < 2));
$force = 1;
shift;
}
$infile = $ARGV[0];
usage() if ($infile !~ /(.+)\.d$/);
#
# If the system has native support for DTrace, we'll use that binary instead.
#
if (-x '/usr/sbin/dtrace' && !$force) {
open(DTRACE, "-| /usr/sbin/dtrace -C -h -s $infile -o /dev/stdout")
or die "can't invoke dtrace(1M)";
while (<DTRACE>) {
emit_dtrace($_);
}
close(DTRACE);
exit(0);
}
emit_prologue($infile);
open(D, "< $infile") or die "couldn't open $infile";
@lines = <D>;
close(D);
while (1) {
my $nl = 0;
my $tok = next_token(1);
last if $eof;
if ($newline && $tok eq '#') {
while (1) {
$tok = get_token(0);
last if ($tok eq "\n");
}
$nl = 1;
} elsif ($tok eq "\n") {
$nl = 1;
} elsif ($tok eq 'provider') {
my $provname = next_token(0);
my @probes = ();
expect_token('{');
while (1) {
$tok = next_token(0);
if ($tok eq 'probe') {
my $probename = next_token(0);
my @args = get_args();
next while (next_token(0) ne ';');
push(@probes, {
'name' => $probename,
'argc' => scalar(@args)
});
} elsif ($tok eq '}') {
expect_token(';');
emit_provider($provname, @probes);
last;
}
}
} else {
die "syntax error at line $lineno near '$tok'\n";
}
$newline = $nl;
}
emit_epilogue($infile);
exit(0);