Back to index

glibc  2.9
eval.c
Go to the documentation of this file.
00001 /* You don't really want to know what this hack is for.
00002    Copyright (C) 1996, 1997, 2000, 2001 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #include <assert.h>
00021 #include <ctype.h>
00022 #include <dlfcn.h>
00023 #include <errno.h>
00024 #include <limits.h>
00025 #include <stdio.h>
00026 #include <stdlib.h>
00027 #include <string.h>
00028 #include <unistd.h>
00029 
00030 static void *funcall (char **stringp) __attribute_noinline__;
00031 static void *eval (char **stringp);
00032 
00033 
00034 long int weak_function
00035 __strtol_internal (const char *nptr, char **endptr, int base, int group)
00036 {
00037   unsigned long int result = 0;
00038   long int sign = 1;
00039 
00040   while (*nptr == ' ' || *nptr == '\t')
00041     ++nptr;
00042 
00043   if (*nptr == '-')
00044     {
00045       sign = -1;
00046       ++nptr;
00047     }
00048   else if (*nptr == '+')
00049     ++nptr;
00050 
00051   if (*nptr < '0' || *nptr > '9')
00052     {
00053       if (endptr != NULL)
00054        *endptr = (char *) nptr;
00055       return 0L;
00056     }
00057 
00058   assert (base == 0);
00059   base = 10;
00060   if (*nptr == '0')
00061     {
00062       if (nptr[1] == 'x' || nptr[1] == 'X')
00063        {
00064          base = 16;
00065          nptr += 2;
00066        }
00067       else
00068        base = 8;
00069     }
00070 
00071   while (*nptr >= '0' && *nptr <= '9')
00072     {
00073       unsigned long int digval = *nptr - '0';
00074       if (result > LONG_MAX / 10
00075          || (sign > 0 ? result == LONG_MAX / 10 && digval > LONG_MAX % 10
00076              : (result == ((unsigned long int) LONG_MAX + 1) / 10
00077                && digval > ((unsigned long int) LONG_MAX + 1) % 10)))
00078        {
00079          errno = ERANGE;
00080          return sign > 0 ? LONG_MAX : LONG_MIN;
00081        }
00082       result *= base;
00083       result += digval;
00084       ++nptr;
00085     }
00086 
00087   return (long int) result * sign;
00088 }
00089 
00090 
00091 static void *
00092 funcall (char **stringp)
00093 {
00094   void *args[strlen (*stringp)], **ap = args;
00095   void *argcookie = &args[1];
00096 
00097   do
00098     {
00099       /* Evaluate the next token.  */
00100       *ap++ = eval (stringp);
00101 
00102       /* Whitespace is irrelevant.  */
00103       while (isspace (**stringp))
00104        ++*stringp;
00105 
00106       /* Terminate at closing paren or end of line.  */
00107     } while (**stringp != '\0' && **stringp != ')');
00108   if (**stringp != '\0')
00109     /* Swallow closing paren.  */
00110     ++*stringp;
00111 
00112   if (args[0] == NULL)
00113     {
00114       static const char unknown[] = "Unknown function\n";
00115       write (1, unknown, sizeof unknown - 1);
00116       return NULL;
00117     }
00118 
00119   /* Do it to it.  */
00120   __builtin_return (__builtin_apply (args[0],
00121                                  &argcookie,
00122                                  (char *) ap - (char *) &args[1]));
00123 }
00124 
00125 static void *
00126 eval (char **stringp)
00127 {
00128   void *value;
00129   char *p = *stringp, c;
00130 
00131   /* Whitespace is irrelevant.  */
00132   while (isspace (*p))
00133     ++p;
00134 
00135   switch (*p)
00136     {
00137     case '"':
00138       /* String constant.  */
00139       value = ++p;
00140       do
00141        if (*p == '\\')
00142          {
00143            switch (*strcpy (p, p + 1))
00144              {
00145              case 't':
00146               *p = '\t';
00147               break;
00148              case 'n':
00149               *p = '\n';
00150               break;
00151              }
00152            ++p;
00153          }
00154       while (*p != '\0' && *p++ != '"');
00155       if (p[-1] == '"')
00156        p[-1] = '\0';
00157       break;
00158 
00159     case '(':
00160       *stringp = ++p;
00161       return funcall (stringp);
00162 
00163     default:
00164       /* Try to parse it as a number.  */
00165       value = (void *) __strtol_internal (p, stringp, 0, 0);
00166       if (*stringp != p)
00167        return value;
00168 
00169       /* Anything else is a symbol that produces its address.  */
00170       value = p;
00171       do
00172        ++p;
00173       while (*p != '\0' && !isspace (*p) && (!ispunct (*p) || *p == '_'));
00174       c = *p;
00175       *p = '\0';
00176       value = dlsym (NULL, value);
00177       *p = c;
00178       break;
00179     }
00180 
00181   *stringp = p;
00182   return value;
00183 }
00184 
00185 
00186 extern void _start (void) __attribute__ ((noreturn));
00187 void
00188 __attribute__ ((noreturn))
00189 _start (void)
00190 {
00191   char *buf = NULL;
00192   size_t bufsz = 0;
00193 
00194   while (__getdelim (&buf, &bufsz, '\n', stdin) > 0)
00195     {
00196       char *p = buf;
00197       eval (&p);
00198     }
00199 
00200   exit (0);
00201 }