Main Page | Class List | Directories | File List | Class Members | File Members

ext.c

Go to the documentation of this file.
00001 /*
00002  * ext.c - Builtin function that links external gawk functions and related
00003  *         utilities.
00004  *
00005  * Christos Zoulas, Thu Jun 29 17:40:41 EDT 1995
00006  * Arnold Robbins, update for 3.1, Mon Nov 23 12:53:39 EST 1998
00007  */
00008 
00009 /*
00010  * Copyright (C) 1995 - 2001, 2003 the Free Software Foundation, Inc.
00011  * 
00012  * This file is part of GAWK, the GNU implementation of the
00013  * AWK Programming Language.
00014  * 
00015  * GAWK is free software; you can redistribute it and/or modify
00016  * it under the terms of the GNU General Public License as published by
00017  * the Free Software Foundation; either version 2 of the License, or
00018  * (at your option) any later version.
00019  * 
00020  * GAWK is distributed in the hope that it will be useful,
00021  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00022  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00023  * GNU General Public License for more details.
00024  * 
00025  * You should have received a copy of the GNU General Public License
00026  * along with this program; if not, write to the Free Software
00027  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
00028  */
00029 
00030 #include "awk.h"
00031 
00032 #ifdef DYNAMIC
00033 
00034 #include <dlfcn.h>
00035 
00036 #ifdef __GNUC__
00037 static unsigned long long dummy;        /* fake out gcc for dynamic loading? */
00038 #endif
00039 
00040 extern int errcount;
00041 
00042 /* do_ext --- load an extension */
00043 
00044 NODE *
00045 do_ext(NODE *tree)
00046 {
00047         NODE *obj;
00048         NODE *fun;
00049         NODE *(*func) P((NODE *, void *));
00050         void *dl;
00051         int flags = RTLD_LAZY;
00052 
00053 #ifdef __GNUC__
00054         AWKNUM junk;
00055 
00056         junk = (AWKNUM) dummy;
00057 #endif
00058 
00059         if (do_lint)
00060                 lintwarn(_("`extension' is a gawk extension"));
00061 
00062         if (do_traditional || do_posix) {
00063                 errcount++;
00064                 error(_("`extension' is a gawk extension"));
00065         }
00066 
00067         obj = tree_eval(tree->lnode);
00068         force_string(obj);
00069 
00070 #ifdef RTLD_GLOBAL
00071         flags |= RTLD_GLOBAL;
00072 #endif
00073         if ((dl = dlopen(obj->stptr, flags)) == NULL)
00074                 fatal(_("extension: cannot open `%s' (%s)\n"), obj->stptr,
00075                       dlerror());
00076 
00077         fun = tree_eval(tree->rnode->lnode);
00078         force_string(fun);
00079 
00080         func = (NODE *(*) P((NODE *, void *))) dlsym(dl, fun->stptr);
00081         if (func == NULL)
00082                 fatal(_("extension: library `%s': cannot call function `%s' (%s)\n"),
00083                                 obj->stptr, fun->stptr, dlerror());
00084         free_temp(obj);
00085         free_temp(fun);
00086 
00087         return (*func)(tree, dl);
00088 }
00089 
00090 /* make_builtin --- register name to be called as func with a builtin body */
00091 
00092 void
00093 make_builtin(char *name, NODE *(*func) P((NODE *)), int count)
00094 {
00095         NODE *p, *b, *f;
00096         char **vnames, *parm_names, *sp;
00097         char buf[200];
00098         int space_needed, i;
00099 
00100         /* count parameters, create artificial list of param names */
00101         space_needed = 0;
00102         for (i = 0; i < count; i++) {
00103                 sprintf(buf, "p%d", i);
00104                 space_needed += strlen(buf) + 1;
00105         }
00106         emalloc(parm_names, char *, space_needed, "make_builtin");
00107         emalloc(vnames, char **, count * sizeof(char  *), "make_builtin");
00108         sp = parm_names;
00109         for (i = 0; i < count; i++) {
00110                 sprintf(sp, "p%d",i);
00111                 vnames[i] = sp;
00112                 sp += strlen(sp) + 1;
00113         }
00114 
00115         getnode(p);
00116         p->type = Node_param_list;
00117         p->flags |= FUNC;
00118         p->rnode = NULL;
00119         p->param = name;
00120         p->param_cnt = count;
00121 #if 0
00122         /* setting these  blows away the param_cnt. dang unions! */
00123         p->source_line = __LINE__;
00124         p->source_file = __FILE__;
00125 #endif
00126 
00127         getnode(b);
00128         b->type = Node_builtin;
00129         b->builtin = func;
00130         b->subnode = p;
00131         b->source_line = __LINE__;
00132         b->source_file = __FILE__;
00133 
00134         f = node(p, Node_func, b);
00135         f->parmlist = vnames;
00136         install(name, f);
00137 }
00138 
00139 /* get_argument --- Get the n'th argument of a dynamically linked function */
00140 
00141 NODE *
00142 get_argument(NODE *tree, int i)
00143 {
00144         extern NODE **stack_ptr;
00145 
00146         if (i < 0 || i >= tree->param_cnt)
00147                 return NULL;
00148 
00149         tree = stack_ptr[i];
00150         if (tree->lnode == Nnull_string)
00151                 return NULL;
00152 
00153         if (tree->type == Node_array_ref) {
00154                 tree = tree->orig_array;
00155                 return tree;
00156         }
00157 
00158         if (tree->type == Node_var_array)
00159                 return tree;
00160 
00161         return tree->lnode;
00162 }
00163 
00164 /* set_value --- set the return value of a dynamically linked function */
00165 
00166 void
00167 set_value(NODE *tree)
00168 {
00169         extern NODE *ret_node;
00170 
00171         if (tree)
00172                 ret_node = tree;
00173         else
00174                 ret_node = Nnull_string;
00175 }
00176 #else
00177 
00178 /* do_ext --- dummy version if extensions not available */
00179 
00180 NODE *
00181 do_ext(NODE *tree)
00182 {
00183         const char *emsg = _("Operation Not Supported");
00184 
00185         unref(ERRNO_node->var_value);
00186         ERRNO_node->var_value = make_string((char *) emsg, strlen(emsg));
00187         return tmp_number((AWKNUM) -1);
00188 }
00189 #endif

© sourcejam.com 2005-2008