1
2##e2ctags.pl
3##Convert an Emacs-style TAGS file to a standard ctags file.
4##Runs in a single pass over the TAGS file and keeps the first
5##tag entry found, and the file name and line number the tag can
6##be found on.
7##Then it opens all relevant files and builds the regular expression
8##for ctags.
9##Run over a few test files and compared with a real ctags file shows
10##only extra tags in the translated file, which probably won't hurt
11##vi.
12##
13
14use strict;
15
16my $filename;
17my ($tag,$line_no,$line);
18my %tags = ();
19my %filetags = ();
20my %files = ();
21my @lines = ();
22
23while (<>) {
24  if ($_ eq "\x0C\n") {
25    ##Grab next line and parse it for the filename
26    $_ = <>;
27    chomp;
28    s/,\d+$//;
29    $filename = $_;
30    ++$files{$filename};
31    next;
32  }
33  ##Figure out how many records in this line and
34  ##extract the tag name and the line that it is found on
35  next if /struct/;
36  if (/\x01/) {
37    ($tag,$line_no) = /\x7F(\w+)\x01(\d+)/;
38  }
39  else {
40    tr/(//d;
41    ($tag,$line_no) = /(\w+)\s*\x7F(\d+),/;
42  }
43  next unless $tag;
44  ##Take only the first entry per tag
45  next if defined($tags{$tag});
46  $tags{$tag}{FILE} = $filename;
47  $tags{$tag}{LINE_NO} = $line_no;
48  push @{$filetags{$filename}}, $tag;
49}
50
51foreach $filename (keys %files) {
52  open FILE, $filename or die "Couldn't open $filename: $!\n";
53  @lines = <FILE>;
54  close FILE;
55  chomp @lines;
56  foreach $tag ( @{$filetags{$filename}} ) {
57    $line = $lines[$tags{$tag}{LINE_NO}-1];
58    if (length($line) >= 50) {
59      $line = substr($line,0,50);
60    }
61    else {
62      $line .= '$';
63    }
64    $line =~ s#\\#\\\\#;
65    $tags{$tag}{LINE} = join '', '/^',$line,'/';
66  }
67}
68
69foreach $tag ( sort keys %tags ) {
70  print "$tag\t$tags{$tag}{FILE}\t$tags{$tag}{LINE}\n";
71}
72