94e365c612
* sysdeps/gnu/Makefile (libdl-routines): Add eval. 1999-07-06 Zack Weinberg <zack@rabi.columbia.edu> * dlfcn: New directory. Move the following files from elf: dladdr.c, dlclose.c, dlerror.c, dlfcn.h, dlopen.c, dlopenold.c, dlsym.c, dlvsym.c. * dlfcn/Makefile: New file. * dlfcn/Versions: New file. * dlfcn/dlsym.c: All ELF-specific code split out to new function _dl_sym. * dlfcn/dlvsym.c: All ELF-specific code split out to new function _dl_vsym. * elf/dl-sym.c: New file. _dl_sym and _dl_vsym are implemented here. * dlfcn/dladdr.c: Remove all references to ELF data structures or headers. * dlfcn/dlclose.c: Likewise. * dlfcn/dlerror.c: Likewise. * dlfcn/dlopen.c: Likewise. * dlfcn/dlopenold.c: Likewise. * Makeconfig (dlfcn): New variable - set to `dlfcn' if elf is yes, empty otherwise. (libdl): Set to dlfcn/libdl.so or libdl.a if elf is yes, depending on build-shared. (subdirs): Add $(dlfcn). (rpath-dirs): Add dlfcn. * elf/Makefile: Remove all references to libdl or its components, except the ones relating to the test cases. (routines): Add dl-sym. * elf/Versions (libc): Add _dl_sym and _dl_vsym for GLIBC_2.2. (libdl): Delete. * elf/dl-close.c (_dl_close): Change argument to void *. * elf/dl-open.c (_dl_open): Change return type to void *. * elf/eval.c: Removed. * elf/ldsodefs.h: Move prototypes of _dl_catch_error, _dlerror_run, _dl_open, _dl_close, _dl_addr, and _dl_mcount_wrapper_check to include/dlfcn.h. Delete _CALL_DL_FCT macro. * include/dlfcn.h: Also prototype _dl_sym and _dl_vsym here. Include real header from dlfcn directory. * include/ldsodefs.h: Removed. * grp/initgroups.c: Use DL_CALL_FCT not _CALL_DL_FCT. * nss/getXXbyYY_r.c: Likewise. * nss/getXXent_r.c: Likewise. * iconv/gconv.c: Likewise. Don't include ldsodefs.h. * iconv/gconv_db.c: Likewise. Don't include ldsodefs.h. * iconv/skeleton.c: Don't include ldsodefs.h. * nss/nsswitch.h: Don't include ldsodefs.h. Include dlfcn.h. 1999-07-07 Ulrich Drepper <drepper@cygnus.com>
139 lines
3.0 KiB
C
139 lines
3.0 KiB
C
/* You don't really want to know what this hack is for.
|
|
Copyright (C) 1996, 1997 Free Software Foundation, Inc.
|
|
This file is part of the GNU C Library.
|
|
|
|
The GNU C Library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public License as
|
|
published by the Free Software Foundation; either version 2 of the
|
|
License, or (at your option) any later version.
|
|
|
|
The GNU C Library 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
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public
|
|
License along with the GNU C Library; see the file COPYING.LIB. If not,
|
|
write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
Boston, MA 02111-1307, USA. */
|
|
|
|
#include <stdio.h>
|
|
#include <ctype.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
#include <dlfcn.h>
|
|
|
|
static void *funcall (char **stringp);
|
|
static void *eval (char **stringp);
|
|
|
|
static void *
|
|
funcall (char **stringp)
|
|
{
|
|
void *args[strlen (*stringp)], **ap = args;
|
|
void *argcookie = &args[1];
|
|
|
|
do
|
|
{
|
|
/* Evaluate the next token. */
|
|
*ap++ = eval (stringp);
|
|
|
|
/* Whitespace is irrelevant. */
|
|
while (isspace (**stringp))
|
|
++*stringp;
|
|
|
|
/* Terminate at closing paren or end of line. */
|
|
} while (**stringp != '\0' && **stringp != ')');
|
|
if (**stringp != '\0')
|
|
/* Swallow closing paren. */
|
|
++*stringp;
|
|
|
|
if (args[0] == NULL)
|
|
{
|
|
static const char unknown[] = "Unknown function\n";
|
|
write (1, unknown, sizeof unknown - 1);
|
|
return NULL;
|
|
}
|
|
|
|
/* Do it to it. */
|
|
__builtin_return (__builtin_apply (args[0],
|
|
&argcookie,
|
|
(char *) ap - (char *) &args[1]));
|
|
}
|
|
|
|
static void *
|
|
eval (char **stringp)
|
|
{
|
|
void *value;
|
|
char *p = *stringp, c;
|
|
|
|
/* Whitespace is irrelevant. */
|
|
while (isspace (*p))
|
|
++p;
|
|
|
|
switch (*p)
|
|
{
|
|
case '"':
|
|
/* String constant. */
|
|
value = ++p;
|
|
do
|
|
if (*p == '\\')
|
|
{
|
|
switch (*strcpy (p, p + 1))
|
|
{
|
|
case 't':
|
|
*p = '\t';
|
|
break;
|
|
case 'n':
|
|
*p = '\n';
|
|
break;
|
|
}
|
|
++p;
|
|
}
|
|
while (*p != '\0' && *p++ != '"');
|
|
if (p[-1] == '"')
|
|
p[-1] = '\0';
|
|
break;
|
|
|
|
case '(':
|
|
*stringp = ++p;
|
|
return funcall (stringp);
|
|
|
|
default:
|
|
/* Try to parse it as a number. */
|
|
value = (void *) strtol (p, stringp, 0);
|
|
if (*stringp != p)
|
|
return value;
|
|
|
|
/* Anything else is a symbol that produces its address. */
|
|
value = p;
|
|
do
|
|
++p;
|
|
while (*p != '\0' && !isspace (*p) && (!ispunct (*p) || *p == '_'));
|
|
c = *p;
|
|
*p = '\0';
|
|
value = dlsym (NULL, value);
|
|
*p = c;
|
|
break;
|
|
}
|
|
|
|
*stringp = p;
|
|
return value;
|
|
}
|
|
|
|
|
|
void
|
|
_start (void)
|
|
{
|
|
char *buf = NULL;
|
|
size_t bufsz = 0;
|
|
|
|
while (__getdelim (&buf, &bufsz, '\n', stdin) > 0)
|
|
{
|
|
char *p = buf;
|
|
eval (&p);
|
|
}
|
|
|
|
exit (0);
|
|
}
|