(linenum→info "unix/slp.c:2238")

glibc/2.7/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) __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:       /* 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: }
Syntax (Markdown)