home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD2.bin / bbs / gnu / ispell-4.0-src.lha / ispell-4.0 / look.c < prev    next >
C/C++ Source or Header  |  1994-02-24  |  7KB  |  388 lines

  1. /* Copyright (C) 1990, 1993 Free Software Foundation, Inc.
  2.  
  3.    This file is part of GNU ISPELL.
  4.  
  5.    This program is free software; you can redistribute it and/or modify
  6.    it under the terms of the GNU General Public License as published by
  7.    the Free Software Foundation; either version 2, or (at your option)
  8.    any later version.
  9.  
  10.    This program is distributed in the hope that it will be useful,
  11.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.    GNU General Public License for more details.
  14.  
  15.    You should have received a copy of the GNU General Public License
  16.    along with this program; if not, write to the Free Software
  17.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19.  
  20. /* lookup a word in a dictionary
  21.  
  22.    the dictionary must be sorted with one lower case word
  23.    per line.  all lines that begin with the argument
  24.    are printed */
  25.  
  26. #include <stdio.h>
  27. #include <ctype.h>
  28. #include <sys/types.h>
  29. #include <sys/stat.h>
  30.  
  31. #ifdef HAVE_MALLOC_H
  32. #include <malloc.h>
  33. #endif
  34.  
  35. #include "getopt.h"
  36. #include "ispell.h"
  37.  
  38. #ifdef __STDC__
  39. static int contains_meta (char *);
  40. void dogrep (char *, char *);
  41. #else
  42. extern int contains_meta ();
  43. extern void dogrep ();
  44. #endif
  45.  
  46. #ifndef _tolower
  47. #define _tolower tolower
  48. #endif
  49.  
  50. #ifdef DICT_LIB
  51. char *dict_lib = DICT_LIB;
  52. char *dict_name = "ispell.words";
  53. #else
  54. char *dict_lib = "/gnu/dict";
  55. char *dict_name = "words";
  56. #endif
  57.  
  58. /* not dictionary, no fold */
  59. int
  60. cmp00 (line, word)
  61.   unsigned char *line, *word;
  62. {
  63.   int x;
  64.   while (1)
  65.     {
  66.       if (*word == 0)
  67.     return (0);
  68.       if (*line == 0)
  69.     return (1);
  70.       x = *line++ - *word++;
  71.       if (x != 0)
  72.     return (x);
  73.     }
  74. }
  75.  
  76. /* not dictionary, fold */
  77. int
  78. cmp01 (line, word)
  79.   unsigned char *line, *word;
  80. {
  81.   int x;
  82.   while (1)
  83.     {
  84.       if (*word == 0)
  85.     return (0);
  86.       if (*line == 0)
  87.     return (1);
  88.       if (isupper (*line))
  89.     x = _tolower (*line) - *word;
  90.       else
  91.     x = *line - *word;
  92.       if (x != 0)
  93.     return (x);
  94.       line++;
  95.       word++;
  96.     }
  97. }
  98.  
  99. /* dictionary, no fold */
  100. int
  101. cmp10 (line, word)
  102.   char *line, *word;
  103. {
  104.   int x;
  105.   while (1)
  106.     {
  107.       if (*word == 0)
  108.     return (0);
  109.       if (*line == 0)
  110.     return (1);
  111.       if (!isalpha (*line) && !isdigit (*line) && !isspace (*line))
  112.     {
  113.       line++;
  114.       continue;
  115.     }
  116.       x = *line++ - *word++;
  117.       if (x != 0)
  118.     return (x);
  119.     }
  120. }
  121.  
  122. /* dictionary, fold */
  123. int
  124. cmp11 (line, word)
  125.   char *line, *word;
  126. {
  127.   int x;
  128.   while (1)
  129.     {
  130.       if (*word == 0)
  131.     return (0);
  132.       if (*line == 0)
  133.     return (1);
  134.       if (!isalpha (*line) && !isdigit (*line) && !isspace (*line))
  135.     {
  136.       line++;
  137.       continue;
  138.     }
  139.       if (isupper (*line))
  140.     x = _tolower (*line) - *word;
  141.       else
  142.     x = *line - *word;
  143.       if (x != 0)
  144.     return (x);
  145.       line++;
  146.       word++;
  147.     }
  148. }
  149.  
  150. void
  151. usage ()
  152. {
  153. #define P(s) fprintf (stderr, s)
  154.   P ("usage: look [-dfr] string [file]\n");
  155.   P (" -d  dictionary order: consider only letters, digits, and spaces\n");
  156.   P (" -f  fold upper case to lower\n");
  157.   P (" -r  string is a regular expression\n");
  158.   exit (1);
  159. }
  160.  
  161. int dflag;
  162. int fflag;
  163. int rflag;
  164.  
  165. int
  166. main (argc, argv)
  167.   int argc;
  168.   char **argv;
  169. {
  170.   char *dict;
  171.   char *word;
  172.   FILE *f;
  173.   struct stat statb;
  174.   long start, end, pos;
  175.   char buf[100];
  176.   int c;
  177.   extern char *optarg;
  178.   extern int optind;
  179.   int (*cmpf) ();
  180.  
  181.   while ((c = getopt (argc, argv, "dfr")) != EOF)
  182.     {
  183.       switch (c)
  184.     {
  185.     case 'r':
  186.       rflag = 1;
  187.       break;
  188.     case 'd':
  189.       dflag = 1;
  190.       break;
  191.     case 'f':
  192.       fflag = 1;
  193.       break;
  194.     default:
  195.       usage ();
  196.     }
  197.     }
  198.  
  199.   if (optind == argc)
  200.     usage ();
  201.  
  202.   word = argv[optind++];
  203.  
  204.   if (optind != argc)
  205.     {
  206.       dict = argv[optind++];
  207.     }
  208.   else
  209.     {
  210.       dflag = 1;
  211.       fflag = 1;
  212.       dict = (char *) xmalloc (strlen (dict_lib) + strlen (dict_name) + 2);
  213.       strcpy (dict, dict_lib);
  214.       strcat (dict, "/");
  215.       strcat (dict, dict_name);
  216.     }
  217.  
  218.   if (rflag)
  219.     {
  220.       if (word[0] == '^' && !contains_meta (word + 1))
  221.     {
  222.       /* only meta character is '^' at beginning -
  223.              * it's ok to skip it and use the binary search
  224.              */
  225.       word++;
  226.     }
  227.       else
  228.     {
  229.       dogrep (word, dict);
  230.       return 0;
  231.     }
  232.     }
  233.  
  234.   if (dflag)
  235.     {
  236.       /* if dictionary order, thow out non-dictionary characters */
  237.       char *p, *q, *nword;
  238.       nword = (char *) xmalloc (strlen (word) + 1);
  239.       p = word;
  240.       q = nword;
  241.       while (*p)
  242.     {
  243.       if (isalpha (*p) || isdigit (*p) || isspace (*p))
  244.         *q++ = *p;
  245.       p++;
  246.     }
  247.       *q = 0;
  248.       word = nword;
  249.  
  250.       if (fflag)
  251.     cmpf = cmp11;
  252.       else
  253.     cmpf = cmp10;
  254.     }
  255.   else if (fflag)
  256.     {
  257.       cmpf = cmp01;
  258.     }
  259.   else
  260.     {
  261.       cmpf = cmp00;
  262.     }
  263.  
  264.   if (fflag)
  265.     {
  266.       char *p;
  267.       for (p = word; *p; p++)
  268.     if (isupper (*p))
  269.       *p = _tolower (*p);
  270.     }
  271.  
  272.   if ((f = fopen (dict, "r")) == NULL)
  273.     {
  274.       fprintf (stderr, "can't open %s\n", dict);
  275.       exit (1);
  276.     }
  277.  
  278.   if (stat (dict, &statb) < 0)
  279.     {
  280.       fprintf (stderr, "can't stat %s\n", dict);
  281.       exit (1);
  282.     }
  283.  
  284.   start = 0;
  285.   end = statb.st_size;
  286.   fseek (f, (end - start) / 2, 0);
  287.   while ((c = getc (f)) != EOF)
  288.     if (c == '\n')
  289.       break;
  290.  
  291.   /* first, find last word before the one we want */
  292.   while (1)
  293.     {
  294.       pos = ftell (f);
  295.       fgets (buf, sizeof buf, f);
  296.       if ((*cmpf) (buf, word) < 0)
  297.     start = pos;
  298.       else
  299.     end = pos;
  300.  
  301.       pos = start + (end - start) / 2 - 100;
  302.       if (pos <= start)
  303.     break;
  304.       fseek (f, pos, 0);
  305.       while ((c = getc (f)) != EOF)
  306.     if (c == '\n')
  307.       break;
  308.       if (c == EOF)
  309.     break;
  310.     }
  311.   if (pos < 0)
  312.     pos = 0;
  313.   fseek (f, pos, 0);
  314.  
  315.   /* 
  316.    * If we are at the file start, then don't skip to the next newline,
  317.    * because then we would never match the first word in the file.  
  318.    */
  319.   if (pos > 0)
  320.     while ((c = getc (f)) != EOF)
  321.       if (c == '\n')
  322.         break;
  323.  
  324.   while (fgets (buf, sizeof buf, f) != NULL)
  325.     {
  326.       int x;
  327.       x = (*cmpf) (buf, word);
  328.       if (x > 0)
  329.     break;
  330.       if (x == 0)
  331.     fputs (buf, stdout);
  332.     }
  333.  
  334.   return 0;
  335. }
  336.  
  337. static int
  338. contains_meta (p)
  339.   char *p;
  340. {
  341.   while (1)
  342.     {
  343.       switch (*p)
  344.     {
  345.     case 0:
  346.       return (0);
  347.     case '$':
  348.     case '^':
  349.     case '.':
  350.     case '*':
  351.     case '+':
  352.     case '?':
  353.     case '[':
  354.     case ']':
  355.     case '\\':
  356.       return (1);
  357.     }
  358.       p++;
  359.     }
  360. }
  361.  
  362. void
  363. dogrep (word, dict)
  364.   char *word;
  365.   char *dict;
  366. {
  367.   char *av[5];
  368.   char **avp;
  369.   char *prog;
  370.  
  371.   if (!contains_meta (word))
  372.     prog = "fgrep";
  373.   else if (fflag)
  374.     prog = "grep";
  375.   else
  376.     prog = "egrep";
  377.   avp = av;
  378.   *avp++ = prog;
  379.   if (fflag)
  380.     *avp++ = "-i";
  381.   *avp++ = word;
  382.   *avp++ = dict;
  383.   *avp = NULL;
  384.  
  385.   execvp (prog, av);
  386.   fprintf (stderr, "can't exec %s\n", prog);
  387. }
  388.