aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArnold D. Robbins <arnold@skeeve.com>2012-05-20 22:26:46 +0300
committerArnold D. Robbins <arnold@skeeve.com>2012-05-20 22:26:46 +0300
commitcd9fdf221c0504639a38e773c3d56a32ae80e2cc (patch)
tree24a71be37fc096f77c3726fd460cc50ac9a44db7
parentab670cb99e104c3718c4c6b343d236898e057634 (diff)
downloadegawk-cd9fdf221c0504639a38e773c3d56a32ae80e2cc.tar.gz
egawk-cd9fdf221c0504639a38e773c3d56a32ae80e2cc.tar.bz2
egawk-cd9fdf221c0504639a38e773c3d56a32ae80e2cc.zip
More extension work.
-rw-r--r--extension/ordchr2.c107
-rw-r--r--extension/readfile2.c116
-rw-r--r--gawkapi.c13
-rw-r--r--gawkapi.h140
4 files changed, 320 insertions, 56 deletions
diff --git a/extension/ordchr2.c b/extension/ordchr2.c
new file mode 100644
index 00000000..1f4a1fcb
--- /dev/null
+++ b/extension/ordchr2.c
@@ -0,0 +1,107 @@
+/*
+ * ordchr.c - Builtin functions that provide ord() and chr() functions.
+ *
+ * Arnold Robbins
+ * arnold@skeeve.com
+ * 8/2001
+ * Revised 6/2004
+ */
+
+/*
+ * Copyright (C) 2001, 2004, 2011 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 <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "gawkapi.h"
+
+static const gawk_api_t *api; /* for convenience macros to work */
+static awk_ext_id_t *ext_id;
+
+int plugin_is_GPL_compatible;
+
+/* do_ord --- return numeric value of first char of string */
+
+static int
+do_ord(int nargs)
+{
+ const awk_value_t *str;
+ awk_value_t result;
+ double ret = -1;
+
+ if (do_lint && nargs > 1)
+ lintwarn(ext_id, "ord: called with too many arguments");
+
+ str = get_curfunc_param(0, AWK_PARAM_STRING);
+ if (str != NULL) {
+ ret = str->str_value.str[0];
+ } else if (do_lint)
+ lintwarn(ext_id, "ord: called with no arguments");
+
+ /* Set the return value */
+ set_return_value(make_number(ret));
+ return 1;
+}
+
+/* do_chr --- turn numeric value into a string */
+
+static int
+do_chr(int nargs)
+{
+ const awk_value_t *num;
+ awk_value_t result;
+ unsigned int ret = 0;
+ double val = 0.0;
+ char str[2];
+
+ str[0] = str[1] = '\0';
+
+ if (do_lint && nargs > 1)
+ lintwarn(ext_id, "chr: called with too many arguments");
+
+ num = get_curfunc_param(0, AWK_PARAM_NUMBER);
+ if (num != NULL) {
+ val = num->num_value;
+ ret = val; /* convert to int */
+ ret &= 0xff;
+ str[0] = ret;
+ str[1] = '\0';
+ } else if (do_lint)
+ lintwarn(ext_id, "chr: called with no arguments");
+
+ /* Set the return value */
+ set_return_value(dup_string(str, 1));
+ return 1;
+}
+
+static awk_ext_func_t func_table[] = {
+ { "ord", do_ord, 1 },
+ { "chr", do_chr, 1 },
+};
+
+/* define the dl_load function using the boilerplate macro */
+
+dl_load_func(api, ext_id, func_table, ord_chr, "")
diff --git a/extension/readfile2.c b/extension/readfile2.c
new file mode 100644
index 00000000..4d8cd245
--- /dev/null
+++ b/extension/readfile2.c
@@ -0,0 +1,116 @@
+/*
+ * readfile.c - Read an entire file into a string.
+ *
+ * Arnold Robbins
+ * Tue Apr 23 17:43:30 IDT 2002
+ * Revised per Peter Tillier
+ * Mon Jun 9 17:05:11 IDT 2003
+ * Revised for new dynamic function facilities
+ * Mon Jun 14 14:53:07 IDT 2004
+ */
+
+/*
+ * Copyright (C) 2002, 2003, 2004, 2011 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 <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "gawkapi.h"
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+static const gawk_api_t *api; /* for convenience macros to work */
+static awk_ext_id_t *ext_id;
+
+int plugin_is_GPL_compatible;
+
+/* do_readfile --- read a file into memory */
+
+static int
+do_readfile(int nargs)
+{
+ const awk_value_t *filename;
+ awk_value_t result;
+ double ret = -1;
+ struct stat sbuf;
+ char *text;
+ int fd;
+
+ if (do_lint && nargs > 1)
+ lintwarn(ext_id, "readfile: called with too many arguments");
+
+ filename = get_curfunc_param(0, AWK_PARAM_STRING);
+ if (filename != NULL) {
+ ret = stat(filename->str_value.str, & sbuf);
+ if (ret < 0) {
+ update_ERRNO_int(errno);
+ goto done;
+ } else if ((sbuf.st_mode & S_IFMT) != S_IFREG) {
+ errno = EINVAL;
+ ret = -1;
+ update_ERRNO_int(errno);
+ goto done;
+ }
+
+ if ((fd = open(filename->str_value.str, O_RDONLY|O_BINARY)) < 0) {
+ ret = -1;
+ update_ERRNO_int(errno);
+ goto done;
+ }
+
+ emalloc(text, char *, sbuf.st_size + 2, "do_readfile");
+ memset(text, '\0', sbuf.st_size + 2);
+
+ if ((ret = read(fd, text, sbuf.st_size)) != sbuf.st_size) {
+ (void) close(fd);
+ ret = -1;
+ update_ERRNO_int(errno);
+ goto done;
+ }
+
+ close(fd);
+ set_return_value(make_string(text, sbuf.st_size));
+ return 1;
+ } else if (do_lint)
+ lintwarn(ext_id, "readfile: called with no arguments");
+
+
+done:
+ /* Set the return value */
+ set_return_value(make_number(ret));
+ return 0;
+}
+
+static awk_ext_func_t func_table[] = {
+ { "readfile", do_readfile, 1 },
+};
+
+/* define the dl_load function using the boilerplate macro */
+
+dl_load_func(api, ext_id, func_table, readfile, "")
diff --git a/gawkapi.c b/gawkapi.c
index 2a9ad927..e1d2a511 100644
--- a/gawkapi.c
+++ b/gawkapi.c
@@ -452,3 +452,16 @@ static gawk_api_t api_impl = {
api_make_string,
api_make_number,
};
+
+/* init_ext_api --- init the extension API */
+
+void
+init_ext_api()
+{
+ api_impl.do_flags[0] = do_lint;
+ api_impl.do_flags[1] = do_traditional;
+ api_impl.do_flags[2] = do_profile;
+ api_impl.do_flags[3] = do_sandbox;
+ api_impl.do_flags[4] = do_debug;
+ api_impl.do_flags[5] = do_mpfr;
+}
diff --git a/gawkapi.h b/gawkapi.h
index 335e9628..76c10260 100644
--- a/gawkapi.h
+++ b/gawkapi.h
@@ -228,6 +228,15 @@ typedef struct gawk_api {
/*
* Lookup a variable, return its value. No messing with the value
* returned. Return value is NULL if the variable doesn't exist.
+ *
+ * Returns a pointer to a static variable. Correct usage is thus:
+ *
+ * awk_value_t val, *vp;
+ * vp = api->sym_lookup(id, name);
+ * if (vp == NULL)
+ * error_code();
+ * val = *vp;
+ * // use val from here on
*/
const awk_value_t *const (*sym_lookup)(awk_ext_id_t id, const char *name);
@@ -241,6 +250,9 @@ typedef struct gawk_api {
/*
* Return the value of an element - read only!
* Use set_array_element to change it.
+ *
+ * As for sym_lookup(), this also returns a static pointer whose
+ * value should be copied before use.
*/
const awk_value_t *const (*get_array_element)(awk_ext_id_t id,
awk_array_t a_cookie, const awk_value_t *const index);
@@ -306,39 +318,55 @@ typedef struct gawk_api {
#define do_debug api->do_flags[gawk_do_debug]
#define do_mpfr api->do_flags[gawk_do_mpfr]
-#define get_curfunc_param api->get_curfunc_param
-#define set_return_value api->set_return_value
+#define get_curfunc_param(count, wanted) \
+ api->get_curfunc_param(ext_id, count, wanted)
+
+#define set_return_value(retval) \
+ api->set_return_value(ext_id, retval)
#define fatal api->api_fatal
#define warning api->api_warning
#define lintwarn api->api_lintwarn
-#define register_open_hook api->register_open_hook
+#define register_open_hook(func) api->register_open_hook(ext_id, func)
-#define update_ERRNO_int api->update_ERRNO_int
-#define update_ERRNO_string api->update_ERRNO_string
+#define update_ERRNO_int(e) api->update_ERRNO_int(ext_id, e)
+#define update_ERRNO_string(str, translate) \
+ api->update_ERRNO_string(ext_id, str, translate)
#define unset_ERRNO api->unset_ERRNO
-#define is_null_string api->is_null_string
+#define add_ext_func(func, ns) api->add_ext_func(ext_id, func, ns)
+#define awk_atexit(funcp, arg0) api->awk_atexit(ext_id, funcp, arg0)
+
+#define sym_lookup(name) api->sym_lookup(ext_id, name)
+#define sym_update(name, value) \
+ api->sym_update(ext_id, name, value)
+
+#define get_array_element(array, element) \
+ api->get_array_element(ext_id, array, element)
+
+#define set_array_element(array, element) \
+ api->set_array_element(ext_id, array, element)
+
+#define del_array_element(array, index) \
+ api->del_array_element(ext_id, array, index)
+
+#define get_element_count(array, count_p) \
+ api->get_element_count(ext_id, array, count_p)
-#define add_ext_func api->add_ext_func
-#define awk_atexit api->awk_atexit
+#define create_array() api->create_array(ext_id)
-#define sym_lookup api->sym_lookup
-#define sym_update api->sym_update
+#define clear_array(array) api->clear_array(ext_id, array)
-#define get_array_element api->get_array_element
-#define set_array_element api->set_array_element
-#define del_array_element api->del_array_element
-#define get_element_count api->get_element_count
-#define clear_array api->clear_array
-#define create_array api->create_array
-#define flatten_array api->flatten_array
-#define release_flattened_array api->release_flattened_array
+#define flatten_array(array, count, data) \
+ api->flatten_array(ext_id, array, count, data)
-#define make_string(id, str, len) api->api_make_string(id, str, len, 0)
-#define dup_string(id, str, len) api->api_make_string(id, str, len, 1)
-#define make_number api->api_make_number
+#define release_flattened_array(array, count, data) \
+ api->release_flattened_array(ext_id, array, count, data)
+
+#define make_string(str, len) api->api_make_string(ext_id, str, len, 0)
+#define dup_string(str, len) api->api_make_string(ext_id, str, len, 1)
+#define make_number(num) api->api_make_number(ext_id, num)
#define emalloc(pointer, type, size, message) \
do { \
@@ -360,48 +388,48 @@ typedef struct gawk_api {
extern int dl_load(const gawk_api_t *const api_p, awk_ext_id_t id);
-
-/* TODO: Turn this into a macro... */
#if 0
/* Boiler plate code: */
-
static gawk_api_t *const api;
static awk_ext_id_t ext_id;
+static awk_ext_func_t func_table[] = {
+ { "name", do_name, 1 },
+ /* ... */
+};
-int dl_load(const gawk_api_t *const api_p, awk_ext_id_t id);
-{
- static awk_ext_func_t func_table[] = {
- { "name", do_name, 1 },
- /* ... */
- };
- size_t i, j;
- int errors = 0;
-
- if (api->major_version != GAWK_API_MAJOR_VERSION
- || api->minor_version < GAWK_API_MINOR_VERSION) {
- fprintf(stderr, "<NAME>: version mismatch with gawk!\n");
- fprintf(stderr, "\tmy version (%d, %d), gawk version (%d, %d)\n",
- GAWK_API_MAJOR_VERSION, GAWK_API_MINOR_VERSION,
- api->major_version, api->minor_version);
- exit(1);
- }
-
- api = api_p;
- ext_id = id;
-
- /* load functions */
- for (i = 0, j = sizeof(func_table) / sizeof(func_table[0]); i < j; i++) {
- if (! add_ext_func(ext_id, & func_table[i], "" /* "NAME" */)) {
- warning(ext_id, "<NAME>: could not add %s\n",
- func_table[i].name);
- errors++;
- }
- }
-
- return (errors == 0);
-}
+dl_load_func(api, ext_id, func_table, some_name, "name_space_in_quotes")
#endif
+#define dl_load_func(global_api_p, global_ext_id, func_table, module, name_space) \
+int dl_load(const gawk_api_t *const api_p, awk_ext_id_t id) \
+{ \
+ size_t i, j; \
+ int errors = 0; \
+ \
+ if (api->major_version != GAWK_API_MAJOR_VERSION \
+ || api->minor_version < GAWK_API_MINOR_VERSION) { \
+ fprintf(stderr, #module ": version mismatch with gawk!\n"); \
+ fprintf(stderr, "\tmy version (%d, %d), gawk version (%d, %d)\n", \
+ GAWK_API_MAJOR_VERSION, GAWK_API_MINOR_VERSION, \
+ api->major_version, api->minor_version); \
+ exit(1); \
+ } \
+ \
+ global_api_p = api_p; \
+ global_ext_id = id; \
+\
+ /* load functions */ \
+ for (i = 0, j = sizeof(func_table) / sizeof(func_table[0]); i < j; i++) { \
+ if (! add_ext_func(& func_table[i], name_space)) { \
+ warning(ext_id, #module ": could not add %s\n", \
+ func_table[i].name); \
+ errors++; \
+ } \
+ } \
+\
+ return (errors == 0); \
+}
+
#ifdef __cplusplus
}
#endif /* C++ */