#!/usr/bin/perl -w -- # -*-Perl-*- use strict; use Getopt::Long; use File::Basename; my $help_message = "build a tags sqlite database from a load built with clearmake.\n Usage: $0 \t --ifile input file (a load built with clearmake) \t --ofile output (db file) \t --help print this help message \n"; my $ifile; my $input; my $output; my $ofile; my $help; my $debug; GetOptions ( "ifile=s" => \$ifile, "ofile=s" => \$ofile, "debug+" => \$debug, "help+" => \$help); if (defined ($help)) { print $help_message; exit(0); } if (!defined($ifile)) { print $help_message; exit(1); } if (!defined($ofile)) { print $help_message; exit(2); } -r $ifile || die "can't open $ifile"; -r $ofile && die "$ofile already exist! remove first!"; die "not in a view!" if (`cleartool pwv -short` eq "** NONE **\n"); die "$ifile is not a load built with clearmake!" unless (`cleartool desc -fmt '%m' $ifile` eq 'derived object'); my $tags_debug = (defined $debug) ? " tee /tmp/debug.tags | " : ""; my $cr_debug = (defined $debug) ? " tee /tmp/debug.cr | " : ""; my $sql_debug = (defined $debug) ? " tee /tmp/debug.sql | " : ""; open TAG, "cleartool catcr -union -element_only -name '*.[cxhs]*' -short -nxname $ifile | " . $cr_debug . " ctags --filter=yes --sort=no -n --c-kinds=+p --c++-kinds=+p | " . $tags_debug ; open SQL, "| " . $sql_debug . " sqlite $ofile"; my %files; my %idents; my $ident_num = 0; my $file_num = 0; my @tag; while () { if (/\A([A-Za-z0-9_~].*)\t(\/\S+)\t(\d+);\"\t(\w)(\t(class|struct|enum|union|namespace):(\S+))?/) { my $ident_no = $idents{$1}; unless (defined($ident_no)) { $ident_no = $ident_num; $idents{$1} = $ident_no; $ident_num++; } my $file_no; my $dir_no; { my $fullpath = $2; my $view = ''; if ($fullpath =~ /\A(\/view\/\w+)(\/.+)\Z/) { $view = $1; $fullpath = $2; } my ($name, $path, $ignored) = File::Basename::fileparse($fullpath); $file_no = $files{$name}; $dir_no = $files{$path}; unless (defined($file_no)) { $file_no = $file_num; $files{$name} = $file_no; $file_num++; } unless (defined($dir_no)) { $dir_no = $file_num; $files{$path} = $dir_no; $file_num++; } } my $scope = undef; if (defined ($7)) { $scope = $idents{$7}; if (!defined($scope)) { $scope = $ident_num; $idents{$7} = $scope; $ident_num++; } } $tag[++$#tag] = [$ident_no, $file_no, $dir_no, $3, $4, defined($scope) ? $scope : -1]; } else { chomp $_; print "WARNING: skip <$_>\n"; } } close TAG; die "No identifier found!" unless ($ident_num > 0); die "No tag found!" unless ($#tag > 0); die "No file found!" unless ($file_num > 0); print SQL "PRAGMA synchronous = OFF;\n"; print SQL "PRAGMA default_synchronous = OFF;\n"; #print SQL "PRAGMA temp_store = MEMORY;\n"; print SQL "PRAGMA count_changes = OFF;\n"; print SQL "begin;\n"; print SQL "create table idents(symname TEXT UNIQUE on conflict abort,symid INTEGER PRIMARY KEY on conflict abort);\n"; print SQL "create table files(fileid INTEGER PRIMARY KEY on conflict abort, filename TEXT UNIQUE on conflict abort);\n"; print SQL "create table tags(sym INTEGER,file INTEGER, path INTEGER, line INTEGER, syntax TEXT, scope INTEGER, unique(sym,file,path,line,syntax,scope));\n"; print SQL "insert or abort into idents values(NULL,-1);\n"; my ($name, $idx); while (($name, $idx) = each %idents) { print SQL "insert or abort into idents values('" . $name . "'," . $idx . ");\n"; } while (($name, $idx) = each %files) { print SQL 'insert or abort into files values(' . $idx . ",'" . $name . "');\n"; } foreach my $i (@tag) { print SQL 'insert or ignore into tags values(' . $i->[0] . ','. $i->[1] . ','. $i->[2] . ',' . $i->[3] . ",'" . $i->[4] . "',". $i->[5] . ");\n"; } print SQL "create index idents_symname on idents(symname);\n"; print SQL "create index files_filename on files(filename);\n"; print SQL "create index tags_sym on tags(sym);\n"; print SQL "commit;\n"; close SQL;