Update.
[platform/upstream/glibc.git] / elf / eval.c
1 /* You don't really want to know what this hack is for.
2    Copyright (C) 1996, 1997 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 Library General Public License as
7    published by the Free Software Foundation; either version 2 of the
8    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    Library General Public License for more details.
14
15    You should have received a copy of the GNU Library General Public
16    License along with the GNU C Library; see the file COPYING.LIB.  If not,
17    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18    Boston, MA 02111-1307, USA.  */
19
20 #include <stdio.h>
21 #include <ctype.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <dlfcn.h>
26
27 static void *funcall (char **stringp);
28 static void *eval (char **stringp);
29
30 static void *
31 funcall (char **stringp)
32 {
33   void *args[strlen (*stringp)], **ap = args;
34   void *argcookie = &args[1];
35
36   do
37     {
38       /* Evaluate the next token.  */
39       *ap++ = eval (stringp);
40
41       /* Whitespace is irrelevant.  */
42       while (isspace (**stringp))
43         ++*stringp;
44
45       /* Terminate at closing paren or end of line.  */
46     } while (**stringp != '\0' && **stringp != ')');
47   if (**stringp != '\0')
48     /* Swallow closing paren.  */
49     ++*stringp;
50
51   if (args[0] == NULL)
52     {
53       static const char unknown[] = "Unknown function\n";
54       write (1, unknown, sizeof unknown - 1);
55       return NULL;
56     }
57
58   /* Do it to it.  */
59   __builtin_return (__builtin_apply (args[0],
60                                      &argcookie,
61                                      (char *) ap - (char *) &args[1]));
62 }
63
64 static void *
65 eval (char **stringp)
66 {
67   void *value;
68   char *p = *stringp, c;
69
70   /* Whitespace is irrelevant.  */
71   while (isspace (*p))
72     ++p;
73
74   switch (*p)
75     {
76     case '"':
77       /* String constant.  */
78       value = ++p;
79       do
80         if (*p == '\\')
81           {
82             switch (*strcpy (p, p + 1))
83               {
84               case 't':
85                 *p = '\t';
86                 break;
87               case 'n':
88                 *p = '\n';
89                 break;
90               }
91             ++p;
92           }
93       while (*p != '\0' && *p++ != '"');
94       if (p[-1] == '"')
95         p[-1] = '\0';
96       break;
97
98     case '(':
99       *stringp = ++p;
100       return funcall (stringp);
101
102     default:
103       /* Try to parse it as a number.  */
104       value = (void *) strtol (p, stringp, 0);
105       if (*stringp != p)
106         return value;
107
108       /* Anything else is a symbol that produces its address.  */
109       value = p;
110       do
111         ++p;
112       while (*p != '\0' && !isspace (*p) && (!ispunct (*p) || *p == '_'));
113       c = *p;
114       *p = '\0';
115       value = dlsym (NULL, value);
116       *p = c;
117       break;
118     }
119
120   *stringp = p;
121   return value;
122 }
123
124
125 void
126 _start (void)
127 {
128   char *buf = NULL;
129   size_t bufsz = 0;
130
131   while (__getdelim (&buf, &bufsz, '\n', stdin) > 0)
132     {
133       char *p = buf;
134       eval (&p);
135     }
136
137   exit (0);
138 }