Updated to fedora-glibc-20090509T2200
[glibc/history.git] / dlfcn / eval.c
blobe0b56624f6678c7355f355176e1973c9f22e27b1
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.
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.
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.
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. */
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>
30 static void *funcall (char **stringp) __attribute_noinline__;
31 static void *eval (char **stringp);
34 long int weak_function
35 __strtol_internal (const char *nptr, char **endptr, int base, int group)
37 unsigned long int result = 0;
38 long int sign = 1;
40 while (*nptr == ' ' || *nptr == '\t')
41 ++nptr;
43 if (*nptr == '-')
45 sign = -1;
46 ++nptr;
48 else if (*nptr == '+')
49 ++nptr;
51 if (*nptr < '0' || *nptr > '9')
53 if (endptr != NULL)
54 *endptr = (char *) nptr;
55 return 0L;
58 assert (base == 0);
59 base = 10;
60 if (*nptr == '0')
62 if (nptr[1] == 'x' || nptr[1] == 'X')
64 base = 16;
65 nptr += 2;
67 else
68 base = 8;
71 while (*nptr >= '0' && *nptr <= '9')
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)))
79 errno = ERANGE;
80 return sign > 0 ? LONG_MAX : LONG_MIN;
82 result *= base;
83 result += digval;
84 ++nptr;
87 return (long int) result * sign;
91 static void *
92 funcall (char **stringp)
94 void *args[strlen (*stringp)], **ap = args;
95 void *argcookie = &args[1];
99 /* Evaluate the next token. */
100 *ap++ = eval (stringp);
102 /* Whitespace is irrelevant. */
103 while (isspace (**stringp))
104 ++*stringp;
106 /* Terminate at closing paren or end of line. */
107 } while (**stringp != '\0' && **stringp != ')');
108 if (**stringp != '\0')
109 /* Swallow closing paren. */
110 ++*stringp;
112 if (args[0] == NULL)
114 static const char unknown[] = "Unknown function\n";
115 write (1, unknown, sizeof unknown - 1);
116 return NULL;
119 /* Do it to it. */
120 __builtin_return (__builtin_apply (args[0],
121 &argcookie,
122 (char *) ap - (char *) &args[1]));
125 static void *
126 eval (char **stringp)
128 void *value;
129 char *p = *stringp, c;
131 /* Whitespace is irrelevant. */
132 while (isspace (*p))
133 ++p;
135 switch (*p)
137 case '"':
138 /* String constant. */
139 value = ++p;
141 if (*p == '\\')
143 switch (*strcpy (p, p + 1))
145 case 't':
146 *p = '\t';
147 break;
148 case 'n':
149 *p = '\n';
150 break;
152 ++p;
154 while (*p != '\0' && *p++ != '"');
155 if (p[-1] == '"')
156 p[-1] = '\0';
157 break;
159 case '(':
160 *stringp = ++p;
161 return funcall (stringp);
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;
169 /* Anything else is a symbol that produces its address. */
170 value = p;
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;
181 *stringp = p;
182 return value;
186 extern void _start (void) __attribute__ ((noreturn));
187 void
188 __attribute__ ((noreturn))
189 _start (void)
191 char *buf = NULL;
192 size_t bufsz = 0;
194 while (__getdelim (&buf, &bufsz, '\n', stdin) > 0)
196 char *p = buf;
197 eval (&p);
200 exit (0);