home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume5 / s5look < prev    next >
Text File  |  1989-02-03  |  5KB  |  260 lines

  1. Path: xanth!nic.MR.NET!hal!ncoast!allbery
  2. From: campbell@redsox.UUCP (Larry Campbell)
  3. Newsgroups: comp.sources.misc
  4. Subject: v05i007: Public domain look(1) for SysV
  5. Message-ID: <491@redsox.UUCP>
  6. Date: 28 Oct 88 02:25:50 GMT
  7. Sender: allbery@ncoast.UUCP
  8. Reply-To: campbell@redsox.UUCP (Larry Campbell)
  9. Organization: The Boston Software Works, Inc.
  10. Lines: 247
  11. Approved: allbery@ncoast.UUCP
  12.  
  13. Posting-number: Volume 5, Issue 7
  14. Submitted-by: "Larry Campbell" <campbell@redsox.UUCP>
  15. Archive-name: s5look
  16.  
  17. Here's a quickie public domain implementation of look.  It's not blazingly
  18. fast, but it sure beats grep, it lints cleanly, and the price is right.
  19.  
  20. /*
  21.  * look.c
  22.  *
  23.  *    <-xtx-*> cc -o look -O -s look.c
  24.  *
  25.  *    An implementation of the V7/Berkeley look(1) utility, which
  26.  *    is annoyingly lacking from System V.  This code is in the public
  27.  *    public domain.  You may use this code for any purpose, commercial
  28.  *    or noncommercial, as long as you don't try to claim you wrote it.
  29.  *
  30.  *    This code hasn't been tuned;  it runs about half the speed of the
  31.  *    V7 version.  That's good enough for me.
  32.  *
  33.  *    If you find bugs, please send me the fixes.
  34.  *
  35.  * Written October, 1988 by:
  36.  *
  37.  *    Larry Campbell
  38.  *    The Boston Software Works, Inc.
  39.  *    120 Fulton Street, Boston, MA 02109
  40.  *    campbell@bsw.com
  41.  ******************************************************************
  42.  * usage:
  43.  *
  44.  *    look [-f] words file
  45.  *
  46.  *    Conducts a binary search in <file>, which must be sorted,
  47.  *    for a line beginning with <words>.  The -f switch means
  48.  *    ignore (fold) case.
  49.  *
  50.  *    If the input file is not sorted, the results are unpredictable.
  51.  */
  52.  
  53. #include <stdio.h>
  54. #include <ctype.h>
  55. #include <string.h>
  56. #include <sys/types.h>
  57. #include <sys/stat.h>
  58.  
  59. extern void
  60.     perror(),
  61.     exit();
  62.  
  63. char
  64.     *words,
  65.     *filename,
  66.     buf[BUFSIZ];
  67.  
  68. int
  69.     fold_flag,
  70.     length;
  71.  
  72. FILE
  73.     *f;
  74.  
  75. long
  76.     left_offset,
  77.     offset,
  78.     right_offset,
  79.     size,
  80.     step;
  81.  
  82. /* Forward declarations */
  83.  
  84. void
  85.     search(),
  86.     start_of_line(),
  87.     strlwr(),
  88.     usage();
  89.  
  90. main(argc, argv)
  91. char *argv[];
  92. {
  93. int
  94.     i;
  95.  
  96. struct stat
  97.     statb;
  98.  
  99. if (argc < 3 || argc > 4)
  100.     usage();
  101. fold_flag = 0;
  102. if (argc == 4) 
  103.     if (argv[1][0] == '-' && argv[1][1] == 'f')
  104.     fold_flag = 1;
  105.     else
  106.     usage();
  107. i = argc - 2;
  108. words = argv[i];
  109. length = strlen(words);
  110. if (fold_flag)
  111.     strlwr(words);
  112.  
  113. filename = argv[i + 1];
  114.  
  115. f = fopen(filename, "r");
  116. if (f == NULL)
  117.     perror("can't open input file");
  118.  
  119. if (fstat(fileno(f), &statb) < 0)
  120.     perror("stat failed on input file");
  121.  
  122. size = statb.st_size;
  123. if (size == 0)
  124.     exit(0);
  125.  
  126. offset = size / 2;
  127. step = offset / 2;
  128. search();
  129. return 0;
  130. }
  131.  
  132. void
  133. search()
  134. {
  135. int
  136.     compare;
  137.  
  138. char
  139.     buf2[BUFSIZ];
  140.  
  141. for (;;)
  142.     {
  143.     if (fseek(f, offset, 0) == -1)
  144.     perror("fseek");
  145.     start_of_line();
  146.     compare = strncmp(words, buf, length);
  147.     if (compare == 0)
  148.     {
  149.     while (offset > 0L)    /* back up to first nonmatching line */
  150.         {
  151.         offset -= left_offset;
  152.         start_of_line();
  153.         compare = strncmp(words, buf, length);
  154.         if (compare != 0)
  155.         {
  156.         if (fseek(f, ++offset, 0) == -1) /* skip nonmatching line */
  157.             perror("fseek");
  158.         if (fgets(buf, BUFSIZ, f) == 0)    /* reload matching line */
  159.             perror("fgets");
  160.         break;
  161.         }
  162.         }
  163.     for (;;)
  164.         {
  165.         (void) fputs(buf, stdout);
  166.         if (fgets(buf, BUFSIZ, f) == 0)
  167.         break;
  168.         (void) strcpy(buf2, buf);
  169.         if (fold_flag)
  170.         strlwr(buf2);
  171.         if (strncmp(words, buf2, length) != 0)
  172.         break;
  173.         }
  174.     exit(0);
  175.     }
  176.  
  177.     if (step == 0)
  178.     exit(1);
  179.     if (compare < 0)
  180.     {
  181.     if (step < left_offset)
  182.         offset -= left_offset;
  183.     else
  184.         offset -= step;
  185.     if (offset <= 0L)
  186.         exit(1);
  187.     }
  188.     else
  189.     {
  190.     if (step < right_offset)
  191.         offset += right_offset;
  192.     else
  193.         offset += step;
  194.     if (offset > size)
  195.         exit(1);
  196.     }
  197.     step = step / 2;
  198.     }
  199. }
  200.  
  201. void
  202. start_of_line()
  203. {
  204. int
  205.     c;
  206.  
  207. long
  208.     toffset;
  209.  
  210. if (offset <= 0L)
  211.     return;
  212. toffset = offset;
  213. while (toffset > 0L)
  214.     {
  215.     c = fgetc(f);
  216.     if (c == '\n')
  217.     break;
  218.     if (fseek(f, --toffset, 0) == -1)
  219.     perror("fseek");
  220.     }
  221. if (fgets(buf, BUFSIZ, f) == 0)
  222.     perror("prev_line: fgets");
  223. if (fold_flag)
  224.     strlwr(buf);
  225. left_offset = offset - toffset;
  226. right_offset = (strlen(buf) - left_offset) + 1;
  227. }
  228.  
  229.  
  230. void
  231. usage()
  232. {
  233. (void) fprintf(stderr, "usage: look [-f] string file\n");
  234. exit(2);
  235. }
  236.  
  237.  
  238. /*
  239.  * This function is in ANSI C but AT&T is still behind the times.
  240.  */
  241.  
  242. void
  243. strlwr(s)
  244. char *s;
  245. {
  246. register char
  247.     c;
  248.  
  249. while (c = *s)
  250.     {
  251.     if (isupper(c))
  252.     *s = tolower(c);
  253.     s++;
  254.     }
  255. }
  256. -- 
  257. Larry Campbell                          The Boston Software Works, Inc.
  258. campbell@bsw.com                        120 Fulton Street
  259. wjh12!redsox!campbell                   Boston, MA 02146
  260.