home *** CD-ROM | disk | FTP | other *** search
- /*
- * regxsrch.c Tue Jan 21 1992 15:28:47
- *
- *
- * Synopsis:
- * ~~~~~~~~~
- * A regular-expression searcher for Clipper. Uses the GNU regex library
- * (as contained in the GNUISH MSDOS project's GNULIB, available in the
- * pd:<msdos.gnuish> directory on Simtel20 and the mirror sites) to do
- * the actual regex searching; thus the Clipper program must be linked
- * against the GNU library (large model version) as well as this code and
- * the C library.
- *
- * Note that this makes no re_set_syntax() call, so the regex functions
- * are left to use the regex library's compile-time default syntax code.
- * As the regex library is distributed, this is 0, giving the egrep syntax
- * except that `\|' is required for the OR operator (`|' by itself is just
- * a literal), and `\(' and `\)' are required for grouping (`(' and `)' are
- * literals). See the file regex.h in the GNULIB or regexlib distributions
- * for details of the available options.
- *
- *
- * Warning:
- * ~~~~~~~~
- * I consider this release a Beta test version. There are no known bugs,
- * and I have tested it thoroughly, but I will not accept responsibility
- * for anything untoward it may do. If it sinks your house in a swamp,
- * kills your dog, and phones your boss and calls him a dirty bastard,
- * you will have only yourself to blame. However, I would appreciate
- * hearing of any bugs you may find, and I will probably fix them.
- *
- *
- * Notes:
- * ~~~~~~
- * This code #includes a header clipper.h, which is simply the virtual
- * concatenation of the files nandef.h and extend.h distributed with Clipper.
- *
- * In case of difficulty using this together with other libraries (such as
- * with super.lib), use the linker option /NODEFAULTLIBRARYSEARCH (/NOD)
- * and specify the C library llibca.lib (*not* llibce.lib) explicitly.
- *
- * To compile this, use MS C switches '-AL -Zl -Oalt -FPa -Gs'. For example,
- * if your default rule for C in make.ini uses $(MODEL),
- *
- * make regxsrch.obj MODEL=L CFLAGS='-Zl -Oalt -FPa -Gs'
- *
- * Assuming you are using GNU make and have the following default rule in
- * make.ini:
- *
- * # To produce a `.exe' file from a `.prg' file (the root of the code tree)
- * # using Clipper.
- * %.exe : %.prg
- * $(CLPC) $< $(CLPFLAGS)
- * $(LD) $(CLPLDFLAGS) $* $(XOBJS),$@,nul, $(CLPLIBS) $(XLIBS) ;
- *
- * you can compile a Clipper program tst.prg that uses this as follows:
- *
- * make tst.exe XOBJS=regxsrch.obj CLPLDFLAGS='/se:512 /noe /nod' XLIBS='gnulib_l llibca'
- *
- *
- * Returns:
- * ~~~~~~~~
- * -4 on parameter error,
- * -3 on memory allocation (_exmgrab) error,
- * -2 on regex error (regex compilation failed),
- * -1 on no match,
- * or the index (base 0) of the match.
- *
- *
- * History:
- * ~~~~~~~~
- * 18 Jan 92 RjR - Initial version.
- * 19 Jan 92 RjR - Bug fixes and cleanup of the Clipper interface.
- * 20 Jan 92 RjR - Do the _exmgrab() only once, for speed and to avoid
- * possible memory fragmentation. This gets us a 10%
- * speed gain.
- * - Buffer the regex from the last call, and do not
- * recompile it if the current regex is the same.
- * This gets us a further 35% speed gain.
- * - Arrange things so that there is only one exit point.
- * - Clean up in-code documentation.
- * - Added debugging code. Define DEBUG to use it.
- * 21 Jan 92 RjR - Cleanup and inspection.
- *
- *
- * Author:
- * ~~~~~~~
- * Richard Reiner <rreiner@nexus.yorku.ca>
- *
- *
- * Distribution:
- * ~~~~~~~~~~~~~
- * Copyright (C) 1992, Richard Reiner
- *
- * regxsrch.c comes with ABSOLUTELY NO WARRANTY. This is free software,
- * and you are welcome to distribute it under the terms of the GNU General
- * Public License, which covers both the warranty information and the
- * terms for redistribution.
- *
- * See the file COPYING in the GNULIB distribution for details.
- *
- */
-
-
- #ifdef DEBUG
- # define DEBUG_MSG(m) printf(m)
- #else
- # define DEBUG_MSG(m)
- #endif
-
- #include <regex.h>
- #include <math.h>
- #include <clipper.h>
- #include <stdlib.h>
- #include <string.h>
-
- #ifdef DEBUG
- # include <stdio.h>
- #endif
-
- #define PATBUFSIZ 2048
- #define FMAPSIZ 256
- #define LASTREGEXBUFSIZ 256
-
- CLIPPER regex_srch (void) {
- static struct re_pattern_buffer *rbuf;
- static char *fmap, *lastregex;
- static int callcount = 0, retval = -2;
- register int parlen;
-
- /* if the Clipper parameters are of the right number and type */
- if (PCOUNT == 2 && ISCHAR(1) && ISCHAR(2)) {
- /*
- * Allocate memory the first time we are called. We do not
- * allocate and free (_exmgrab() and _exmback()) each time we are
- * called, since the time required for allocation and freeing is
- * quite high relative to the time required for the actual regex
- * match. Instead we alloc once, and never free until Clipper
- * does it for us at the Clipper program's termination.
- */
- if (callcount == 0) {
- callcount++;
- /* allocate memory from Clipper */
- fmap = _exmgrab(FMAPSIZ);
- rbuf = (struct re_pattern_buffer *) _exmgrab(sizeof (struct re_pattern_buffer));
- rbuf->buffer = _exmgrab(PATBUFSIZ);
- lastregex = _exmgrab(LASTREGEXBUFSIZ);
-
- /* ensure lastregex is null terminated */
- lastregex[LASTREGEXBUFSIZ - 1] = '\0';
- }
-
- /* if one of the _exmgrab()s failed */
- if (fmap==NULL || rbuf==NULL || rbuf->buffer==NULL || lastregex==NULL) {
- /* store allocation error indication for Clipper */
- retval = -3;
- } else { /* _exmgrab()s were OK */
- /* initialize rbuf fields */
- rbuf->allocated = PATBUFSIZ;
- rbuf->translate = 0;
-
- /* store length of target string for later repeated use */
- parlen = _parclen(1, 1);
-
- /* if this regex is not the same as the last one */
- if (strncmp(lastregex, _parc(2,1), LASTREGEXBUFSIZ - 1) != 0) {
- #ifdef DEBUG
- DEBUG_MSG("Regex not the same as previous.\n");
- #endif
- /* store the regex for next time */
- strncpy(lastregex, _parc(2,1), LASTREGEXBUFSIZ - 1);
- /* compile the regex */
- if (re_compile_pattern(_parc(2,1), _parclen(2,1), rbuf) != 0) {
- /* store compilation error indication for Clipper */
- retval = -2;
- } else { /* the compilation was successful, so we search */
- rbuf->fastmap = fmap;
- retval = re_search(rbuf, _parc(1,1), parlen, 0, parlen-1, 0);
- }
- } else { /* regex is the same as the last one, so no need to recompile */
- DEBUG_MSG("Regex same as previous.\n");
- /* Search only if the last search, which was using this
- same regex, did not produce an error. Otherwise, don't
- change anything */
- if (retval >= -1) {
- retval = re_search(rbuf, _parc(1,1), parlen, 0, parlen-1, 0);
- } else {
- DEBUG_MSG("Last attempt produced error; not searching.\n");
- }
- }
- }
- } else { /* Clipper parameters were not OK */
- /* store parameter error indication for Clipper */
- retval = -4;
- }
- #ifdef DEBUG
- printf("retval == %d.\n",retval);
- #endif
- _retni(retval);
- return;
- }
-