#!/usr/bin/perl -w # # idlwave_catalog # # Program to create IDLWAVE library catalogs. # # (c) 2002-2004 J.D. Smith # # Scans all IDL ".pro" files at the current level and recursively in # all directories beneath it, compiling a catalog of information for # each directory with any routines found, stored in a file named # ".idlwave_catalog". Any such "library catalogs" on the IDL path # will be automatically loaded into IDLWAVE. # # Usage: idlwave_catalog [-l] [-v] [-d] [-s] [-f] [-x PATTERN] [-h] libname # libname - Unique name of the catalog (4 or more alphanumeric # characters -- only 10 will be shown in routine info). # -l - Scan local directory only, otherwise recursively # catalog all directories at or beneath this one. # -v - Print verbose information. # -d - Instead of scanning, delete all .idlwave_catalog files # here or below. # -s - Be silent. # -f - Force overwriting any catalogs found with a different # library name. # -x - Skip directories matching the passed pattern # -h - Print this usage. # # You can arrange to have this script run automatically to update # libraries which change frequently. The name will be used to refer # to the routines collectively, so make it unique and descriptive # (without spaces). E.g. "NasaLib". A file named .idlwave_catalog # will be created in each directory with ".pro" routine files. # # $Id: idlwave_catalog,v 1.5 2004/10/13 20:34:07 jdsmith Exp $ use Getopt::Std; $opt_l=$opt_s=$opt_f=$opt_v=$opt_d=$opt_h=0; getopt('x'); $opt_v=0 if $opt_s; usage() if $opt_h; unless ($opt_d) { $libname=shift or usage(); if (length($libname)<=3 or ($libname=~tr/A-Za-z0-9_//c)) { die "LibName must be alphanumeric, >3 characters, and contains no spaces.\n" } } $cat=".idlwave_catalog"; unless ($opt_l) { use File::Find; find(sub{ if (/\Q$cat\E$/) { if ($opt_d) { if (unlink $_) { print "Removing catalog $File::Find::name\n" if $opt_v; } else { warn "Can't remove catalog $File::Find::name: $!\n" unless $opt_s; } } else { $dirs{$File::Find::dir}{cat}=libname($_); } return; } return if $opt_d; return unless -f and /\.pro$/i; parsefile($File::Find::dir, $_); }, '.'); } else { #Just process the local directory opendir(DIR,".") || die "Can't open this directory: $!"; if (-f $cat) { if ($opt_d) { if (unlink $cat) { print "Removing catalog $cat\n" if $opt_v; } else { warn "Can't remove catalog $cat: $!\n" unless $opt_s; } } else { $dirs{"."}{cat}=libname($cat); } } unless($opt_d) { foreach (grep {-f and /\.pro$/i} readdir(DIR)) { parsefile(".",$_); } } closedir DIR; } exit if $opt_d; #Nothing more to do foreach $dir (keys %dirs) { if ($opt_x and $dir=~/$opt_x/) { print "Skipping $dir\n" if $opt_v; next; } next if !defined($dirs{$dir}{pro}) || !$dirs{$dir}{pro}; print "Cataloging $dir\n" if $opt_v; if (exists $dirs{$dir}{cat} && $dirs{$dir}{cat} ne $libname) { if ($opt_f) { warn "Overwriting existing \"$dirs{$dir}{cat}\" catalog in " . ($dir eq "."?"this directory":$dir) . ".\n" unless $opt_s; } else { warn "Skipping existing \"$dirs{$dir}{cat}\" catalog in " . ($dir eq "."?"this directory":$dir) . " (-f overrides).\n" unless $opt_s; next; } } unless (open CATALOG, ">$dir/$cat") { warn "Can't open catalog file $dir/$cat for writing... skipping\n"; next; } # $time=localtime(); print CATALOG <) { next unless /^[ \t]*(pro|function)[ \t]+(?:([a-zA-Z0-9\$_]+)::)?([a-zA-Z0-9\$_]+)/i; ($type,$class,$name)=(lc($1) eq "pro"?"pro":"fun",$2,$3); $call=""; @kwds=@args=(); while (/[ \t]*\$\s*(;.*)?[\r\n]+/) { # Continuations $call.=$`; $_=; while (/^\s*(;.*)?[\r\n]+/) {$_=} #skip blank or comment lines } s/\s*(;.*)?[\r\n]+//; $call.=$_; while($call=~/,\s*([a-zA-Z][a-zA-Z0-9\$_]*|(?:_ref)?_extra)\s*(=)?/gi) { if ($2) { push @kwds, $1; } else { push @args, $1; } } $is_func=$type eq "fun"; @kwds=sort {lc($a) cmp lc($b)} @kwds; # Name type class push @{$dirs{$dir}{pro}}, qq{("$name" $type } . ($class?qq("$class"):"nil") . # Source (source-type file dir library-name) qq< (lib "$file" nil "$libname") > . #Calling sequence '"' . ($is_func?"Result = ":"") . ($class?'Obj ->[%s::]':"") . '%s' . # Argument list (@args?($is_func?"(":", ") . join(", ",@args) . ($is_func?')':""):"") . '"' . # Keywords ' (nil' . (@kwds?' ("'.join('") ("', @kwds).'")':"") . "))"; } close FILE; return } sub libname { my $file=shift; open FILE, $file; while () { return $1 if /\(setq idlwave-library-catalog-libname "([^"]+)"\)/; } ""; } sub usage { print <