1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
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) __attribute_noinline__;
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:
100: *ap++ = eval (stringp);
101:
102:
103: while (isspace (**stringp))
104: ++*stringp;
105:
106:
107: } while (**stringp != '\0' && **stringp != ')');
108: if (**stringp != '\0')
109:
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:
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:
132: while (isspace (*p))
133: ++p;
134:
135: switch (*p)
136: {
137: case '"':
138:
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:
165: value = (void *) __strtol_internal (p, stringp, 0, 0);
166: if (*stringp != p)
167: return value;
168:
169:
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: }