]> git.ipfire.org Git - thirdparty/glibc.git/blob - dlfcn/eval.c
* Makerules ($(common-objpfx)shlib.lds): New target.
[thirdparty/glibc.git] / dlfcn / eval.c
1 /* You don't really want to know what this hack is for.
2 Copyright (C) 1996, 1997, 2000, 2001 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
4
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
9
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
14
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
19
20 #include <assert.h>
21 #include <ctype.h>
22 #include <dlfcn.h>
23 #include <errno.h>
24 #include <limits.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29
30 static void *funcall (char **stringp);
31 static void *eval (char **stringp);
32
33
34 long int weak_function
35 __strtol_internal (const char *nptr, char **endptr, int base, int group)
36 {
37 unsigned long int result = 0;
38 long int sign = 1;
39
40 while (*nptr == ' ' || *nptr == '\t')
41 ++nptr;
42
43 if (*nptr == '-')
44 {
45 sign = -1;
46 ++nptr;
47 }
48 else if (*nptr == '+')
49 ++nptr;
50
51 if (*nptr < '0' || *nptr > '9')
52 {
53 if (endptr != NULL)
54 *endptr = (char *) nptr;
55 return 0L;
56 }
57
58 assert (base == 0);
59 base = 10;
60 if (*nptr == '0')
61 {
62 if (nptr[1] == 'x' || nptr[1] == 'X')
63 {
64 base = 16;
65 nptr += 2;
66 }
67 else
68 base = 8;
69 }
70
71 while (*nptr >= '0' && *nptr <= '9')
72 {
73 unsigned long int digval = *nptr - '0';
74 if (result > LONG_MAX / 10
75 || (sign > 0 ? result == LONG_MAX / 10 && digval > LONG_MAX % 10
76 : (result == ((unsigned long int) LONG_MAX + 1) / 10
77 && digval > ((unsigned long int) LONG_MAX + 1) % 10)))
78 {
79 errno = ERANGE;
80 return sign > 0 ? LONG_MAX : LONG_MIN;
81 }
82 result *= base;
83 result += digval;
84 ++nptr;
85 }
86
87 return (long int) result * sign;
88 }
89
90
91 static void *
92 funcall (char **stringp)
93 {
94 void *args[strlen (*stringp)], **ap = args;
95 void *argcookie = &args[1];
96
97 do
98 {
99 /* Evaluate the next token. */
100 *ap++ = eval (stringp);
101
102 /* Whitespace is irrelevant. */
103 while (isspace (**stringp))
104 ++*stringp;
105
106 /* Terminate at closing paren or end of line. */
107 } while (**stringp != '\0' && **stringp != ')');
108 if (**stringp != '\0')
109 /* Swallow closing paren. */
110 ++*stringp;
111
112 if (args[0] == NULL)
113 {
114 static const char unknown[] = "Unknown function\n";
115 write (1, unknown, sizeof unknown - 1);
116 return NULL;
117 }
118
119 /* Do it to it. */
120 __builtin_return (__builtin_apply (args[0],
121 &argcookie,
122 (char *) ap - (char *) &args[1]));
123 }
124
125 static void *
126 eval (char **stringp)
127 {
128 void *value;
129 char *p = *stringp, c;
130
131 /* Whitespace is irrelevant. */
132 while (isspace (*p))
133 ++p;
134
135 switch (*p)
136 {
137 case '"':
138 /* String constant. */
139 value = ++p;
140 do
141 if (*p == '\\')
142 {
143 switch (*strcpy (p, p + 1))
144 {
145 case 't':
146 *p = '\t';
147 break;
148 case 'n':
149 *p = '\n';
150 break;
151 }
152 ++p;
153 }
154 while (*p != '\0' && *p++ != '"');
155 if (p[-1] == '"')
156 p[-1] = '\0';
157 break;
158
159 case '(':
160 *stringp = ++p;
161 return funcall (stringp);
162
163 default:
164 /* Try to parse it as a number. */
165 value = (void *) __strtol_internal (p, stringp, 0, 0);
166 if (*stringp != p)
167 return value;
168
169 /* Anything else is a symbol that produces its address. */
170 value = p;
171 do
172 ++p;
173 while (*p != '\0' && !isspace (*p) && (!ispunct (*p) || *p == '_'));
174 c = *p;
175 *p = '\0';
176 value = dlsym (NULL, value);
177 *p = c;
178 break;
179 }
180
181 *stringp = p;
182 return value;
183 }
184
185
186 extern void _start (void) __attribute__ ((noreturn));
187 void
188 __attribute__ ((noreturn))
189 _start (void)
190 {
191 char *buf = NULL;
192 size_t bufsz = 0;
193
194 while (__getdelim (&buf, &bufsz, '\n', stdin) > 0)
195 {
196 char *p = buf;
197 eval (&p);
198 }
199
200 exit (0);
201 }