mirror of
git://sourceware.org/git/glibc.git
synced 2024-11-21 01:12:26 +08:00
499e7464ed
Sat Sep 7 14:00:33 1996 David Mosberger-Tang <davidm@azstarnet.com> * catgets/catgets.c (catopen): Allocate sizeof(*result) bytes instead of sizeof(nl_catd) (which is just a pointer!). Sat Sep 7 19:39:19 1996 Ulrich Drepper <drepper@cygnus.com> * Makefile ($(objpfx)version-info.h): Generate from Banner files. * version.c (banner): Add contents of version-info.h to string. * Makerules: If $($(subdir)-version) is available name versioned shared library according to this value instead of glibc's version. * libio/Banner: New file. * elf/eval.c (funcall): Write error message in case function is not found. (eval): Recognize `_' in names.
119 lines
2.1 KiB
C
119 lines
2.1 KiB
C
#include <stdio.h>
|
|
#include <ctype.h>
|
|
#include <stdlib.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 (getline (&buf, &bufsz, stdin) > 0)
|
|
{
|
|
char *p = buf;
|
|
eval (&p);
|
|
}
|
|
|
|
exit (0);
|
|
}
|