Crombie Tools
feedpanda.pl
Go to the documentation of this file.
1 #! /usr/bin/env perl
2 
3 use strict;
4 use warnings;
5 
6 use Data::Dumper;
7 
8 # Check arguments and print help function if needed
9 sub print_use {
10  print "Usage: $0 PANDADEF SOURCE SOURCE ... OUTPUTHEAD\n\n";
11  print "PANDADEF Must be a PandaTree def file\n";
12  print "SOURCE Source file(s) that you would like to analyze\n";
13  print "OUTPUTHEAD Place where you would like to put the output header\n";
14  return "\nYou did something wrong with arguments\n";
15 }
16 # Check presence of arguments
17 my $out_file = pop @ARGV or die print_use;
18 if (not @ARGV) {
19  die print_use;
20 }
21 
22 # Check that each source file exists
23 foreach my $fname (@ARGV) {
24  if (not -e $fname) {
25  print "File $fname does not exist!\n\n";
26  die print_use;
27  }
28 }
29 
30 # Check first line of header
31 if (-e $out_file) {
32  open (my $handle, '<', $out_file);
33  chomp (my $first = <$handle>);
34  close $handle;
35  if ($first ne '#ifndef CROMBIE_FEEDPANDA_H') {
36  print "First line of $out_file looks suspicious! I don't want to overwrite:\n";
37  print "$first\n";
38  die print_use;
39  }
40 }
41 
42 # Location of Panda definitions
43 my $def_file = shift @ARGV;
44 my @source;
45 my @branches = ('triggers');
46 my $include_dir = '';
47 my %read_files;
48 
49 sub open_src {
50  my @output;
51  open(my $handle, '<', shift);
52  for (<$handle>) {
53  if (/#include .([\w\/]+\.h)/) {
54  if (-f "${include_dir}/$1") {
55  if (1 < ($read_files{$1} += 1)) {
56  next;
57  }
58  push @output, open_src("${include_dir}/$1");
59  }
60  }
61  else {
62  push @output, $_;
63  }
64  }
65  close $handle;
66  return @output;
67 }
68 
69 for (@ARGV) {
70  if (-d $_) {
71  $include_dir = $_;
72  next;
73  }
74 
75  push @source, open_src($_);
76 }
77 
78 # Filter to get the members called
79 chomp(@source = grep { /\.|(->)|(::)/ } @source);
80 
81 for (@source) {
82  # Don't match with function members of event
83  while (/\be(vent)?(\.|->)(\w+)(?!\w*\()/g) {
84  push @branches, $3;
85  }
86  # Also match offsets
87  while (/\&panda::Event::(\w+)/g) {
88  push @branches, $1;
89  }
90 }
91 
92 sub uniq_sort {
93  my %seen;
94  return sort(grep {! $seen{$_}++ } @_);
95 }
96 
97 # Get unique branches from first pass
98 @branches = uniq_sort @branches;
99 
100 # Now check def file for references to load
101 open (my $handle, '<', $def_file);
102 chomp (my @pandadef = grep { /->/ } <$handle>);
103 close $handle;
104 my %poss_refs;
105 my @last_branches;
106 while (@last_branches != @branches) {
107  @last_branches = uniq_sort @branches;
108  # Fill more branches
109  foreach my $branch (@branches) {
110  foreach my $line (@pandadef) {
111  if ($line =~ /$branch\.(\w+)->(\w+)/) {
112  push @{$poss_refs{$1}}, $2;
113  }
114  }
115  }
116  foreach my $key (keys %poss_refs) {
117  @{$poss_refs{$key}} = uniq_sort @{$poss_refs{$key}};
118  my @new_branches = grep { /(\.|->)$key/ } @source;
119  if (@new_branches) {
120  push @branches, @{$poss_refs{$key}};
121  }
122  }
123  @branches = uniq_sort @branches;
124 }
125 
126 # Now we have our branches. Time to write a header file!
127 open (my $out, '>', $out_file);
128 
129 print $out <<HEAD;
130 #ifndef CROMBIE_FEEDPANDA_H
131 #define CROMBIE_FEEDPANDA_H 1
132 
133 #include "TTree.h"
134 
135 #include "PandaTree/Objects/interface/Event.h"
136 
137 namespace crombie {
138  void feedpanda(panda::Event& event, TTree* input) {
139  event.setStatus(*input, {"!*"});
140  event.setAddress(*input,
141 HEAD
142 
143 print $out ' {"' . join("\",\n \"", @branches) . '"';
144 
145 print $out <<HEAD;
146  });
147  }
148 }
149 
150 #endif
151 HEAD
152 
153 close $out;