script to generate ctags from etags
Colin Kuskie [Wed, 20 Jan 1999 16:29:35 +0000 (08:29 -0800)]
Message-ID: <Pine.GSO.3.96.990120160519.5755Q-100000@pdxue150.cadence.com>
Subject: [PATCH 5.005_54] adding ctags to the source, FAQ, make

p4raw-id: //depot/perl@2902

Makefile.SH
emacs/e2ctags.pl [new file with mode: 0644]
pod/perlfaq3.pod

index 30e5447..42377d3 100644 (file)
@@ -646,6 +646,9 @@ emacs/cperl-mode.elc: emacs/cperl-mode.el
 
 etags: emacs/cperl-mode.elc
        sh emacs/ptags
+       perl emacs/e2ctags.pl TAGS > tags
+
+ctags: etags
 
 # AUTOMATICALLY GENERATED MAKE DEPENDENCIES--PUT NOTHING BELOW THIS LINE
 # If this runs make out of memory, delete /usr/include lines.
diff --git a/emacs/e2ctags.pl b/emacs/e2ctags.pl
new file mode 100644 (file)
index 0000000..ef7a8d8
--- /dev/null
@@ -0,0 +1,75 @@
+
+##e2ctags.pl
+##Convert an Emacs-style TAGS file to a standard ctags file.
+##Runs in a single pass over the TAGS file and keeps the first
+##tag entry found, and the file name and line number the tag can
+##be found on.
+##Then it opens all relevant files and builds the regular expression
+##for ctags.
+##Run over a few test files and compared with a real ctags file shows
+##only extra tags in the translated file, which probably won't hurt
+##vi.
+##
+
+use strict;
+
+my $filename;
+my ($tag,$line_no,$line);
+my %tags = ();
+my %files = ();
+my @lines = ();
+
+while (<>) {
+  if ($_ eq "\x0C\n") {
+    ##Grab next line and parse it for the filename
+    $_ = <>;
+    chomp;
+    s/,\d+$//;
+    $filename = $_;
+    ++$files{$filename};
+    next;
+  }
+  ##Figure out how many records in this line and
+  ##extract the tag name and the line that it is found on
+  next if /struct/;
+  if (/\x01/) {
+    ($tag,$line_no) = /\x7F(\w+)\x01(\d+)/;
+    next unless $tag;
+    ##Take only the first entry per tag
+    next if defined($tags{$tag});
+    $tags{$tag}{FILE} = $filename;
+    $tags{$tag}{LINE_NO} = $line_no;
+  }
+  else {
+    tr/(//d;
+    ($tag,$line_no) = /(\w+)\s*\x7F(\d+),/;
+    next unless $tag;
+    ##Take only the first entry per tag
+    next if defined($tags{$tag});
+    $tags{$tag}{FILE} = $filename;
+    $tags{$tag}{LINE_NO} = $line_no;
+  }
+}
+
+foreach $filename (keys %files) {
+  open FILE, $filename or die "Couldn't open $filename: $!\n";
+  @lines = <FILE>;
+  close FILE;
+  chomp @lines;
+  foreach $tag ( keys %tags ) {
+    next unless $filename eq $tags{$tag}{FILE};
+    $line = $lines[$tags{$tag}{LINE_NO}-1];
+    if (length($line) >= 50) {
+      $line = substr($line,0,50);
+    }
+    else {
+      $line .= '$';
+    }
+    $line =~ s#\\#\\\\#;
+    $tags{$tag}{LINE} = join '', '/^',$line,'/';
+  }
+}
+
+foreach $tag ( sort keys %tags ) {
+  print "$tag\t$tags{$tag}{FILE}\t$tags{$tag}{LINE}\n";
+}
index 28e64ec..4c38016 100644 (file)
@@ -147,9 +147,16 @@ results are not particularly satisfying for sophisticated code.
 The a2ps at http://www.infres.enst.fr/~demaille/a2ps/ does lots of things
 related to generating nicely printed output of documents.
 
-=head2 Is there a ctags for Perl?
+=head2 Is there a etags/ctags for perl?
 
-There's a simple one at
+With respect to the source code for the Perl interpreter, yes.
+There has been support for etags in the source for a long time.
+Ctags was introduced in v5.005_54 (and probably 5.005_03).
+After building perl, type 'make etags' or 'make ctags' and both
+sets of tag files will be built.
+
+Now, if you're looking to build a tag file for perl code, then there's
+a simple one at
 http://www.perl.com/CPAN/authors/id/TOMC/scripts/ptags.gz which may do
 the trick.  And if not, it's easy to hack into what you want.