gawk-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gawk-diffs] [SCM] gawk branch, array-iface, updated. 50c2afd6433f1c4407


From: John Haque
Subject: [gawk-diffs] [SCM] gawk branch, array-iface, updated. 50c2afd6433f1c4407b04d2f75e536da7c94fe74
Date: Wed, 25 Apr 2012 16:57:16 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "gawk".

The branch, array-iface has been updated
       via  50c2afd6433f1c4407b04d2f75e536da7c94fe74 (commit)
      from  1a4aaf18f5ec6149315aabc53dbe667f1abfdb62 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
http://git.sv.gnu.org/cgit/gawk.git/commit/?id=50c2afd6433f1c4407b04d2f75e536da7c94fe74

commit 50c2afd6433f1c4407b04d2f75e536da7c94fe74
Author: john haque <address@hidden>
Date:   Wed Apr 25 11:36:51 2012 -0500

    New array extension.

diff --git a/extension/ChangeLog b/extension/ChangeLog
index 0b3053e..75dc66a 100644
--- a/extension/ChangeLog
+++ b/extension/ChangeLog
@@ -1,3 +1,8 @@
+2011-04-24         John Haque     <address@hidden>
+
+       * spec_array.c, spec_array.h, sparr.c, testsparr.awk: New files.
+       * steps: Updated.
+
 2011-08-31         John Haque     <address@hidden>
 
        * arrayparm.c, filefuncs.c, fork.c, ordchr.c, readfile.c,
diff --git a/extension/sparr.c b/extension/sparr.c
new file mode 100644
index 0000000..e986eb1
--- /dev/null
+++ b/extension/sparr.c
@@ -0,0 +1,162 @@
+/*
+ * sparr.c - Example of changing behavior of arrays in gawk.
+ *     See testsparr.awk for usage.
+ */
+
+/*
+ * 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 "awk.h"
+#include "spec_array.h"
+
+int plugin_is_GPL_compatible;
+
+typedef struct {
+       int load_file;
+       NODE *filename;
+} sdata_t;
+
+/* install_array --- install an array in the symbol table */
+
+static NODE *
+install_array(const char *name)
+{
+       NODE *r;
+
+       r = lookup(name);
+       if (r == NULL)
+               r = install_symbol(estrdup(name, strlen(name)), Node_var_array);
+       switch (r->type) {
+       case Node_var_new:
+               r = force_array(r, FALSE);
+               /* fall through */
+       case Node_var_array:
+               assoc_clear(r);
+               break;
+       default:
+               fatal(_("`%s' is not an array"), name);
+       }
+       return r;
+}
+
+/* fetch_SYS --- fetch routine for the array `SYS' */
+
+static NODE *
+fetch_SYS(NODE *symbol, NODE *subs, void *data)
+{
+       force_string(subs);
+       if (strcmp(subs->stptr, "time") == 0)
+               return do_strftime(0);
+       return NULL;
+}
+
+/* store_SYS --- store routine for the array `SYS' */
+
+static void
+store_SYS(NODE *symbol, NODE *subs, NODE *val, void *data)
+{
+       sdata_t *sd = (sdata_t *) data;
+ 
+       if (subs != NULL && val != NULL && val->type == Node_val) {
+               force_string(subs);
+               if (strcmp(subs->stptr, "readline") == 0) {
+                       sd->load_file = TRUE;
+                       unref(sd->filename);
+                       sd->filename = dupnode(val);
+               }
+       }
+}
+
+/* load_READLINE --- load routine for the array `READLINE' */
+
+static void
+load_READLINE(NODE *symbol, void *data)
+{
+       sdata_t *sd = (sdata_t *) data;
+       NODE *file, *tmp;
+       FILE *fp;
+       static char linebuf[BUFSIZ];
+       int i, long_line = FALSE;
+
+       if (! sd->load_file)    /* non-existent SYS["readline"] or already 
loaded */ 
+               return;
+
+       file = sd->filename;
+       force_string(file);
+
+       if (file->stlen == 0)
+               return;
+
+       assoc_clear(symbol);
+
+       if ((fp = fopen(file->stptr, "r" )) == NULL) {
+               warning(_("READLINE (%s): %s"), file->stptr, strerror(errno));
+               return;
+       }
+
+       for (i = 1; fgets(linebuf, sizeof(linebuf), fp ) != NULL; i++) {
+               NODE **lhs;
+               size_t sz;
+
+               sz = strlen(linebuf);
+               if (sz > 0 && linebuf[sz - 1] == '\n') {
+                       linebuf[sz - 1] = '\0';
+                       sz--;
+                       if (long_line) {
+                               long_line = FALSE;
+                               i--;
+                               continue;
+                       }
+               } else if (long_line) {
+                       i--;
+                       continue;
+               } else {
+                       if (do_lint)
+                               lintwarn(_("file `%s' does not end in newline 
or line # `%d' is too long"),
+                                       file->stptr, i);
+                       long_line = TRUE;
+               }
+
+               tmp = make_number(i);
+               lhs = assoc_lookup(symbol, tmp);
+               unref(tmp);
+               unref(*lhs);
+               *lhs = make_string(linebuf, sz);
+       }
+       fclose(fp);
+       sd->load_file = FALSE;  /* don't load this file again */
+}      
+
+/* dlload --- load this library */
+
+NODE *
+dlload(NODE *obj, void *dl)
+{
+       NODE *a1, *a2;
+       static sdata_t data;
+
+       a1 = install_array("SYS");
+       register_dyn_array(a1, fetch_SYS, store_SYS, & data);
+       a2 = install_array("READLINE");
+       register_deferred_array(a2, load_READLINE, & data);
+       return make_number((AWKNUM) 0);
+}
diff --git a/extension/spec_array.c b/extension/spec_array.c
new file mode 100644
index 0000000..b271300
--- /dev/null
+++ b/extension/spec_array.c
@@ -0,0 +1,384 @@
+/*
+ * spec_array.c - Support for specialized associative arrays.
+ */
+
+/*
+ * 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 "awk.h"
+#include "spec_array.h"
+
+typedef struct spec_array {
+       Fetch_func_t fetch_func;
+       Store_func_t store_func;
+       Load_func_t load_func;
+       void *data;
+} array_t;
+
+/*
+ * The array_t structure is attached to the array itself without
+ * the necessity to maintain a list of symbols; this works only
+ * because there is just enough free space in the NODE strcture when
+ * the base array is str_array.
+ */
+
+#define        SUPER(F)        (*str_array_func[AFUNC(F)])
+
+
+/*
+ * deferred_array --- Deferred loading of array at run-time.
+ *
+ * The load routine takes two arguments, the array and
+ * a void * data:
+ *
+ *     void load_func(NODE *array, void *data)
+ *
+ * Use register_deferred_array(array, load_func, void *data) to
+ * bind an array to the load routine. 
+ */
+
+static NODE **deferred_array_init(NODE *, NODE *);
+static NODE **deferred_array_lookup(NODE *, NODE *);
+static NODE **deferred_array_exists(NODE *, NODE *);
+static NODE **deferred_array_remove(NODE *, NODE *);
+static NODE **deferred_array_clear(NODE *, NODE *);
+static NODE **deferred_array_list(NODE *, NODE *);
+static NODE **deferred_array_copy(NODE *, NODE *);
+static NODE **deferred_array_length(NODE *, NODE *);
+
+static afunc_t deferred_array_func[] = {
+       deferred_array_init,
+       (afunc_t) 0,    /* typeof */
+       deferred_array_length,
+       deferred_array_lookup,
+       deferred_array_exists,
+       deferred_array_clear,
+       deferred_array_remove,
+       deferred_array_list, 
+       deferred_array_copy,
+       null_afunc,     /* dump */
+       (afunc_t) 0,    /* store */
+};
+
+
+/* deferred_array_init --- called when array becomes empty, e.g: delete 
BOUND_ARRAY */
+
+static NODE **
+deferred_array_init(NODE *symbol, NODE *subs)
+{
+       if (symbol != NULL) {
+               array_t *av = (array_t *) symbol->xarray;
+               symbol->xarray = NULL;  /* this is to avoid an assertion 
failure in null_array */ 
+               null_array(symbol);     /* typeless empty array */
+               if (symbol->parent_array == NULL) {
+                       /* main array */
+                       symbol->array_funcs = deferred_array_func;      /* 
restore type */
+                       symbol->xarray = (NODE *) av;
+               } else if (av)  /* sub-array */
+                       efree(av);
+       }
+       return NULL;
+}
+
+/* deferred_array_length --- get the length of the array */
+
+static NODE **
+deferred_array_length(NODE *symbol, NODE *subs)
+{
+       static NODE *length_node;
+       array_t *av = (array_t *) symbol->xarray;
+       if (av) {
+               symbol->xarray = NULL;
+               (*av->load_func)(symbol, av->data);
+               symbol->xarray = (NODE *) av;
+       }
+       length_node = symbol;
+       return & length_node;
+}
+
+#define DEF_ARR(F) static NODE **                      \
+deferred_array_##F(NODE *symbol, NODE *subs)           \
+{                                                      \
+       array_t *av = (array_t *) symbol->xarray;       \
+       if (av) {                                       \
+               symbol->xarray = NULL;                  \
+               (*av->load_func)(symbol, av->data);     \
+               symbol->xarray = (NODE *) av;           \
+       }                                               \
+       return SUPER(a##F)(symbol, subs);               \
+}
+
+/* the rest of the routines */
+
+DEF_ARR(exists)
+DEF_ARR(lookup)
+DEF_ARR(clear)
+DEF_ARR(remove)
+DEF_ARR(list)
+DEF_ARR(copy)
+
+#undef DEF_ARR
+
+
+/*
+ * dyn_array --- array with triggers for reading and writing
+ *     an element.
+ *
+ * The fetch routine should expect three arguments, the array,
+ * the subscript and optional void * data. It should return the value
+ * if it exists or NULL otherwise.
+ *
+ *     NODE *fetch_func(NODE *array, NODE *subs, void *data)
+ *
+ * The store routine must take an additional argument for the
+ * value. The value can be NULL if the specific element is
+ * removed from the array. The subscript (and the value) is NULL
+ * when the entire array is deleted. 
+ *
+ *     void store_func(NODE *array, NODE *subs, NODE *value, void *data)
+ *
+ * Use register_dyn_array(array, fetch_func, store_func, void *data) to
+ * bind an array to the fetch/store routine.
+ */
+
+
+static NODE **dyn_array_init(NODE *, NODE *);
+static NODE **dyn_array_lookup(NODE *, NODE *);
+static NODE **dyn_array_exists(NODE *, NODE *);
+static NODE **dyn_array_remove(NODE *, NODE *);
+static NODE **dyn_array_clear(NODE *, NODE *);
+static NODE **dyn_array_list(NODE *, NODE *);
+static NODE **dyn_array_copy(NODE *, NODE *);
+static NODE **dyn_array_store(NODE *, NODE *);
+
+static afunc_t dyn_array_func[] = {
+       dyn_array_init,
+       (afunc_t) 0,    /* typeof */
+       null_length,    /* length */
+       dyn_array_lookup,
+       dyn_array_exists,
+       dyn_array_clear,
+       dyn_array_remove,
+       dyn_array_list, 
+       dyn_array_copy,
+       null_afunc,     /* dump */
+       dyn_array_store,
+};
+
+/* dyn_array_init --- called when array becomes empty */
+
+static NODE **
+dyn_array_init(NODE *symbol, NODE *subs)
+{
+       if (symbol != NULL) {
+               array_t *av = (array_t *) symbol->xarray;
+               symbol->xarray = NULL;
+               null_array(symbol);     /* typeless empty array */
+               if (symbol->parent_array == NULL) {
+                       /* main array */
+                       symbol->array_funcs = dyn_array_func;   /* restore type 
*/
+                       symbol->xarray = (NODE *) av;
+               } else if (av)  /* sub-array */
+                       efree(av);
+       }
+       return NULL;
+}
+
+/* dyn_array_exists --- check if the SUBS exists */
+
+static NODE **
+dyn_array_exists(NODE *symbol, NODE *subs)
+{
+       NODE *r;
+       array_t *av = (array_t *) symbol->xarray;
+
+       if (av && av->fetch_func) {
+               symbol->xarray = NULL;
+               r = (*av->fetch_func)(symbol, subs, av->data);
+               symbol->xarray = (NODE *) av;
+               if (r != NULL) {
+                       NODE **lhs;
+                       lhs = SUPER(alookup)(symbol, subs);
+                       unref(*lhs);
+                       *lhs = r;
+                       return lhs;
+               }
+       }
+
+       return SUPER(aexists)(symbol, subs);
+}
+
+/* dyn_array_lookup --- lookup SUBS and return a pointer to store its value */
+
+static NODE **
+dyn_array_lookup(NODE *symbol, NODE *subs)
+{
+       NODE **lhs;
+       NODE *r;
+       array_t *av = (array_t *) symbol->xarray;
+
+       lhs = SUPER(alookup)(symbol, subs);
+       if (av && av->fetch_func) {
+               symbol->xarray = NULL;
+               r = (*av->fetch_func)(symbol, subs, av->data);
+               symbol->xarray = (NODE *) av;
+               if (r != NULL) {
+                       unref(*lhs);
+                       *lhs = r;
+               }
+       }
+       return lhs;
+}
+
+/* dyn_array_store --- call the store routine after an assignment */
+
+static NODE **
+dyn_array_store(NODE *symbol, NODE *subs)
+{
+       array_t *av = (array_t *) symbol->xarray;
+
+       if (av && av->store_func) {
+               NODE **lhs;
+               lhs = SUPER(aexists)(symbol, subs);
+               symbol->xarray = NULL;
+               (*av->store_func)(symbol, subs, *lhs, av->data);
+               symbol->xarray = (NODE *) av;
+       }
+       return NULL;
+}
+
+/* dyn_array_remove --- remove the index from the array */
+
+static NODE **
+dyn_array_remove(NODE *symbol, NODE *subs)
+{
+       array_t *av = (array_t *) symbol->xarray;
+
+       if (av && av->store_func) {
+               symbol->xarray = NULL;
+               (*av->store_func)(symbol, subs, NULL, av->data);
+               symbol->xarray = (NODE *) av;
+       }
+       return SUPER(aremove)(symbol, subs);
+}
+
+/* dyn_array_clear --- flush all the values in symbol[] */
+
+static NODE **
+dyn_array_clear(NODE *symbol, NODE *subs)
+{
+       array_t *av = (array_t *) symbol->xarray;
+
+       if (av && av->store_func) {
+               symbol->xarray = NULL;
+               (*av->store_func)(symbol, NULL, NULL, av->data);
+               symbol->xarray = (NODE *) av;
+       }
+       return SUPER(aclear)(symbol, subs);
+}
+
+/* dyn_array_list --- return a list of items in symbol[] */
+
+static NODE **
+dyn_array_list(NODE *symbol, NODE *subs)
+{
+       return SUPER(alist)(symbol, subs);
+}
+
+/* dyn_array_copy --- duplicate the array */
+
+static NODE **
+dyn_array_copy(NODE *symbol, NODE *subs)
+{
+       return SUPER(acopy)(symbol, subs);
+}
+
+/* register_array_s --- attach the specified routine(s) to an array */
+
+static void
+register_array_s(NODE *symbol, Fetch_func_t fetch_func,
+                       Store_func_t store_func, Load_func_t load_func, void 
*data)
+{
+       array_t *av;
+
+       if (symbol->type != Node_var_array)
+               fatal(_("register_array_s: argument is not an array"));
+
+       if (symbol->array_funcs == deferred_array_func
+                       || symbol->array_funcs == dyn_array_func)
+               fatal(_("register_array_s: `%s' already is a deferred/dyn 
array"),
+                       array_vname(symbol));
+
+       assoc_clear(symbol);
+       assert(symbol->xarray == NULL);
+       emalloc(av, array_t *, sizeof (array_t), "register_spec_array");
+       av->fetch_func = fetch_func;
+       av->store_func = store_func;
+       av->load_func = load_func;
+       av->data = data;
+       symbol->xarray = (NODE *) av;
+}
+
+/* register_deferred_array --- make the array to be loaded at run-time */
+
+void
+register_deferred_array(NODE *symbol, Load_func_t load_func, void *dq)
+{
+       if (! load_func)
+               fatal(_("register_deferred_array: null load function"));
+       register_array_s(symbol, 0, 0, load_func, dq);
+       symbol->array_funcs = deferred_array_func;
+}
+
+/* register_dyn_array --- attach read and write triggers to an array */
+
+void
+register_dyn_array(NODE *symbol, Fetch_func_t fetch_func,
+               Store_func_t store_func, void *dq)
+{
+       register_array_s(symbol, fetch_func, store_func, 0, dq);
+       symbol->array_funcs = dyn_array_func;
+}
+
+/* unregister_array_s --- un-special the array */
+
+void *
+unregister_array_s(NODE *symbol)
+{
+       void *data = NULL;
+       if (symbol->type != Node_var_array)
+               fatal(_("unregister_array_s: argument is not an array"));
+
+       if (symbol->array_funcs == dyn_array_func
+               || symbol->array_funcs == deferred_array_func
+       ) {
+               array_t *av;
+
+               av = (array_t *) symbol->xarray;
+               assert(av != NULL);
+               data = av->data;
+               efree(av);
+               symbol->array_funcs = str_array_func;
+               symbol->xarray = NULL;
+               /* FIXME: do we assoc_clear the array ? */
+       }
+       return data;
+}
diff --git a/extension/spec_array.h b/extension/spec_array.h
new file mode 100644
index 0000000..f75fc7c
--- /dev/null
+++ b/extension/spec_array.h
@@ -0,0 +1,28 @@
+/*
+ * 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
+ */
+
+
+typedef NODE *(*Fetch_func_t)(NODE *, NODE *, void *);
+typedef void(*Store_func_t)(NODE *, NODE *, NODE *, void *);
+typedef void(*Load_func_t)(NODE *, void *);
+extern void register_dyn_array(NODE *, Fetch_func_t, Store_func_t, void *);
+extern void register_deferred_array(NODE *, Load_func_t, void *);
+extern void *unregister_array_s(NODE *);
diff --git a/extension/steps b/extension/steps
index a6696dd..0cd0042 100755
--- a/extension/steps
+++ b/extension/steps
@@ -13,6 +13,8 @@ gcc -fPIC -shared -Wall -DHAVE_CONFIG_H -c -O -g -I.. 
arrayparm.c
 gcc -fPIC -shared -Wall -DHAVE_CONFIG_H -c -O -g -I.. readfile.c
 gcc -fPIC -shared -Wall -DHAVE_CONFIG_H -c -O -g -I.. testarg.c
 gcc -fPIC -shared -Wall -DHAVE_CONFIG_H -c -O -g -I.. rwarray.c
+gcc -fPIC -shared -Wall -DHAVE_CONFIG_H -c -O -g -I.. spec_array.c
+gcc -fPIC -shared -Wall -DHAVE_CONFIG_H -c -O -g -I.. sparr.c
 ld -o dl.so -shared dl.o
 ld -o filefuncs.so -shared filefuncs.o
 ld -o fork.so -shared fork.o
@@ -21,3 +23,4 @@ ld -o arrayparm.so -shared arrayparm.o
 ld -o readfile.so -shared readfile.o
 ld -o testarg.so -shared testarg.o
 ld -o rwarray.so -shared rwarray.o
+ld -o sparr.so -shared sparr.o spec_array.o
diff --git a/extension/testsparr.awk b/extension/testsparr.awk
new file mode 100644
index 0000000..b31409f
--- /dev/null
+++ b/extension/testsparr.awk
@@ -0,0 +1,17 @@
+# ../gawk -lsparr -f testsparr.awk
+BEGIN {
+       print SYS["time"]
+       SYS["readline"] = "sparr.c";
+       printf("File %s has %d lines\n", SYS["readline"], length(READLINE)) 
+       SYS["readline"] = "testsparr.awk";
+       printf("File %s has %d lines\n", SYS["readline"], length(READLINE)) 
+       for (i = 1; i in READLINE; i++)
+               print READLINE[i]
+
+       system("sleep 1")
+
+#      PROCINFO["/dev/stdin", "READ_TIMEOUT"] = 1000
+#      getline < "/dev/stdin"
+
+       print SYS["time"]
+}

-----------------------------------------------------------------------

Summary of changes:
 extension/ChangeLog                |    5 +
 extension/sparr.c                  |  162 +++++++++++++++
 extension/spec_array.c             |  384 ++++++++++++++++++++++++++++++++++++
 random.h => extension/spec_array.h |   36 +---
 extension/steps                    |    3 +
 extension/testsparr.awk            |   17 ++
 6 files changed, 578 insertions(+), 29 deletions(-)
 create mode 100644 extension/sparr.c
 create mode 100644 extension/spec_array.c
 copy random.h => extension/spec_array.h (54%)
 create mode 100644 extension/testsparr.awk


hooks/post-receive
-- 
gawk



reply via email to

[Prev in Thread] Current Thread [Next in Thread]