libexplain  1.4.D001
libexplain/string_to/pointer.c
Go to the documentation of this file.
00001 /*
00002  * libexplain - Explain errno values returned by libc functions
00003  * Copyright (C) 2009, 2010, 2013 Peter Miller
00004  * Written by Peter Miller <pmiller@opensource.org.au>
00005  *
00006  * This program is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU Lesser General Public License as
00008  * published by the Free Software Foundation; either version 3 of the
00009  * License, or (at your option) any later version.
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public License
00017  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00018  */
00019 
00020 #include <libexplain/ac/dlfcn.h>
00021 #include <libexplain/ac/stdio.h>
00022 #include <libexplain/ac/string.h>
00023 
00024 #include <libexplain/string_to_thing.h>
00025 
00026 
00027 void *
00028 explain_parse_pointer_or_die(const char *text)
00029 {
00030     if (0 == strcasecmp(text, "null"))
00031         return NULL;
00032     if (0 == strcasecmp(text, "(null)"))
00033         return NULL;
00034     if (0 == strcasecmp(text, "nul"))
00035         return NULL;
00036     if (0 == strcasecmp(text, "nil"))
00037         return NULL;
00038     if (0 == strcasecmp(text, "(nil)"))
00039         return NULL;
00040     if (0 == strcmp(text, "stdin"))
00041         return stdin;
00042     if (0 == strcmp(text, "stdout"))
00043         return stdout;
00044     if (0 == strcmp(text, "stderr"))
00045         return stderr;
00046 
00047 #ifdef HAVE_DLSYM
00048     if (text[0] == '&')
00049     {
00050         void            *handle;
00051 
00052         handle = dlopen(NULL, RTLD_NOW);
00053         if (handle)
00054         {
00055             void            *p;
00056 
00057             /* clear any previous error */
00058             dlerror();
00059 
00060             p = dlsym(handle, text + 1);
00061             if (dlerror() == NULL)
00062             {
00063                 dlclose(handle);
00064                 return p;
00065             }
00066             dlclose(handle);
00067         }
00068     }
00069 #endif
00070 
00071     /*
00072      * Pointers are strange beasts, and NULL pointers even stranger.  The ANSI C
00073      * standard says that the NULL pointer need not be all-bits-zero, but that
00074      * a NULL pointer *constant* may be *written* as "0".  This does _not_ mean
00075      * that an arithmetic value of all-bits-zero, when cast to (void *) will
00076      * actually have the same value as the NULL pointer.  Hence the code below:
00077      * it uses an explicit constant NULL pointer.
00078      *
00079      * I have used such a machine, BTW, and I sincerely hope none of them are
00080      * still in use today.  Zero was a valid code and data address (and actually
00081      * used!), so the operating system guaranteed that another page of memory
00082      * would never be mapped, and the NULL pointer, while written as 0, had a
00083      * value of the base address of that page of memory.
00084      */
00085     if (0 == strcmp(text, "0"))
00086         return NULL;
00087 
00088 #if SIZEOF_VOID_P > SIZEOF_LONG
00089     return (void *)explain_parse_longlong_or_die(text);
00090 #else
00091     return (void *)explain_parse_long_or_die(text);
00092 #endif
00093 }
00094 
00095 
00096 /* vim: set ts=8 sw=4 et : */