"Fossies" - the Fresh Open Source Software Archive

Member "gawk-5.1.0/ext.c" (20 Mar 2020, 6989 Bytes) of package /linux/misc/gawk-5.1.0.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "ext.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 5.0.1_vs_5.1.0.

    1 /*
    2  * ext.c - Builtin function that links external gawk functions and related
    3  *     utilities.
    4  *
    5  * Christos Zoulas, Thu Jun 29 17:40:41 EDT 1995
    6  * Arnold Robbins, update for 3.1, Mon Nov 23 12:53:39 EST 1998
    7  */
    8 
    9 /*
   10  * Copyright (C) 1995 - 2001, 2003-2014, 2016-2020,
   11  * the Free Software Foundation, Inc.
   12  *
   13  * This file is part of GAWK, the GNU implementation of the
   14  * AWK Programming Language.
   15  *
   16  * GAWK is free software; you can redistribute it and/or modify
   17  * it under the terms of the GNU General Public License as published by
   18  * the Free Software Foundation; either version 3 of the License, or
   19  * (at your option) any later version.
   20  *
   21  * GAWK is distributed in the hope that it will be useful,
   22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   24  * GNU General Public License for more details.
   25  *
   26  * You should have received a copy of the GNU General Public License
   27  * along with this program; if not, write to the Free Software
   28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
   29  */
   30 
   31 #include "awk.h"
   32 extern SRCFILE *srcfiles;
   33 
   34 #ifdef DYNAMIC
   35 
   36 #include <dlfcn.h>
   37 
   38 #define INIT_FUNC   "dl_load"
   39 
   40 /* load_ext --- load an external library */
   41 
   42 void
   43 load_ext(const char *lib_name)
   44 {
   45     int (*install_func)(const gawk_api_t *const, awk_ext_id_t);
   46     void *dl;
   47     int flags = RTLD_LAZY;
   48     int *gpl_compat;
   49 
   50     if (do_sandbox)
   51         fatal(_("extensions are not allowed in sandbox mode"));
   52 
   53     if (do_traditional || do_posix)
   54         fatal(_("-l / @load are gawk extensions"));
   55 
   56     if (lib_name == NULL)
   57         fatal(_("load_ext: received NULL lib_name"));
   58 
   59     if ((dl = dlopen(lib_name, flags)) == NULL)
   60         fatal(_("load_ext: cannot open library `%s': %s"), lib_name,
   61               dlerror());
   62 
   63     /* Per the GNU Coding standards */
   64     gpl_compat = (int *) dlsym(dl, "plugin_is_GPL_compatible");
   65     if (gpl_compat == NULL)
   66         fatal(_("load_ext: library `%s': does not define `plugin_is_GPL_compatible': %s"),
   67                 lib_name, dlerror());
   68 
   69     install_func = (int (*)(const gawk_api_t *const, awk_ext_id_t))
   70                 dlsym(dl, INIT_FUNC);
   71     if (install_func == NULL)
   72         fatal(_("load_ext: library `%s': cannot call function `%s': %s"),
   73                 lib_name, INIT_FUNC, dlerror());
   74 
   75     if (install_func(& api_impl, NULL /* ext_id */) == 0)
   76         warning(_("load_ext: library `%s' initialization routine `%s' failed"),
   77                 lib_name, INIT_FUNC);
   78 }
   79 
   80 /* make_builtin --- register name to be called as func with a builtin body */
   81 
   82 awk_bool_t
   83 make_builtin(const char *name_space, const awk_ext_func_t *funcinfo)
   84 {
   85     NODE *symbol, *f;
   86     INSTRUCTION *b;
   87     const char *name = funcinfo->name;
   88     int count = funcinfo->max_expected_args;
   89     const char *install_name;
   90 
   91     if (name == NULL || *name == '\0')
   92         fatal(_("make_builtin: missing function name"));
   93 
   94     if (! is_valid_identifier(name))
   95         return awk_false;
   96 
   97     assert(name_space != NULL);
   98     if (name_space[0] == '\0' || strcmp(name_space, awk_namespace) == 0) {
   99         if (check_special(name) >= 0)
  100             fatal(_("make_builtin: cannot use gawk built-in `%s' as function name"), name);
  101 
  102         f = lookup(name);
  103         install_name = estrdup(name, strlen(name));
  104     } else {
  105         if (! is_valid_identifier(name_space))
  106             return awk_false;
  107 
  108         if (check_special(name_space) >= 0)
  109             fatal(_("make_builtin: cannot use gawk built-in `%s' as namespace name"), name_space);
  110         if (check_special(name) >= 0)
  111             fatal(_("make_builtin: cannot use gawk built-in `%s' as function name"), name);
  112 
  113         size_t len = strlen(name_space) + 2 + strlen(name) + 1;
  114         char *buf;
  115         emalloc(buf, char *, len, "make_builtin");
  116         sprintf(buf, "%s::%s", name_space, name);
  117         install_name = buf;
  118 
  119         f = lookup(install_name);
  120     }
  121 
  122     if (f != NULL) {
  123         // found it, but it shouldn't be there if we want to install this function
  124         if (f->type == Node_func) {
  125             /* user-defined function */
  126             fatal(_("make_builtin: cannot redefine function `%s'"), name);
  127         } else if (f->type == Node_ext_func) {
  128             /* multiple extension() calls etc. */
  129             if (do_lint)
  130                 lintwarn(_("make_builtin: function `%s' already defined"), name);
  131             return awk_false;
  132         } else
  133             /* variable name etc. */
  134             fatal(_("make_builtin: function name `%s' previously defined"), name);
  135     }
  136 
  137     if (count < 0)
  138         fatal(_("make_builtin: negative argument count for function `%s'"),
  139                 name);
  140 
  141     b = bcalloc(Op_symbol, 1, 0);
  142     b->extfunc = funcinfo->function;
  143     b->c_function = (awk_ext_func_t *) funcinfo;
  144 
  145     /* NB: extension sub must return something */
  146 
  147     symbol = install_symbol(install_name, Node_ext_func);
  148     symbol->code_ptr = b;
  149     track_ext_func(name);
  150     return awk_true;
  151 }
  152 
  153 /* get_argument --- get the i'th argument of a dynamically linked function */
  154 
  155 NODE *
  156 get_argument(int i)
  157 {
  158     NODE *t;
  159     int arg_count;
  160     INSTRUCTION *pc;
  161 
  162     pc = TOP()->code_ptr;       /* Op_ext_builtin instruction */
  163     arg_count = pc->expr_count; /* # of arguments supplied */
  164 
  165     if (i < 0 || i >= arg_count)
  166         return NULL;
  167 
  168     t = PEEK(arg_count - i);
  169     if (t->type == Node_param_list)
  170         t = GET_PARAM(t->param_cnt);
  171 
  172     if (t->type == Node_array_ref) {
  173         if (t->orig_array->type == Node_var) {
  174             /* already a scalar, can no longer use it as array */
  175             t->type = Node_var;
  176             t->var_value = Nnull_string;
  177             return t;
  178         }
  179         return t->orig_array;   /* Node_var_new or Node_var_array */
  180     }
  181     if (t->type == Node_var)    /* See Case Node_var in setup_frame(), eval.c */
  182         return Nnull_string;
  183     /* Node_var_new, Node_var_array or Node_val */
  184     return t;
  185 }
  186 
  187 
  188 /*
  189  * get_actual_argument --- get the i'th scalar or array argument of a
  190  *  dynamically linked function.
  191  */
  192 
  193 NODE *
  194 get_actual_argument(NODE *t, int i, bool want_array)
  195 {
  196     char *fname;
  197     INSTRUCTION *pc;
  198 
  199     pc = TOP()->code_ptr;   /* Op_ext_builtin instruction */
  200     fname = (pc + 1)->func_name;
  201 
  202     if (t->type == Node_var_new) {
  203         if (want_array)
  204             return force_array(t, false);
  205         else {
  206             t->type = Node_var;
  207             t->var_value = dupnode(Nnull_string);
  208             return t->var_value;
  209         }
  210     }
  211 
  212     if (want_array) {
  213         if (t->type != Node_var_array)
  214             fatal(_("function `%s': argument #%d: attempt to use scalar as an array"),
  215                 fname, i + 1);
  216     } else {
  217         if (t->type != Node_val)
  218             fatal(_("function `%s': argument #%d: attempt to use array as a scalar"),
  219                 fname, i + 1);
  220     }
  221     assert(t->type == Node_var_array || t->type == Node_val);
  222     return t;
  223 }
  224 
  225 #else
  226 
  227 /* load_ext --- dummy version if extensions not available */
  228 
  229 void
  230 load_ext(const char *lib_name)
  231 {
  232     fatal(_("dynamic loading of libraries is not supported"));
  233 }
  234 #endif
  235 
  236 /* close_extensions --- execute extension cleanup routines */
  237 
  238 void
  239 close_extensions()
  240 {
  241     SRCFILE *s;
  242 
  243     if (srcfiles == NULL)
  244         return;
  245 
  246     for (s = srcfiles->next; s != srcfiles; s = s->next)
  247         if (s->stype == SRC_EXTLIB && s->fini_func)
  248                         (*s->fini_func)();
  249 }
  250 
  251 /* is_valid_identifier --- return true if name is a valid simple identifier */
  252 
  253 bool
  254 is_valid_identifier(const char *name)
  255 {
  256     const char *sp = name;
  257     int c;
  258 
  259     if (! is_letter(*sp))
  260         return false;
  261 
  262     for (sp++; (c = *sp++) != '\0';) {
  263         if (! is_identchar(c))
  264             return false;
  265     }
  266 
  267     return true;
  268 }