* 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>
This commit is contained in:
Ulrich Drepper 1999-07-07 18:39:33 +00:00
parent 2556bfe6fd
commit 94e365c612
31 changed files with 674 additions and 367 deletions

View File

@ -1,3 +1,59 @@
1999-07-07 Ulrich Drepper <drepper@cygnus.com>
* 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>
* sysdeps/generic/setenv.c: Describe problem.

View File

@ -415,7 +415,7 @@ else
default-rpath = $(libdir)
endif
# This is how to find at build-time things that will be installed there.
rpath-dirs = math elf nss nis db2 rt resolv
rpath-dirs = math elf dlfcn nss nis db2 rt resolv
rpath-link = \
$(common-objdir):$(subst $(empty) ,:,$(patsubst ../$(subdir),.,$(rpath-dirs:%=$(common-objpfx)%)))
elfobjdir := $(patsubst ../$(subdir),.,$(common-objpfx)elf)
@ -746,6 +746,19 @@ endif
-include $(common-objpfx)sysd-dirs
ifeq ($(elf),yes)
dlfcn = dlfcn
ifeq ($(build-shared),yes)
libdl = $(common-objpfx)dlfcn/libdl.so$(libdl.so-version)
else
libdl = $(common-objpfx)dlfcn/libdl.a
endif
else
# No ELF - no libdl, at least for now.
dlfcn =
libdl =
endif
# These are the subdirectories containing the library source. The order
# is more or less arbitrary. The sorting step will take care of the
# dependencies. Only the $(binfmt-subdir) should always be kept at the
@ -755,7 +768,7 @@ all-subdirs = csu assert ctype db db2 locale intl catgets math setjmp signal\
grp pwd posix io termios resource misc socket sysvipc gmon \
gnulib iconv iconvdata wctype manual shadow md5-crypt po argp \
$(add-ons) nss localedata timezone rt debug $(sysdep-subdirs) \
$(binfmt-subdir)
$(dlfcn) $(binfmt-subdir)
all-subdirs := $(filter-out $(sysdep-inhibit-subdirs),$(all-subdirs))
ifeq ($(sysd-dirs-done),t)

34
dlfcn/Makefile Normal file
View File

@ -0,0 +1,34 @@
# Copyright (C) 1995, 1996, 1997, 1998, 1999 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.
subdir := dlfcn
headers := dlfcn.h
extra-libs := libdl
libdl-routines := dlopen dlclose dlsym dlvsym dlerror dladdr
distribute := dlopenold.c
extra-libs-others := libdl
include ../Makeconfig
ifeq ($(versioning),yes)
libdl-routines += dlopenold
libdl-shared-only-routines := dlopenold
endif
include ../Rules

8
dlfcn/Versions Normal file
View File

@ -0,0 +1,8 @@
libdl {
GLIBC_2.0 {
dladdr; dlclose; dlerror; dlopen; dlsym;
}
GLIBC_2.1 {
dlopen; dlvsym;
}
}

View File

@ -1,5 +1,5 @@
/* Locate the shared object symbol nearest a given address.
Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
Copyright (C) 1996, 1997, 1998, 1999 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
@ -18,9 +18,6 @@
Boston, MA 02111-1307, USA. */
#include <dlfcn.h>
#include <stddef.h>
#include <elf/ldsodefs.h>
int
dladdr (const void *address, Dl_info *info)

View File

@ -1,5 +1,5 @@
/* Close a handle opened by `dlopen'.
Copyright (C) 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
Copyright (C) 1995, 1996, 1997, 1998, 1999 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
@ -18,7 +18,6 @@
Boston, MA 02111-1307, USA. */
#include <dlfcn.h>
#include <elf/ldsodefs.h>
static void
dlclose_doit (void *handle)

View File

@ -22,8 +22,6 @@
#include <stdlib.h>
#include <string.h>
#include <bits/libc-lock.h>
#include <elf/ldsodefs.h>
/* Type for storing results of dynamic loading actions. */
struct dl_action_result

100
dlfcn/dlfcn.h Normal file
View File

@ -0,0 +1,100 @@
/* User functions for run-time dynamic loading.
Copyright (C) 1995, 1996, 1997, 1998, 1999 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. */
#ifndef _DLFCN_H
#define _DLFCN_H 1
#include <features.h>
#define __need_NULL
#include <stddef.h>
/* Collect various system dependent definitions and declarations. */
#include <bits/dlfcn.h>
/* If the first argument of `dlsym' or `dlvsym' is set to RTLD_NEXT
the run-time address of the symbol called NAME in the next shared
object is returned. The "next" relation is defined by the order
the shared objects were loaded. */
#define RTLD_NEXT ((void *) -1l)
/* If the first argument to `dlsym' or `dlvsym' is set to RTLD_DEFAULT
the run-time address of the symbol called NAME in the global scope
is returned. */
#define RTLD_DEFAULT NULL
__BEGIN_DECLS
/* Open the shared object FILE and map it in; return a handle that can be
passed to `dlsym' to get symbol values from it. */
extern void *dlopen __P ((__const char *__file, int __mode));
/* Unmap and close a shared object opened by `dlopen'.
The handle cannot be used again after calling `dlclose'. */
extern int dlclose __P ((void *__handle));
/* Find the run-time address in the shared object HANDLE refers to
of the symbol called NAME. */
extern void *dlsym __P ((void *__restrict __handle,
__const char *__restrict __name));
#ifdef __USE_GNU
/* Find the run-time address in the shared object HANDLE refers to
of the symbol called NAME with VERSION. */
extern void *dlvsym __P ((void *__restrict __handle,
__const char *__restrict __name,
__const char *__restrict __version));
#endif
/* When any of the above functions fails, call this function
to return a string describing the error. Each call resets
the error string so that a following call returns null. */
extern char *dlerror __P ((void));
#ifdef __USE_GNU
/* Fill in *INFO with the following information about ADDRESS.
Returns 0 iff no shared object's segments contain that address. */
typedef struct
{
__const char *dli_fname; /* File name of defining object. */
void *dli_fbase; /* Load address of that object. */
__const char *dli_sname; /* Name of nearest symbol. */
void *dli_saddr; /* Exact value of nearest symbol. */
} Dl_info;
extern int dladdr __P ((const void *__address, Dl_info *__info));
/* To support profiling of shared objects it is a good idea to call
the function found using `dlsym' using the following macro since
these calls do not use the PLT. But this would mean the dynamic
loader has no chance to find out when the function is called. The
macro applies the necessary magic so that profiling is possible.
Rewrite
foo = (*fctp) (arg1, arg2);
into
foo = DL_CALL_FCT (fctp, (arg1, arg2));
*/
# define DL_CALL_FCT(fctp, args) \
(_dl_mcount_wrapper_check (fctp), (*(fctp)) args)
/* This function calls the profiling functions. */
extern void _dl_mcount_wrapper_check __P ((void *__selfpc));
#endif
__END_DECLS
#endif /* dlfcn.h */

View File

@ -18,8 +18,6 @@
Boston, MA 02111-1307, USA. */
#include <dlfcn.h>
#include <stddef.h>
#include <elf/ldsodefs.h>
struct dlopen_args
{
@ -27,12 +25,11 @@ struct dlopen_args
const char *file;
int mode;
/* The return value of dlopen_doit. */
struct link_map *new;
void *new;
/* Address of the caller. */
const void *caller;
};
static void
dlopen_doit (void *a)
{

View File

@ -18,8 +18,6 @@
Boston, MA 02111-1307, USA. */
#include <dlfcn.h>
#include <stddef.h>
#include <elf/ldsodefs.h>
/* This file is for compatibility with glibc 2.0. Compile it only if
versioning is used. */
@ -31,7 +29,7 @@ struct dlopen_args
const char *file;
int mode;
/* The return value of dlopen_doit. */
struct link_map *new;
void *new;
/* Address of the caller. */
const void *caller;
};
@ -45,7 +43,6 @@ dlopen_doit (void *a)
args->new = _dl_open (args->file ?: "", args->mode, args->caller);
}
void *
__dlopen_nocheck (const char *file, int mode)
{

51
dlfcn/dlsym.c Normal file
View File

@ -0,0 +1,51 @@
/* Look up a symbol in a shared object loaded by `dlopen'.
Copyright (C) 1995, 1996, 1997, 1998, 1999 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 <dlfcn.h>
struct dlsym_args
{
/* The arguments to dlsym_doit. */
void *handle;
const char *name;
void *who;
/* The return value of dlsym_doit. */
void *sym;
};
static void
dlsym_doit (void *a)
{
struct dlsym_args *args = (struct dlsym_args *) a;
args->sym = _dl_sym (args->handle, args->name, args->who);
}
void *
dlsym (void *handle, const char *name)
{
struct dlsym_args args;
args.who = __builtin_return_address (0);
args.handle = handle;
args.name = name;
return (_dlerror_run (dlsym_doit, &args) ? NULL : args.sym);
}

55
dlfcn/dlvsym.c Normal file
View File

@ -0,0 +1,55 @@
/* Look up a versioned symbol in a shared object loaded by `dlopen'.
Copyright (C) 1995, 1996, 1997, 1998, 1999 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 <dlfcn.h>
struct dlvsym_args
{
/* The arguments to dlvsym_doit. */
void *handle;
const char *name;
const char *version;
void *who;
/* The return values of dlvsym_doit. */
void *sym;
};
static void
dlvsym_doit (void *a)
{
struct dlvsym_args *args = (struct dlvsym_args *)a;
args->sym = _dl_vsym (args->handle, args->name, args->version, args->who);
}
void *
__dlvsym (void *handle, const char *name, const char *version_str)
{
struct dlvsym_args args;
args.handle = handle;
args.name = name;
args.who = __builtin_return_address (0);
args.version = version_str;
return (_dlerror_run (dlvsym_doit, &args) ? NULL : args.sym);
}
weak_alias (__dlvsym, dlvsym)

View File

@ -22,7 +22,7 @@ subdir := elf
headers = elf.h bits/elfclass.h bits/dlfcn.h link.h dlfcn.h
routines = $(dl-routines) dl-open dl-close dl-symbol dl-support \
dl-addr enbl-secure dl-profstub dl-origin dl-libc
dl-addr enbl-secure dl-profstub dl-origin dl-libc dl-sym
# The core dynamic linking functions are in libc for the static and
# profiled libraries.
@ -35,24 +35,16 @@ elide-routines.os = $(dl-routines) dl-support enbl-secure
# ld.so uses those routines, plus some special stuff for being the program
# interpreter and operating independent of libc.
rtld-routines := rtld $(dl-routines) dl-sysdep dl-environ dl-minimal
distribute = $(rtld-routines:=.c) dynamic-link.h do-rel.h dl-machine.h \
dl-hash.h soinit.c sofini.c ldd.bash.in eval.c \
genrtldtbl.awk atomicity.h dl-procinfo.h ldsodefs.h \
dl-librecon.h interp.c sln.c dl-dst.h hp-timing.h \
testobj1.c testobj2.c testobj3.c testobj4.c testobj5.c \
testobj6.c testobj1_1.c failobj.c do-lookup.h \
gen-trusted-dirs.awk
distribute := $(rtld-routines:=.c) dynamic-link.h do-rel.h dl-machine.h \
dl-hash.h soinit.c sofini.c ldd.bash.in \
genrtldtbl.awk atomicity.h dl-procinfo.h ldsodefs.h \
dl-librecon.h interp.c sln.c dl-dst.h hp-timing.h \
do-lookup.h sprof.c gen-trusted-dirs.awk \
testobj1.c testobj2.c testobj3.c testobj4.c testobj5.c \
testobj6.c testobj1_1.c failobj.c
include ../Makeconfig
extra-libs = libdl
extra-libs-others = $(extra-libs)
libdl-routines := dlopen dlclose dlsym dlvsym dlerror dladdr
ifeq ($(versioning),yes)
libdl-routines += dlopenold
libdl-shared-only-routines := dlopenold
endif
before-compile = $(objpfx)trusted-dirs.h
ifeq ($(versioning),yes)
@ -60,7 +52,7 @@ ld-map = $(common-objpfx)ld.so.map
endif
ifeq (yes,$(build-shared))
extra-objs = $(rtld-routines:=.os) soinit.os sofini.os eval.os interp.os
extra-objs = $(rtld-routines:=.os) soinit.os sofini.os interp.os
generated = librtld.os dl-allobjs.os ld.so trusted-dirs.h trusted-dirs.st
install-others = $(inst_slibdir)/$(rtld-installed-name)
install-bin = ldd
@ -85,15 +77,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
testobj1_1 failobj
extra-objs += $(modules-names:=.os)
ifeq ($(build-shared),yes)
libdl = $(objpfx)libdl.so$(libdl.so-version)
else
libdl = $(objpfx)libdl.a
endif
include ../Rules
ifeq (yes,$(build-shared))
# Make sure these things are built in the `make lib' pass so they can be used
# to run programs during the `make others' pass.
@ -163,10 +148,6 @@ $(objpfx)trusted-dirs.st: Makefile $(..)Makeconfig
CPPFLAGS-dl-load.c = -I$(objpfx).
CFLAGS-dl-load.c += -Wno-uninitialized
# Specify the dependencies of libdl.so; its commands come from the generic
# rule to build a shared library.
$(objpfx)libdl.so: $(objpfx)libdl_pic.a $(common-objpfx)libc.so $(objpfx)ld.so
ifeq (yes,$(build-shared))
$(inst_slibdir)/$(rtld-version-installed-name): $(objpfx)ld.so $(+force)
$(do-install-program)
@ -209,9 +190,8 @@ $(objpfx)ldd: ldd.bash.in $(common-objpfx)soversions.mk \
chmod 555 $@.new
mv -f $@.new $@
$(objpfx)sprof: $(libdl)
test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(modules-names)))
generated += $(addsuffix .so,$(modules-names))
@ -251,14 +231,9 @@ $(objpfx)loadfail.out: $(objpfx)failobj.so
$(objpfx)multiload: $(libdl)
LDFLAGS-multiload = -rdynamic
CFLAGS-multiload.c = -DOBJDIR=\"$(elf-objpfx)\"
CFLAGS-multiload.c = -DOBJDIR=\"$(objpfx)\"
$(objpfx)multiload.out: $(objpfx)testobj1.so
$(objpfx)origtest: $(libdl)
$(objpfx)origtest.out: $(objpfx)testobj1.so
# muwahaha
LDFLAGS-dl.so = -Wl,-dynamic-linker,$(slibdir)/$(rtld-installed-name)
$(objpfx)libdl.so: $(objpfx)eval.os

View File

@ -7,6 +7,10 @@ libc {
# functions used in other libraries
_dl_mcount_wrapper; _dl_mcount_wrapper_check;
}
GLIBC_2.2 {
# functions used in other libraries
_dl_sym; _dl_vsym;
}
}
ld.so {
@ -45,12 +49,3 @@ ld.so {
_dl_dst_count; _dl_dst_substitute;
}
}
libdl {
GLIBC_2.0 {
dladdr; dlclose; dlerror; dlopen; dlsym;
}
GLIBC_2.1 {
dlopen; dlvsym;
}
}

View File

@ -36,9 +36,10 @@ __libc_lock_define (extern, _dl_load_lock)
void
internal_function
_dl_close (struct link_map *map)
_dl_close (void *_map)
{
struct link_map **list;
struct link_map *map = _map;
unsigned nsearchlist;
unsigned int i;

View File

@ -211,7 +211,7 @@ dl_open_worker (void *a)
}
struct link_map *
void *
internal_function
_dl_open (const char *file, int mode, const void *caller)
{

129
elf/dl-sym.c Normal file
View File

@ -0,0 +1,129 @@
/* Look up a symbol in a shared object loaded by `dlopen'.
Copyright (C) 1999 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 <stddef.h>
#include <setjmp.h>
#include <libintl.h>
#include <dlfcn.h>
#include <ldsodefs.h>
#include <dl-hash.h>
void *
internal_function
_dl_sym (void *handle, const char *name, void *who)
{
ElfW(Addr) loadbase;
const ElfW(Sym) *ref = NULL;
if (handle == RTLD_DEFAULT)
/* Search the global scope. */
loadbase = _dl_lookup_symbol (name, &ref, _dl_global_scope, NULL, 0);
else if (handle == RTLD_NEXT)
{
struct link_map *l, *match;
ElfW(Addr) caller = (ElfW(Addr)) who;
/* Find the highest-addressed object that CALLER is not below. */
match = NULL;
for (l = _dl_loaded; l; l = l->l_next)
if (caller >= l->l_addr && (!match || match->l_addr < l->l_addr))
match = l;
if (! match)
_dl_signal_error (0, NULL, _("\
RTLD_NEXT used in code not dynamically loaded"));
l = match;
while (l->l_loader)
l = l->l_loader;
loadbase = _dl_lookup_symbol_skip (name, &ref, l->l_local_scope,
NULL, match);
}
else
{
/* Search the scope of the given object. */
struct link_map *map = handle;
loadbase = _dl_lookup_symbol (name, &ref, map->l_local_scope,
map->l_name, 0);
}
if (loadbase)
return (void *) (loadbase + ref->st_value);
return NULL;
}
void *
internal_function
_dl_vsym (void *handle, const char *name, const char *version, void *who)
{
ElfW(Addr) loadbase;
const ElfW(Sym) *ref = NULL;
struct r_found_version vers;
/* Compute hash value to the version string. */
vers.name = version;
vers.hidden = 1;
vers.hash = _dl_elf_hash (version);
/* We don't have a specific file where the symbol can be found. */
vers.filename = NULL;
if (handle == RTLD_DEFAULT)
/* Search the global scope. */
loadbase = _dl_lookup_versioned_symbol (name, &ref, _dl_global_scope,
NULL, &vers, 0);
else if (handle == RTLD_NEXT)
{
struct link_map *l, *match;
ElfW(Addr) caller = (ElfW(Addr)) who;
/* Find the highest-addressed object that CALLER is not below. */
match = NULL;
for (l = _dl_loaded; l; l = l->l_next)
if (caller >= l->l_addr && (!match || match->l_addr < l->l_addr))
match = l;
if (! match)
_dl_signal_error (0, NULL, _("\
RTLD_NEXT used in code not dynamically loaded"));
l = match;
while (l->l_loader)
l = l->l_loader;
loadbase = _dl_lookup_versioned_symbol_skip (name, &ref,
l->l_local_scope,
NULL, &vers, match);
}
else
{
/* Search the scope of the given object. */
struct link_map *map = handle;
loadbase = _dl_lookup_versioned_symbol (name, &ref,
map->l_local_scope,
map->l_name, &vers, 0);
}
if (loadbase)
return (void *) (loadbase + ref->st_value);
return NULL;
}

View File

@ -1,100 +0,0 @@
/* Look up a symbol in a shared object loaded by `dlopen'.
Copyright (C) 1995, 1996, 1997, 1998, 1999 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 <dlfcn.h>
#include <setjmp.h>
#include <stddef.h>
#include <libintl.h>
#include <elf/ldsodefs.h>
struct dlsym_args
{
/* The arguments to dlsym_doit. */
void *handle;
const char *name;
struct r_found_version version;
ElfW(Addr) caller;
/* The return values of dlsym_doit. */
ElfW(Addr) loadbase;
const ElfW(Sym) *ref;
};
static void
dlsym_doit (void *a)
{
struct dlsym_args *args = (struct dlsym_args *) a;
args->ref = NULL;
if (args->handle == RTLD_DEFAULT)
/* Search the global scope. */
args->loadbase = _dl_lookup_symbol (args->name, &args->ref,
_dl_global_scope, NULL, 0);
else if (args->handle == RTLD_NEXT)
{
struct link_map *l, *match;
/* Find the highest-addressed object that CALLER is not below. */
match = NULL;
for (l = _dl_loaded; l; l = l->l_next)
if (args->caller >= l->l_addr && (!match || match->l_addr < l->l_addr))
match = l;
if (! match)
_dl_signal_error (0, NULL, _("\
RTLD_NEXT used in code not dynamically loaded"));
l = match;
while (l->l_loader)
l = l->l_loader;
args->loadbase = _dl_lookup_symbol_skip (args->name, &args->ref,
l->l_local_scope, NULL, match);
if (args->loadbase == 0)
{
/* This means that no such symbol is defined. In this case we
have to provide a phony Elfxx_Sym entry since the value is
referenced in `dlsym'. */
static const ElfW(Sym) null_result;
args->ref = &null_result;
}
}
else
{
/* Search the scope of the given object. */
struct link_map *map = args->handle;
args->loadbase = _dl_lookup_symbol (args->name, &args->ref,
map->l_local_scope, map->l_name, 0);
}
}
void *
dlsym (void *handle, const char *name)
{
struct dlsym_args args;
args.caller = (ElfW(Addr)) __builtin_return_address (0);
args.handle = handle;
args.name = name;
return (_dlerror_run (dlsym_doit, &args)
? NULL : (void *) (args.loadbase + args.ref->st_value));
}

View File

@ -1,116 +0,0 @@
/* Look up a versioned symbol in a shared object loaded by `dlopen'.
Copyright (C) 1995, 1996, 1997, 1998, 1999 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 <dlfcn.h>
#include <setjmp.h>
#include <stddef.h>
#include <libintl.h>
#include <elf/ldsodefs.h>
#include <dl-hash.h>
struct dlvsym_args
{
/* The arguments to dlvsym_doit. */
void *handle;
const char *name;
struct r_found_version version;
ElfW(Addr) caller;
/* The return values of dlvsym_doit. */
ElfW(Addr) loadbase;
const ElfW(Sym) *ref;
};
static void
dlvsym_doit (void *a)
{
struct dlvsym_args *args = (struct dlvsym_args *)a;
args->ref = NULL;
if (args->handle == RTLD_DEFAULT)
/* Search the global scope. */
args->loadbase = _dl_lookup_versioned_symbol (args->name, &args->ref,
_dl_global_scope,
NULL, &args->version, 0);
else if (args->handle == RTLD_NEXT)
{
struct link_map *l, *match;
/* Find the highest-addressed object that CALLER is not below. */
match = NULL;
for (l = _dl_loaded; l; l = l->l_next)
if (args->caller >= l->l_addr && (!match || match->l_addr < l->l_addr))
match = l;
if (! match)
_dl_signal_error (0, NULL, _("\
RTLD_NEXT used in code not dynamically loaded"));
l = match;
while (l->l_loader)
l = l->l_loader;
args->loadbase = _dl_lookup_versioned_symbol_skip (args->name,
&args->ref,
l->l_local_scope,
NULL, &args->version,
match);
if (args->loadbase == 0)
{
/* This means that no such symbol is defined. In this case we
have to provide a phony Elfxx_Sym entry since the value is
referenced in `dlsym'. */
static const ElfW(Sym) null_result;
args->ref = &null_result;
}
}
else
{
/* Search the scope of the given object. */
struct link_map *map = args->handle;
args->loadbase = _dl_lookup_versioned_symbol (args->name, &args->ref,
map->l_local_scope,
map->l_name,
&args->version, 0);
}
}
void *
__dlvsym (void *handle, const char *name, const char *version_str)
{
struct dlvsym_args args;
args.handle = handle;
args.name = name;
args.caller = (ElfW(Addr)) __builtin_return_address (0);
/* Compute hash value to the version string. */
args.version.name = version_str;
args.version.hidden = 1;
args.version.hash = _dl_elf_hash (version_str);
/* We don't have a specific file where the symbol can be found. */
args.version.filename = NULL;
return (_dlerror_run (dlvsym_doit, &args)
? NULL : (void *) (args.loadbase + args.ref->st_value));
}
weak_alias (__dlvsym, dlvsym)

View File

@ -215,17 +215,6 @@ extern void _dl_signal_cerror (int errcode,
const char *errstring)
internal_function;
/* Call OPERATE, catching errors from `dl_signal_error'. If there is no
error, *ERRSTRING is set to null. If there is an error, *ERRSTRING is
set to a string constructed from the strings passed to _dl_signal_error,
and the error code passed is the return value. ERRSTRING if nonzero
points to a malloc'ed string which the caller has to free after use.
ARGS is passed as argument to OPERATE. */
extern int _dl_catch_error (char **errstring,
void (*operate) (void *),
void *args)
internal_function;
/* Call OPERATE, receiving errors from `dl_signal_cerror'. Unlike
`_dl_catch_error' the operation is resumed after the OPERATE
function returns.
@ -235,14 +224,6 @@ extern void _dl_receive_error (receiver_fct fct, void (*operate) (void *),
internal_function;
/* Helper function for <dlfcn.h> functions. Runs the OPERATE function via
_dl_catch_error. Returns zero for success, nonzero for failure; and
arranges for `dlerror' to return the error details.
ARGS is passed as argument to OPERATE. */
extern int _dlerror_run (void (*operate) (void *), void *args)
internal_function;
/* Open the shared object NAME and map in its segments.
LOADER's DT_RPATH is used in searching for NAME.
If the object is already opened, returns its existing map.
@ -267,18 +248,6 @@ extern unsigned int _dl_map_object_deps (struct link_map *map,
extern void _dl_setup_hash (struct link_map *map) internal_function;
/* Open the shared object NAME, relocate it, and run its initializer if it
hasn't already been run. MODE is as for `dlopen' (see <dlfcn.h>). If
the object is already opened, returns its existing map. */
extern struct link_map *_dl_open (const char *name, int mode,
const void *caller)
internal_function;
/* Close an object previously opened by _dl_open. */
extern void _dl_close (struct link_map *map)
internal_function;
/* Search loaded objects' symbol tables for a definition of the symbol
referred to by UNDEF. *SYM is the symbol table entry containing the
reference; it is replaced with the defining symbol, and the base load
@ -324,10 +293,6 @@ extern ElfW(Addr) _dl_lookup_versioned_symbol_skip (const char *undef,
struct link_map *skip_this)
internal_function;
/* Locate shared object containing the given address. */
extern int _dl_addr (const void *address, Dl_info *info)
internal_function;
/* Look up symbol NAME in MAP's scope and return its run-time address. */
extern ElfW(Addr) _dl_symbol_value (struct link_map *map, const char *name)
internal_function;
@ -409,7 +374,6 @@ extern void _dl_mcount (ElfW(Addr) frompc, ElfW(Addr) selfpc);
calling function. */
extern void _dl_mcount_wrapper (void *selfpc);
/* Show the members of the auxiliary array passed up from the kernel. */
extern void _dl_show_auxv (void) internal_function;
@ -424,18 +388,6 @@ extern const struct r_strlenpair *_dl_important_hwcaps (const char *platform,
size_t *max_capstrlen)
internal_function;
/* When we do profiling we have the problem that uses of `dlopen'ed
objects don't use the PLT but instead use a pointer to the function.
We still want to have profiling data and in these cases we must do
the work of calling `_dl_mcount' ourself. The following macros
helps do it. */
#define _CALL_DL_FCT(fctp, args) \
({ if (_dl_profile_map != NULL) \
_dl_mcount_wrapper (fctp); \
(*fctp) args; \
})
__END_DECLS
#endif /* ldsodefs.h */

View File

@ -26,7 +26,6 @@
#include <sys/types.h>
#include <nsswitch.h>
/* Type of the lookup function. */
typedef enum nss_status (*initgroups_function) (const char *, gid_t,
long int *, long int *,
@ -67,7 +66,7 @@ compat_call (service_user *nip, const char *user, gid_t group, long int *start,
setgrent_fct = __nss_lookup_function (nip, "setgrent");
if (setgrent_fct)
{
status = _CALL_DL_FCT (setgrent_fct, ());
status = DL_CALL_FCT (setgrent_fct, ());
if (status != NSS_STATUS_SUCCESS)
return status;
}
@ -78,7 +77,7 @@ compat_call (service_user *nip, const char *user, gid_t group, long int *start,
do
{
while ((status = _CALL_DL_FCT (getgrent_fct,
while ((status = DL_CALL_FCT (getgrent_fct,
(&grpbuf, tmpbuf, buflen, errnop)),
status == NSS_STATUS_TRYAGAIN)
&& *errnop == ERANGE)
@ -122,7 +121,7 @@ compat_call (service_user *nip, const char *user, gid_t group, long int *start,
done:
if (endgrent_fct)
_CALL_DL_FCT (endgrent_fct, ());
DL_CALL_FCT (endgrent_fct, ());
return NSS_STATUS_SUCCESS;
}
@ -190,7 +189,7 @@ initgroups (user, group)
break;
}
else
status = _CALL_DL_FCT (fct, (user, group, &start, &size, groups, limit,
status = DL_CALL_FCT (fct, (user, group, &start, &size, groups, limit,
&errno));
/* This is really only for debugging. */

View File

@ -23,7 +23,6 @@
#include <gconv.h>
#include <sys/param.h>
#include <dlfcn.h>
#include <ldsodefs.h>
int
internal_function
@ -42,7 +41,7 @@ __gconv (__gconv_t cd, const unsigned char **inbuf,
if (inbuf == NULL || *inbuf == NULL)
/* We just flush. */
result = _CALL_DL_FCT (cd->__steps->__fct,
result = DL_CALL_FCT (cd->__steps->__fct,
(cd->__steps, cd->__data, NULL, NULL,
converted, 1));
else
@ -56,7 +55,7 @@ __gconv (__gconv_t cd, const unsigned char **inbuf,
do
{
last_start = *inbuf;
result = _CALL_DL_FCT (cd->__steps->__fct,
result = DL_CALL_FCT (cd->__steps->__fct,
(cd->__steps, cd->__data, inbuf, inbufend,
converted, 0));
}

View File

@ -26,7 +26,6 @@
#include <bits/libc-lock.h>
#include <dlfcn.h>
#include <ldsodefs.h>
#include <gconv_int.h>
@ -165,7 +164,7 @@ free_derivation (void *p)
for (cnt = 0; cnt < deriv->nsteps; ++cnt)
if (deriv->steps[cnt].__end_fct)
_CALL_DL_FCT (deriv->steps[cnt].__end_fct, (&deriv->steps[cnt]));
DL_CALL_FCT (deriv->steps[cnt].__end_fct, (&deriv->steps[cnt]));
/* Free the name strings. */
free ((char *) deriv->steps[0].__from_name);
@ -237,7 +236,7 @@ gen_steps (struct derivation_step *best, const char *toset,
/* Call the init function. */
if (result[step_cnt].__init_fct != NULL)
{
status = _CALL_DL_FCT (result[step_cnt].__init_fct,
status = DL_CALL_FCT (result[step_cnt].__init_fct,
(&result[step_cnt]));
if (status != __GCONV_OK)
@ -258,7 +257,7 @@ gen_steps (struct derivation_step *best, const char *toset,
while (++step_cnt < *nsteps)
{
if (result[step_cnt].__end_fct != NULL)
_CALL_DL_FCT (result[step_cnt].__end_fct, (&result[step_cnt]));
DL_CALL_FCT (result[step_cnt].__end_fct, (&result[step_cnt]));
#ifndef STATIC_GCONV
__gconv_release_shlib (result[step_cnt].__shlib_handle);
#endif

View File

@ -86,8 +86,6 @@
#ifndef STATIC_GCONV
# include <dlfcn.h>
#endif
#include <ldsodefs.h>
/* The direction objects. */
#if DEFINE_DIRECTION_OBJECTS || DEFINE_INIT

View File

@ -1,5 +1,5 @@
#ifndef _DLFCN_H
#include <elf/dlfcn.h>
#include <dlfcn/dlfcn.h>
/* Now define the internal interfaces. */
extern void *__dlvsym __P ((void *__handle, __const char *__name,
@ -8,7 +8,51 @@ extern void *__dlvsym __P ((void *__handle, __const char *__name,
extern void *__libc_dlopen __P ((__const char *__name));
extern void *__libc_dlsym __P ((void *__map, __const char *__name));
extern int __libc_dlclose __P ((void *__map));
extern int _dl_addr __P ((const void *address, Dl_info *info))
/* Locate shared object containing the given address. */
extern int _dl_addr (const void *address, Dl_info *info)
internal_function;
/* Open the shared object NAME, relocate it, and run its initializer if it
hasn't already been run. MODE is as for `dlopen' (see <dlfcn.h>). If
the object is already opened, returns its existing map. */
extern void *_dl_open (const char *name, int mode, const void *caller)
internal_function;
/* Close an object previously opened by _dl_open. */
extern void _dl_close (void *map)
internal_function;
/* Look up NAME in shared object HANDLE (which may be RTLD_DEFAULT or
RTLD_NEXT). WHO is the calling function, for RTLD_NEXT. Returns
the symbol value, which may be NULL. */
extern void *_dl_sym (void *handle, const char *name, void *who)
internal_function;
/* Look up version VERSION of symbol NAME in shared object HANDLE
(which may be RTLD_DEFAULT or RTLD_NEXT). WHO is the calling
function, for RTLD_NEXT. Returns the symbol value, which may be
NULL. */
extern void *_dl_vsym (void *handle, const char *name, const char *version,
void *who)
internal_function;
/* Call OPERATE, catching errors from `dl_signal_error'. If there is no
error, *ERRSTRING is set to null. If there is an error, *ERRSTRING is
set to a string constructed from the strings passed to _dl_signal_error,
and the error code passed is the return value. ERRSTRING if nonzero
points to a malloc'ed string which the caller has to free after use.
ARGS is passed as argument to OPERATE. */
extern int _dl_catch_error (char **errstring,
void (*operate) (void *),
void *args)
internal_function;
/* Helper function for <dlfcn.h> functions. Runs the OPERATE function via
_dl_catch_error. Returns zero for success, nonzero for failure; and
arranges for `dlerror' to return the error details.
ARGS is passed as argument to OPERATE. */
extern int _dlerror_run (void (*operate) (void *), void *args)
internal_function;
#endif

View File

@ -1,15 +0,0 @@
/* We must use the appropriate version for the system. */
#ifdef HAVE_ELF
# include <elf/ldsodefs.h>
#else
/* We have no dynamic loading. Define the macros we need here as dummy
versions. */
# ifndef _LDSODEFS_H
# define _LDSODEFS_H 1
/* Call a function through a pointer. */
# define _CALL_DL_FCT(fctp, args) (*fctp) args
# define DL_CALL_FCT(fctp, args) (*fctp) args
# endif /* ldsodefs.h */
#endif

View File

@ -179,7 +179,7 @@ INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer,
while (no_more == 0)
{
status = _CALL_DL_FCT (fct, (ADD_VARIABLES, resbuf, buffer, buflen,
status = DL_CALL_FCT (fct, (ADD_VARIABLES, resbuf, buffer, buflen,
&errno H_ERRNO_VAR));
/* The status is NSS_STATUS_TRYAGAIN and errno is ERANGE the

View File

@ -164,7 +164,7 @@ SETFUNC_NAME (STAYOPEN)
while (! no_more)
{
int is_last_nip = nip == last_nip;
enum nss_status status = _CALL_DL_FCT (fct, (STAYOPEN_VAR));
enum nss_status status = DL_CALL_FCT (fct, (STAYOPEN_VAR));
no_more = __nss_next (&nip, SETFUNC_NAME_STRING, (void **) &fct,
status, 0);
@ -201,7 +201,7 @@ ENDFUNC_NAME (void)
while (! no_more)
{
/* Ignore status, we force check in __NSS_NEXT. */
_CALL_DL_FCT (fct, ());
DL_CALL_FCT (fct, ());
if (nip == last_nip)
/* We have processed all services which were used. */
@ -245,7 +245,7 @@ INTERNAL (REENTRANT_GETNAME) (LOOKUP_TYPE *resbuf, char *buffer, size_t buflen,
{
int is_last_nip = nip == last_nip;
status = _CALL_DL_FCT (fct,
status = DL_CALL_FCT (fct,
(resbuf, buffer, buflen, &errno H_ERRNO_VAR));
/* The the status is NSS_STATUS_TRYAGAIN and errno is ERANGE the
@ -277,7 +277,7 @@ INTERNAL (REENTRANT_GETNAME) (LOOKUP_TYPE *resbuf, char *buffer, size_t buflen,
(void **) &sfct);
if (! no_more)
status = _CALL_DL_FCT (sfct, (STAYOPEN_TMPVAR));
status = DL_CALL_FCT (sfct, (STAYOPEN_TMPVAR));
else
status = NSS_STATUS_NOTFOUND;
}

View File

@ -26,8 +26,7 @@
#include <nss.h>
#include <resolv.h>
#include <search.h>
#include <ldsodefs.h>
#include <dlfcn.h>
/* Actions performed after lookup finished. */
typedef enum

View File

@ -45,3 +45,8 @@ endif
ifeq ($(subdir),misc)
sysdep_headers += sys/mtio.h
endif
ifeq ($(subdir),dlfcn)
libdl-routines += eval
endif

138
sysdeps/gnu/eval.c Normal file
View File

@ -0,0 +1,138 @@
/* 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);
}