diff options
-rw-r--r-- | extension/ChangeLog | 6 | ||||
-rw-r--r-- | extension/Makefile.am | 3 | ||||
-rw-r--r-- | extension/Makefile.in | 20 | ||||
-rw-r--r-- | extension/configh.in | 6 | ||||
-rwxr-xr-x | extension/configure | 4 | ||||
-rw-r--r-- | extension/configure.ac | 4 | ||||
-rw-r--r-- | extension/fnmatch.c | 175 | ||||
-rw-r--r-- | test/ChangeLog | 5 | ||||
-rw-r--r-- | test/Makefile.am | 4 | ||||
-rw-r--r-- | test/Makefile.in | 9 | ||||
-rw-r--r-- | test/Maketests | 5 | ||||
-rw-r--r-- | test/fnmatch.awk | 10 | ||||
-rw-r--r-- | test/fnmatch.ok | 9 |
13 files changed, 250 insertions, 10 deletions
diff --git a/extension/ChangeLog b/extension/ChangeLog index 2ea13e36..4eab7d7a 100644 --- a/extension/ChangeLog +++ b/extension/ChangeLog @@ -1,3 +1,9 @@ +2012-07-12 Arnold D. Robbins <arnold@skeeve.com> + + * fnmatch.c: New file. + * Makefile.am: Build fnmatch extension. + * configure.ac: Look for fnmatch.h and fnmatch function. + 2012-07-11 Arnold D. Robbins <arnold@skeeve.com> * filefuncs.c (array_set, do_stat): Use make_const_string. diff --git a/extension/Makefile.am b/extension/Makefile.am index 5c6532b4..abe778e2 100644 --- a/extension/Makefile.am +++ b/extension/Makefile.am @@ -33,6 +33,7 @@ ACLOCAL_AMFLAGS = -I m4 pkgextension_LTLIBRARIES = \ filefuncs.la \ + fnmatch.la \ fork.la \ ordchr.la \ readfile.la \ @@ -44,6 +45,8 @@ MY_MODULE_FLAGS = -module -avoid-version -no-undefined filefuncs_la_SOURCES = filefuncs.c filefuncs_la_LDFLAGS = $(MY_MODULE_FLAGS) +fnmatch_la_SOURCES = fnmatch.c +fnmatch_la_LDFLAGS = $(MY_MODULE_FLAGS) fork_la_SOURCES = fork.c fork_la_LDFLAGS = $(MY_MODULE_FLAGS) ordchr_la_SOURCES = ordchr.c diff --git a/extension/Makefile.in b/extension/Makefile.in index 1747bcdb..71920fec 100644 --- a/extension/Makefile.in +++ b/extension/Makefile.in @@ -136,6 +136,12 @@ filefuncs_la_OBJECTS = $(am_filefuncs_la_OBJECTS) filefuncs_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(filefuncs_la_LDFLAGS) $(LDFLAGS) -o $@ +fnmatch_la_LIBADD = +am_fnmatch_la_OBJECTS = fnmatch.lo +fnmatch_la_OBJECTS = $(am_fnmatch_la_OBJECTS) +fnmatch_la_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(fnmatch_la_LDFLAGS) $(LDFLAGS) -o $@ fork_la_LIBADD = am_fork_la_OBJECTS = fork.lo fork_la_OBJECTS = $(am_fork_la_OBJECTS) @@ -185,11 +191,11 @@ CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ -SOURCES = $(filefuncs_la_SOURCES) $(fork_la_SOURCES) \ - $(ordchr_la_SOURCES) $(readfile_la_SOURCES) \ +SOURCES = $(filefuncs_la_SOURCES) $(fnmatch_la_SOURCES) \ + $(fork_la_SOURCES) $(ordchr_la_SOURCES) $(readfile_la_SOURCES) \ $(rwarray_la_SOURCES) $(testext_la_SOURCES) $(time_la_SOURCES) -DIST_SOURCES = $(filefuncs_la_SOURCES) $(fork_la_SOURCES) \ - $(ordchr_la_SOURCES) $(readfile_la_SOURCES) \ +DIST_SOURCES = $(filefuncs_la_SOURCES) $(fnmatch_la_SOURCES) \ + $(fork_la_SOURCES) $(ordchr_la_SOURCES) $(readfile_la_SOURCES) \ $(rwarray_la_SOURCES) $(testext_la_SOURCES) $(time_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ @@ -340,6 +346,7 @@ ACLOCAL_AMFLAGS = -I m4 # Note: rwarray does not currently compile. pkgextension_LTLIBRARIES = \ filefuncs.la \ + fnmatch.la \ fork.la \ ordchr.la \ readfile.la \ @@ -350,6 +357,8 @@ pkgextension_LTLIBRARIES = \ MY_MODULE_FLAGS = -module -avoid-version -no-undefined filefuncs_la_SOURCES = filefuncs.c filefuncs_la_LDFLAGS = $(MY_MODULE_FLAGS) +fnmatch_la_SOURCES = fnmatch.c +fnmatch_la_LDFLAGS = $(MY_MODULE_FLAGS) fork_la_SOURCES = fork.c fork_la_LDFLAGS = $(MY_MODULE_FLAGS) ordchr_la_SOURCES = ordchr.c @@ -456,6 +465,8 @@ clean-pkgextensionLTLIBRARIES: } filefuncs.la: $(filefuncs_la_OBJECTS) $(filefuncs_la_DEPENDENCIES) $(EXTRA_filefuncs_la_DEPENDENCIES) $(filefuncs_la_LINK) -rpath $(pkgextensiondir) $(filefuncs_la_OBJECTS) $(filefuncs_la_LIBADD) $(LIBS) +fnmatch.la: $(fnmatch_la_OBJECTS) $(fnmatch_la_DEPENDENCIES) $(EXTRA_fnmatch_la_DEPENDENCIES) + $(fnmatch_la_LINK) -rpath $(pkgextensiondir) $(fnmatch_la_OBJECTS) $(fnmatch_la_LIBADD) $(LIBS) fork.la: $(fork_la_OBJECTS) $(fork_la_DEPENDENCIES) $(EXTRA_fork_la_DEPENDENCIES) $(fork_la_LINK) -rpath $(pkgextensiondir) $(fork_la_OBJECTS) $(fork_la_LIBADD) $(LIBS) ordchr.la: $(ordchr_la_OBJECTS) $(ordchr_la_DEPENDENCIES) $(EXTRA_ordchr_la_DEPENDENCIES) @@ -476,6 +487,7 @@ distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/filefuncs.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fnmatch.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fork.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ordchr.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readfile.Plo@am__quote@ diff --git a/extension/configh.in b/extension/configh.in index 519f8ea3..179b5863 100644 --- a/extension/configh.in +++ b/extension/configh.in @@ -3,6 +3,12 @@ /* Define to 1 if you have the <dlfcn.h> header file. */ #undef HAVE_DLFCN_H +/* Define to 1 if you have the `fnmatch' function. */ +#undef HAVE_FNMATCH + +/* Define to 1 if you have the <fnmatch.h> header file. */ +#undef HAVE_FNMATCH_H + /* Define to 1 if you have the `GetSystemTimeAsFileTime' function. */ #undef HAVE_GETSYSTEMTIMEASFILETIME diff --git a/extension/configure b/extension/configure index 30b162a8..301e3418 100755 --- a/extension/configure +++ b/extension/configure @@ -11462,7 +11462,7 @@ then CFLAGS="$CFLAGS -Wall -Wextra" fi -for ac_header in time.h sys/time.h sys/select.h +for ac_header in fnmatch.h time.h sys/time.h sys/select.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" @@ -11476,7 +11476,7 @@ fi done -for ac_func in nanosleep select gettimeofday GetSystemTimeAsFileTime +for ac_func in fnmatch gettimeofday nanosleep select GetSystemTimeAsFileTime do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" diff --git a/extension/configure.ac b/extension/configure.ac index 838350cf..160d55d8 100644 --- a/extension/configure.ac +++ b/extension/configure.ac @@ -45,9 +45,9 @@ then CFLAGS="$CFLAGS -Wall -Wextra" fi -AC_CHECK_HEADERS(time.h sys/time.h sys/select.h) +AC_CHECK_HEADERS(fnmatch.h time.h sys/time.h sys/select.h) -AC_CHECK_FUNCS(nanosleep select gettimeofday GetSystemTimeAsFileTime) +AC_CHECK_FUNCS(fnmatch gettimeofday nanosleep select GetSystemTimeAsFileTime) dnl checks for compiler characteristics AC_C_INLINE diff --git a/extension/fnmatch.c b/extension/fnmatch.c new file mode 100644 index 00000000..7f050dcd --- /dev/null +++ b/extension/fnmatch.c @@ -0,0 +1,175 @@ +/* + * fnmatch.c - Provide an interface to fnmatch(3) routine + * + * Arnold Robbins + * arnold@skeeve.com + * Written 7/2012 + */ + +/* + * Copyright (C) 2012 the Free Software Foundation, Inc. + * + * This file is part of GAWK, the GNU implementation of the + * AWK Programming Language. + * + * GAWK is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * GAWK is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <stdio.h> +#include <assert.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <sys/types.h> +#include <sys/stat.h> +#include "config.h" +#include "gawkapi.h" + +#ifdef HAVE_FNMATCH_H +#define _GNU_SOURCE 1 /* use GNU extensions if they're there */ +#include <fnmatch.h> +#endif + +/* Provide GNU extensions as no-ops if not defined */ +#ifndef FNM_CASEFOLD +#define FNM_CASEFOLD 0 +#endif +#ifndef FNM_LEADING_DIR +#define FNM_LEADING_DIR 0 +#endif +#ifndef FNM_FILE_NAME +#define FNM_FILE_NAME 0 +#endif + +static const gawk_api_t *api; /* for convenience macros to work */ +static awk_ext_id_t *ext_id; + +static awk_bool_t init_fnmatch(void); +static awk_bool_t (*init_func)(void) = init_fnmatch; + +int plugin_is_GPL_compatible; + + +/* do_fnmatch --- implement the fnmatch interface */ + +static awk_value_t * +do_fnmatch(int nargs, awk_value_t *result) +{ + static int flags_mask = + FNM_CASEFOLD | FNM_FILE_NAME | + FNM_LEADING_DIR | FNM_NOESCAPE | + FNM_PATHNAME | FNM_PERIOD ; + awk_value_t pattern, string, flags; + int int_flags, retval; + + make_number(-1.0, result); /* default return */ +#ifdef HAVE_FNMATCH + if (nargs < 3) { + warning(ext_id, "fnmatch: called with less than three arguments"); + goto out; + } else if (do_lint && nargs > 3) + lintwarn(ext_id, "fnmatch: called with more than three arguments"); + + if (! get_argument(0, AWK_STRING, & pattern)) { + warning(ext_id, "fnmatch: could not get first argument"); + goto out; + } + + if (! get_argument(1, AWK_STRING, & string)) { + warning(ext_id, "fnmatch: could not get second argument"); + goto out; + } + + if (! get_argument(2, AWK_NUMBER, & flags)) { + warning(ext_id, "fnmatch: could not get third argument"); + goto out; + } + + int_flags = flags.num_value; + int_flags &= flags_mask; + + retval = fnmatch(pattern.str_value.str, + string.str_value.str, int_flags); + make_number((double) retval, result); + +out: +#else + fatal(ext_id, "fnmatch is not implemented on this system\n"); +#endif + return result; +} + +static struct fnmflags { + const char *name; + int value; +} flagtable[] = { + { "CASEFOLD", FNM_CASEFOLD }, + { "FILE_NAME", FNM_FILE_NAME }, + { "LEADING_DIR", FNM_LEADING_DIR }, + { "NOESCAPE", FNM_NOESCAPE }, + { "PATHNAME", FNM_PATHNAME }, + { "PERIOD", FNM_PERIOD }, + { NULL, 0 } +}; + +/* init_fnmatch --- load array with flags */ + +static awk_bool_t +init_fnmatch(void) +{ + int errors = 0; +#ifdef HAVE_FNMATCH + awk_value_t index, value, the_array; + awk_array_t new_array; + int i; + + if (! sym_update("FNM_NOMATCH", make_number(FNM_NOMATCH, & value))) { + warning(ext_id, "fnmatch init: could not add FNM_NOMATCH variable"); + errors++; + } + + new_array = create_array(); + for (i = 0; flagtable[i].name != NULL; i++) { + (void) make_const_string(flagtable[i].name, + strlen(flagtable[i].name), & index); + (void) make_number(flagtable[i].value, & value); + if (! set_array_element(new_array, & index, & value)) { + warning(ext_id, "fnmatch init: could not set array element %s", + flagtable[i].name); + errors++; + } + } + + the_array.val_type = AWK_ARRAY; + the_array.array_cookie = new_array; + + if (! sym_update("FNM", & the_array)) { + warning(ext_id, "fnmatch init: could not install FNM array"); + errors++; + } + +#endif + return errors == 0; +} + +static awk_ext_func_t func_table[] = { + { "fnmatch", do_fnmatch, 3 }, +}; + +/* define the dl_load function using the boilerplate macro */ + +dl_load_func(func_table, fnmatch, "") diff --git a/test/ChangeLog b/test/ChangeLog index 057434f9..019d2f34 100644 --- a/test/ChangeLog +++ b/test/ChangeLog @@ -1,3 +1,8 @@ +2012-07-12 Arnold D. Robbins <arnold@skeeve.com> + + * Makefile.am (fnmatch): New test. + * fnmatch.awk, fnmatch.ok: New files. + 2012-06-28 Andrew J. Schorr <aschorr@telemetry-investments.com> * time.awk: Avoid possibly throwing a spurious error by protecting diff --git a/test/Makefile.am b/test/Makefile.am index 58fddfc0..a244c6a0 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -230,6 +230,8 @@ EXTRA_DIST = \ fnasgnm.awk \ fnasgnm.in \ fnasgnm.ok \ + fnmatch.awk \ + fnmatch.ok \ fnmisc.awk \ fnmisc.ok \ fnparydl.awk \ @@ -889,7 +891,7 @@ LOCALE_CHARSET_TESTS = \ mbprintf1 mbprintf2 mbprintf3 rebt8b2 rtlenmb sort1 sprintfc SHLIB_TESTS = \ - filefuncs fork fork2 ordchr ordchr2 readfile rwarray \ + fnmatch filefuncs fork fork2 ordchr ordchr2 readfile rwarray \ testext time # List of the tests which should be run with --lint option: diff --git a/test/Makefile.in b/test/Makefile.in index 3e170f84..61e32b1b 100644 --- a/test/Makefile.in +++ b/test/Makefile.in @@ -442,6 +442,8 @@ EXTRA_DIST = \ fnasgnm.awk \ fnasgnm.in \ fnasgnm.ok \ + fnmatch.awk \ + fnmatch.ok \ fnmisc.awk \ fnmisc.ok \ fnparydl.awk \ @@ -1097,7 +1099,7 @@ LOCALE_CHARSET_TESTS = \ mbprintf1 mbprintf2 mbprintf3 rebt8b2 rtlenmb sort1 sprintfc SHLIB_TESTS = \ - filefuncs fork fork2 ordchr ordchr2 readfile rwarray \ + fnmatch filefuncs fork fork2 ordchr ordchr2 readfile rwarray \ testext time @@ -3174,6 +3176,11 @@ sprintfc: @AWKPATH=$(srcdir) $(AWK) -f $@.awk < $(srcdir)/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@ +fnmatch: + @echo $@ + @AWKPATH=$(srcdir) $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@ + filefuncs: @echo $@ @AWKPATH=$(srcdir) $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ diff --git a/test/Maketests b/test/Maketests index b10e1756..0a4e5820 100644 --- a/test/Maketests +++ b/test/Maketests @@ -1199,6 +1199,11 @@ sprintfc: @AWKPATH=$(srcdir) $(AWK) -f $@.awk < $(srcdir)/$@.in >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@ +fnmatch: + @echo $@ + @AWKPATH=$(srcdir) $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ + @-$(CMP) $(srcdir)/$@.ok _$@ && rm -f _$@ + filefuncs: @echo $@ @AWKPATH=$(srcdir) $(AWK) -f $@.awk >_$@ 2>&1 || echo EXIT CODE: $$? >>_$@ diff --git a/test/fnmatch.awk b/test/fnmatch.awk new file mode 100644 index 00000000..e8ef9377 --- /dev/null +++ b/test/fnmatch.awk @@ -0,0 +1,10 @@ +@load "fnmatch" + +BEGIN { + print "FNM_NOMATCH =", FNM_NOMATCH + for (i in FNM) + printf("FNM[\"%s\"] = %d\n", i, FNM[i]) + + printf("fnmatch(\"*.a\", \"foo.a\", 0) = %d\n", fnmatch("*.a", "foo.a", 0) ) + printf("fnmatch(\"*.a\", \"foo.c\", 0) = %d\n", fnmatch("*.a", "foo.c", 0)) +} diff --git a/test/fnmatch.ok b/test/fnmatch.ok new file mode 100644 index 00000000..cc17c6b1 --- /dev/null +++ b/test/fnmatch.ok @@ -0,0 +1,9 @@ +FNM_NOMATCH = 1 +FNM["LEADING_DIR"] = 8 +FNM["CASEFOLD"] = 16 +FNM["NOESCAPE"] = 2 +FNM["PERIOD"] = 4 +FNM["PATHNAME"] = 1 +FNM["FILE_NAME"] = 1 +fnmatch("*.a", "foo.a", 0) = 0 +fnmatch("*.a", "foo.c", 0) = 1 |