/* Copyright (c) 1994 Sun Wu, Udi Manber, Burra Gopal. All Rights Reserved. */ Started in Feb 1991. This chronicle briefly describes the progress of agrep. Feb/91: The approximate pattern matching algorithm called 'bitap' (bit-parallel approximate pattern matching) is designed. The algorithm is a generalization of Baeza-Yates' "shift-or" algorithm for exact matching. Mar/91: Many extensions of the algorithm 'bitap' are found, especially for approximate regular expression pattern matching. Preliminary implementation of the algorithm showed a strong promise for a general-purpose fast approximate pattern-matching tool. Apr/91: Approximate regular expression pattern matching was implemented. The result is even better than expected. The design of the software tool is pinned down. (For example, record oriented, multi-pattern, AND/OR logic queries.) A partition technique for approximate pattern matching is used. May/91: The prototype of "agrep" is completed. A lot of debugging/optimization in this month. Jun/91: The first version of agrep is released. agrep 1.0 was announced and made available by anonymous ftp from cs.arizona.edu. Jul/91: A sub-linear expected-time algorithm, called "amonkey" for approximate pattern matching (for simple pattern) is designed. The algorithm has the same time complexity as that of Chang&Lawler but is much much faster in practice. The algorithm is based on a variation of Boyer-Moore technique, which we call "block-shifting." A sub-linear expected-time algorithm, called "mgrep" for matching a set of patterns is designed based on the "block-shifting" technique with a hashing technique. Aug/91: "amonkey" is implemented and incorporated into agrep. It is very fast for long patterns like DNA patterns. (But roughly the same for matching English words as the bitap algorithm using the partition technique.) Prototype of "mgrep" is implemented. Sep/91: "mgrep" is incorporated into agrep to support the -f option. An algorithm for approximate pattern matching that combines the 'partition' technique with the sub-linear expected-time algorithm for multi-patterns is designed. Implementation shows it to be the fastest for ASCII text (and pattern). Boyer-moore technique for exact matching is incorporated. Nov/91: The final paper of "agrep" that is to appear in USENIX conference (Jan 1992) is finished. Jan/92: Some new options are added, such as find best matches (-B), and file outputs (-G). The man pages are revised. agrep version 2.0 is released. Fixed the following bugs and change the version to be 2.01. 1. -G option doesn't work correctly. 2. multiple definition of some global variables. 3. -# with -w forced the first character of the pattern to be matched Mar/92: Fixed the following bugs and change the version to be 2.02. 1. agrep sometimes misses some matches for pipeline input. 2. the word delimiter was not defined consistantly. ------------------------------------------------------------------------------ bgopal: The following changes were made to the original agrep during 1993-94: 1. Modifications to make main() take multiple options from the same '-' group: - the only modifications were in main.c. 2. Now, to make agrep take input from a buffer so that it can be used as a procedure from another program. Places where changes have to be done: - asearch.c/fill_buf(), bitap.c/fill_buf() - main.c/read() statements - mgrep.c/read() statements - sgrep.c/read() statements - probably don't have to change scanf in main.c where a y/n is asked. - probably don't have to change readdir in recursive.c. I have used fill_buf everywhere for reading things from a file. I have to verify whether this is actually used to take input in which it has to search for patterns or to read things REALLY from a file (-f option, file_out, etc.). If former, then I can simply modify fill_buf to read from an fd or from an input string. How to specify that string / area of memory is a separate issue to be resolved during the weekend. I have resolved it. I've also made a library interface for agrep. So 2 is done. 3. Make errno = exit code whenever you return -1 instead of exiting. 4. See if there is a way to avoid copying of memory bytes in agrep by using pointer manipulation instead of fill_buf: a part of making agrep a callable routine. Important to make it really fast, that's why do this. Solution: --------- I think I've solved the problem: but there is a restriction for within the memory pattern matching: THE SEARCHBUFFER HAS TO BEGIN WITH A NEWLINE -- otherwise we cannot avoid the copying. This fact can be checked in the library interface. There are some more problems whose solution I'm not sure of: ask Udi. The problem is: a. In asearch(), asearch0() and asearch1(), some data is copied after the data read in the buffer. Is that crucial? The same thing can be seen in bitap(). This is done when num_read < BlockSize -- why? b. In sgrep(), the whole buffer is filled with pat[m-1] so that bm() does not enter an infinite-loop. Is that crucial if there is an equivalent of a single iteration of the while-fill_buf-loop. I have not modified prepf() to read the multi-pattern from memory, not a file. I have to modify it later (including agrep.c). Function fill_buf now simply reads from the fd given: it does not bother about pointer manipulation. Note: wherever there is a while(i lots of problems! *). **** These were completed and added into glimpse/glimpseindex in Spring 1994. 7. One other problems with agrep as a callable routine: the variable names used by agrep can clash with user defined variable names. Making agrep variables static is not going to help since they are accessed throughout agrep code. Making code reentrant is not the issue (it is almost impossible!).