From bff61cf9e1b2fd17eb971c1e5253f4d84eaedd3a Mon Sep 17 00:00:00 2001 From: Clint Adams Date: Mon, 2 Jul 2001 19:39:34 +0000 Subject: 15211: zsh/pcre module --- ChangeLog | 6 +++ Doc/Zsh/mod_pcre.yo | 22 ++++++++ Functions/Example/zpgrep | 25 +++++++++ Src/Modules/pcre.c | 134 +++++++++++++++++++++++++++++++++++++++++++++++ Src/Modules/pcre.mdd | 7 +++ zshconfig.ac | 8 ++- 6 files changed, 200 insertions(+), 2 deletions(-) create mode 100644 Doc/Zsh/mod_pcre.yo create mode 100644 Functions/Example/zpgrep create mode 100644 Src/Modules/pcre.c create mode 100644 Src/Modules/pcre.mdd diff --git a/ChangeLog b/ChangeLog index ac299f589..05fa2fab0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2001-07-02 Clint Adams + + * 15211: zshconfig.ac, Doc/Zsh/mod_pcre.yo, + Functions/Example/zpgrep, Src/Modules/pcre.c, + Src/Modules/pcre.mdd: interface to PCRE library. + 2001-07-02 Oliver Kiddle * 15204: zshconfig.ac, Src/compat.c, Src/params.c: fix compilation diff --git a/Doc/Zsh/mod_pcre.yo b/Doc/Zsh/mod_pcre.yo new file mode 100644 index 000000000..76cf5dec6 --- /dev/null +++ b/Doc/Zsh/mod_pcre.yo @@ -0,0 +1,22 @@ +COMMENT(!MOD!zsh/pcre +Interface to the PCRE library. +!MOD!) +cindex(regular expressions, perl-compatible) +The tt(zsh/pcre) module makes some commands available as builtins: + +startitem() +findex(pcre_compile) +item(tt(pcre_compile) [ tt(-aimx) ] var(PCRE))( +Compiles a perl-compatible regular expression. +) +findex(pcre_study) +item(tt(pcre_study))( +Studies the previously-compiled PCRE which may result in faster +matching. +) +findex(pcre_match) +item(tt(pcre_match) var(string))( +Returns successfully if tt(string) matches the previously-compiled +PCRE. +) +enditem() diff --git a/Functions/Example/zpgrep b/Functions/Example/zpgrep new file mode 100644 index 000000000..8b1edaa1c --- /dev/null +++ b/Functions/Example/zpgrep @@ -0,0 +1,25 @@ +# Usage: zpgrep ... +# + +zpgrep() { +local file pattern + +pattern=$1 +shift + +if ((! ARGC)) then + set -- - +fi + +pcre_compile $pattern +pcre_study + +for file +do + if [[ "$file" == - ]] then + while read -u0 buf; do pcre_match $buf && print $buf; done + else + while read -u0 buf; do pcre_match $buf && print $buf; done < "$file" + fi +done +} diff --git a/Src/Modules/pcre.c b/Src/Modules/pcre.c new file mode 100644 index 000000000..a4dbb24c9 --- /dev/null +++ b/Src/Modules/pcre.c @@ -0,0 +1,134 @@ +/* + * pcre.c - interface to the PCRE library + * + * This file is part of zsh, the Z shell. + * + * Copyright (c) 2001 Clint Adams + * All rights reserved. + * + * Permission is hereby granted, without written agreement and without + * license or royalty fees, to use, copy, modify, and distribute this + * software and to distribute modified versions of this software for any + * purpose, provided that the above copyright notice and the following + * two paragraphs appear in all copies of this software. + * + * In no event shall Clint Adams or the Zsh Development Group be liable + * to any party for direct, indirect, special, incidental, or consequential + * damages arising out of the use of this software and its documentation, + * even if Andrew Main and the Zsh Development Group have been advised of + * the possibility of such damage. + * + * Clint Adams and the Zsh Development Group specifically disclaim any + * warranties, including, but not limited to, the implied warranties of + * merchantability and fitness for a particular purpose. The software + * provided hereunder is on an "as is" basis, and Andrew Main and the + * Zsh Development Group have no obligation to provide maintenance, + * support, updates, enhancements, or modifications. + * + */ + +/**/ +#if defined(HAVE_PCRE_COMPILE) && defined(HAVE_PCRE_EXEC) + +#include "pcre.mdh" +#include "pcre.pro" +#include + +static pcre *pcre_pattern; +static pcre_extra *pcre_hints; + +/**/ +static int +bin_pcre_compile(char *nam, char **args, char *ops, int func) +{ + int pcre_opts = 0, pcre_errptr; + const char *pcre_error; + + if(ops['a']) pcre_opts |= PCRE_ANCHORED; + if(ops['i']) pcre_opts |= PCRE_CASELESS; + if(ops['m']) pcre_opts |= PCRE_MULTILINE; + if(ops['x']) pcre_opts |= PCRE_EXTENDED; + + pcre_pattern = pcre_compile(*args, pcre_opts, &pcre_error, &pcre_errptr, NULL); + + if (pcre_pattern == NULL) + { + zwarnnam(nam, "error in regex: %s", pcre_error, 0); + return 1; + } + + return 0; +} + +/**/ +#ifdef HAVE_PCRE_STUDY + +/**/ +static int +bin_pcre_study(char *nam, char **args, char *ops, int func) +{ + const char *pcre_error; + + pcre_hints = pcre_study(pcre_pattern, 0, &pcre_error); + if (pcre_error != NULL) + { + zwarnnam(nam, "error while studying regex: %s", pcre_error, 0); + return 1; + } + + return 0; +} + +/**/ +#endif /* HAVE_PCRE_STUDY */ + +/**/ +static int +bin_pcre_match(char *nam, char **args, char *ops, int func) +{ +#define PCRE_OVEC_SIZE 50 + + int ovec[PCRE_OVEC_SIZE]; /* throwing this away now, but will be useful someday */ + + return !(pcre_exec(pcre_pattern, pcre_hints, *args, strlen(*args), 0, 0, ovec, PCRE_OVEC_SIZE) >= 0); +} + +static struct builtin bintab[] = { + BUILTIN("pcre_compile", 0, bin_pcre_compile, 1, 1, 0, "aimx", NULL), +#ifdef HAVE_PCRE_STUDY + BUILTIN("pcre_study", 0, bin_pcre_study, 0, 0, 0, NULL, NULL), +#endif + BUILTIN("pcre_match", 0, bin_pcre_match, 1, 1, 0, NULL, NULL) +}; + +/**/ +int +setup_(Module m) +{ + return 0; +} + +/**/ +int +boot_(Module m) +{ + return !addbuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)); +} + +/**/ +int +cleanup_(Module m) +{ + deletebuiltins(m->nam, bintab, sizeof(bintab)/sizeof(*bintab)); + return 0; +} + +/**/ +int +finish_(Module m) +{ + return 0; +} + +/**/ +#endif /* HAVE_PCRE_COMPILE && HAVE_PCRE_EXEC */ diff --git a/Src/Modules/pcre.mdd b/Src/Modules/pcre.mdd new file mode 100644 index 000000000..d6290dd1b --- /dev/null +++ b/Src/Modules/pcre.mdd @@ -0,0 +1,7 @@ +name=zsh/pcre +link=either +load=no + +autobins="pcre_compile pcre_study pcre_match" + +objects="pcre.o" diff --git a/zshconfig.ac b/zshconfig.ac index 78fb6404e..279dcf46d 100644 --- a/zshconfig.ac +++ b/zshconfig.ac @@ -475,7 +475,7 @@ AC_CHECK_HEADERS(sys/time.h sys/times.h sys/select.h termcap.h termio.h \ limits.h fcntl.h libc.h sys/utsname.h sys/resource.h \ locale.h errno.h stdlib.h unistd.h sys/capability.h \ utmp.h utmpx.h sys/types.h pwd.h grp.h poll.h sys/mman.h \ - netinet/in_systm.h) + netinet/in_systm.h, pcre.h) if test $dynamic = yes; then AC_CHECK_HEADERS(dlfcn.h) AC_CHECK_HEADERS(dl.h) @@ -643,6 +643,9 @@ AC_CHECK_LIB(cap, cap_get_proc) AC_CHECK_LIB(socket, socket) +dnl pcre-config should probably be employed here +AC_CHECK_LIB(pcre, pcre_compile) + dnl --------------------- dnl CHECK TERMCAP LIBRARY dnl --------------------- @@ -933,7 +936,8 @@ AC_CHECK_FUNCS(strftime difftime gettimeofday \ putenv getenv \ brk sbrk \ pathconf sysconf \ - tgetent tigetflag tigetnum tigetstr setupterm) + tgetent tigetflag tigetnum tigetstr setupterm \ + pcre_compile pcre_study pcre_exec) AC_FUNC_STRCOLL dnl Check if tgetent accepts NULL (and will allocate its own termcap buffer) -- cgit 1.4.1