home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / perl / scripts-convex / lqi < prev    next >
Encoding:
Text File  |  1991-08-09  |  5.9 KB  |  299 lines

  1. #!/usr/local/bin/perl
  2. #
  3. # intersect.pl  -- find intersection of lq phrases
  4. #
  5. # Tom Christiansen 
  6. # tchrist@convex.com
  7. # 8 Aug 91
  8.  
  9. $match         = '-mh';
  10. $lqprog     = 'lqshow';
  11.  
  12. sub gensym { 'gensym' . ++$gensym; };
  13. *choices = &gensym;  # init list of lists
  14.  
  15. $SIG{'INTR'} = 'INTR';
  16.  
  17. sub usage {
  18.     select(STDERR);
  19.     print <<FINIS;
  20. usage: $0 [-CAB <num>] [-v] [-q]  [-d directory] [-n] [-l | -L | -R]  
  21.     [-mp | -mh | -ma] phrase ... [ [-a | -r] phrase ... ] ...
  22.  
  23. -a    add    set of phrases
  24. -r    remove set of phrases
  25.  
  26. -A    lines of context after
  27. -B    lines of context before
  28. -C    lines of context before and after
  29.  
  30. -n    sort numerically
  31.  
  32. -q    use lqkwik instead of lqshow
  33. -v    verbose mode
  34.  
  35. -l    list filenames
  36. -L    just list base names 
  37. -R    list raw lqshow triples
  38.  
  39. -d    set LQTEXTDIR
  40.  
  41. -m[pha] lqphrase match fuzziness
  42.         p    precise
  43.         h    heuristic
  44.         a    almost anything goes
  45.  
  46. FINIS
  47.  
  48.     exit 1;
  49.  
  50.  
  51. $sort = "sort +2 +0n +1n";
  52.  
  53. while ($_ = shift) {
  54.     if    (/^-m[pha]$/) { $match = $_; } 
  55.     elsif (/^-q$/)     { $lqprog = 'lqkwik'; } 
  56.     elsif (/^-n$/)     { $numsort++; }
  57.     elsif (/^-R$/)     { $listonly++; $rawlist++;}
  58.     elsif (/^-v$/)     { $verbose++; }
  59.     elsif (/^-a$/)     { *choices = &gensym; } # start a new list 
  60.     elsif (/^-r$/)     { *choices = &gensym; $nand[$gensym]++; } 
  61.     elsif (/^-d(.*)$/)     { $ENV{'LQTEXTDIR'} = $1 || shift; } 
  62.     elsif (/^-l$/i)     { $listonly = 1; $shortlist = /L/; }
  63.     elsif (/^-[AB](\d*)$/) { 
  64.     $hadwin++;
  65.     y/A-Z/a-z/; # gotta pass lower case
  66.     $lqshow_opts .= ' '. $_;
  67.     $lqshow_opts .= ' ' . shift unless $1;
  68.     } 
  69.     elsif (/^-C(\d*)$/) {
  70.     $hadwin++;
  71.     $context = $1 || shift;
  72.     $lqshow_opts = "-a $context -b $context";
  73.     }
  74.     elsif (/^-(.*)/) {
  75.     warn "unknown option: $1\n";
  76.     &usage;
  77.     } 
  78.     else { 
  79.     push(@choices, $_); 
  80.     } 
  81. }
  82.  
  83. &usage unless @choices;
  84. ### finally the interesting part...
  85.  
  86. unless ($hadwin) {
  87.     &getwin;
  88.     $context = int($rows - 3)/2;
  89.     $lqshow_opts = "-a $context -b $context";
  90.  
  91. $func = 'adding';
  92. &read_choices(*need, 'gensym1');
  93.  
  94. @fold = @fnew;
  95. %fold = %fnew;
  96.  
  97. for ($i = 2; $i <= $gensym; $i++) {
  98.     $func = $nand[$i] ? 'subtracting' : 'adding';
  99.     &read_choices(*want, "gensym$i");
  100.     &$func(*need, *want);
  101. }
  102.  
  103. $TMP = "/tmp/inter$$";
  104. if ($numsort) { 
  105.     # too hard to make sort do this
  106.     #print STDERR "sorting the hard way..." if $verbose;
  107.     $i = 0;
  108.     for (@need) {
  109.     $i++;
  110.     s/^ /0/; # convex printf is broken
  111.     ($block, $offset, $file) = split;
  112.     push(@block, $block);
  113.     push(@offset, $offset);
  114.     $file =~ /(\d+)$/;
  115.     push(@file, $1);
  116.     } 
  117.     open (TMP, ">$TMP") || die "can't write to $TMP: $!";
  118.     print TMP @need[sort bynum $[..$#need];
  119.     #print STDERR "done\n" if $verbose;
  120. } else { 
  121.     open (TMP, "| $sort > $TMP");
  122.     for (@need) {
  123.     s/^ /0/; # convex printf is broken
  124.     print TMP;
  125.     } 
  126. }
  127. unless (close TMP) { 
  128.     warn "can't close $TMP correctly";
  129.     &done;
  130. }
  131.  
  132. $count = @need;
  133.  
  134. unless ($verbose) {
  135.     local(%seen);
  136.     for (@need) {
  137.     $fcount++ unless $seen{(split)[2]}++;
  138.     } 
  139.     print STDERR "total of $count ", &plural('match', $count);
  140.     print STDERR " in $fcount ", &plural('file',$fcount), "\n";
  141.  
  142.  
  143. if ($listonly) {
  144.     open (TMP, "<$TMP");
  145.     if ($rawlist) {
  146.     print while <TMP>;
  147.     } else {
  148.     while (<TMP>) {
  149.         s/.*\s(\S+)$/$1/;
  150.         $shortlist && s#.*/##;
  151.         print unless $printed{$_}++;
  152.     } 
  153.     }
  154. } else {
  155.     warn "No matches found\n", &done unless $count;
  156.     $cmd = "$lqprog ";
  157.     $cmd .= "$lqshow_opts " if $lqprog =~ /show/;
  158.     $cmd .= "-f $TMP";
  159.     warn "running: $cmd\n" if $verbose;
  160.     system $cmd;
  161. }
  162.  
  163. &done;
  164.  
  165.  
  166. ##############################################################
  167.  
  168. sub read_choices {
  169.     local(*results, *targets) = @_;
  170.     local(@pretty) = ();
  171.  
  172.     local($fcount, $count) = (0,0);
  173.  
  174.     die "no targets" unless @targets;    
  175.  
  176.     @results = ();
  177.  
  178.     for (@targets) { push (@pretty, "\"$_\""); } 
  179.     local($pretty) = join(', ', @pretty);
  180.     print STDERR "$func $pretty: " if $verbose;
  181.  
  182.     # don't let the shell get even close to touching my targets
  183.     die "can't fork: $!" unless defined ($pid = open(KID, "-|"));
  184.     unless ($pid) {
  185.     exec 'lqphrase', $match, @targets;
  186.     die "can't exec lqphrase: $!" ;
  187.     }
  188.  
  189.     @fnew = ();
  190.     %fnew = ();
  191.  
  192.     for (<KID>) {
  193.     $count++;
  194.     $file = (split)[2];
  195.     $fcount++ unless $fnew{$file}++;
  196.     next if %fold && !$fold{$file};
  197.     push(@results, $_);
  198.     push(@fnew, $file);
  199.     } 
  200.     close KID;
  201.     print STDERR "$count in $fcount\n" if $verbose;
  202.     die "No matches for $pretty\n" unless $count;
  203.     die "lqphrase exited badly" if $?;
  204.  
  205. sub adding {
  206.     local($mfunc) = 'add2c';
  207.     &merge;
  208.  
  209. sub subtracting {
  210.     local($mfunc) = 'sub2c';
  211.     &merge;
  212.  
  213. sub merge {
  214.     local(*a, *b) = @_;
  215.     local($_);
  216.     local(@c, *f1, *f2, *f3);
  217.     local($file);
  218.  
  219.     print STDERR  "  intersection => " if $verbose;
  220.  
  221.     &$mfunc(*a, *fold);
  222.     &$mfunc(*b, *fnew);
  223.  
  224.     %fold = %f3;
  225.     @fold = @f3;
  226.  
  227.     local($count) = 0+@c;
  228.     local($fcount) = 0;
  229.     $fcount++ while each %fold;
  230.  
  231.     print STDERR " $count in $fcount\n" if $verbose;
  232.  
  233.     @a = @c;
  234.  
  235. sub plural {
  236.     local($_, $number) = @_;
  237.     local($end) = 's';
  238.     return $_ if $number == 1;
  239.     if (/[cst]h$/) { $end = 'es'; } 
  240.     "$_$end";
  241.  
  242. sub add2c {
  243.     local(*list, *set) = @_;
  244.     local($i);
  245.  
  246.     for ($i = 0; $i < @list; $i++) {
  247.     next unless $fnew{$set[$i]} && $fold{$set[$i]};
  248.     push(@c, $list[$i]);
  249.     push(@f3, $set[$i]);
  250.     $f3{$set[$i]}++;
  251.     } 
  252.  
  253. sub sub2c {
  254.     local(*list, *set) = @_;
  255.     local($i);
  256.  
  257.     for ($i = 0; $i < @list; $i++) {
  258.     next if $fnew{$set[$i]};
  259.     push(@c, $list[$i]);
  260.     push(@f3, $set[$i]);
  261.     $f3{$set[$i]}++;
  262.     } 
  263.  
  264. sub bynum {
  265.     $file[$a]   <=> $file[$b]  ||
  266.     $block[$a]  <=> $block[$b] ||
  267.     $offset[$a] <=> $offset[$b];
  268.  
  269.  
  270. sub INTR {
  271.     warn "\nInterrupt!\n";
  272.     &done;
  273.  
  274. sub done {
  275.     #unlink $TMP;
  276.     exit;
  277.  
  278. sub getwin {
  279.     $TIOCGWINSZ = 0x40087468;  # should be require sys/ioctl.pl
  280.     if (ioctl(STDOUT, $TIOCGWINSZ, $winsize)) {
  281.         ($rows, $cols, $xpixel, $ypixel) = unpack('S4', $winsize);
  282.     } else {
  283.         $cols = $ENV{TERMCAP} =~ /:co#(\d+)/ ? $1 : 80;
  284.     }
  285. }
  286.