diff options
-rw-r--r-- | extension/ordchr2.c | 107 | ||||
-rw-r--r-- | extension/readfile2.c | 116 | ||||
-rw-r--r-- | gawkapi.c | 13 | ||||
-rw-r--r-- | gawkapi.h | 140 |
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, "") @@ -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; +} @@ -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++ */ |