libexplain  1.4.D001
libexplain/ac/string.c
Go to the documentation of this file.
00001 /*
00002  * libexplain - Explain errno values returned by libc functions
00003  * Copyright (C) 2008-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 published by
00008  * the Free Software Foundation; either version 3 of the License, or (at
00009  * 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/stddef.h>
00021 #include <libexplain/ac/stdlib.h>
00022 #include <libexplain/ac/string.h>
00023 #include <libexplain/ac/stdio.h>
00024 
00025 #include <libexplain/gcc_attributes.h>
00026 
00027 
00028 /*
00029  *  NAME
00030  *      strerror - string for error number
00031  *
00032  *  SYNOPSIS
00033  *      char *strerror(int errnum);
00034  *
00035  *  DESCRIPTION
00036  *      The strerror function maps the error number in errnum to an error
00037  *      message string.
00038  *
00039  *  RETURNS
00040  *      The strerror function returns a pointer to the string, the contents of
00041  *      which are implementation-defined.  The array pointed to shall not be
00042  *      modified by the program, but may be overwritten by a subsequent call to
00043  *      the strerror function.
00044  *
00045  *  CAVEAT
00046  *      Unknown errors will be rendered in the form "Error %d", where %d will
00047  *      be replaced by a decimal representation of the error number.
00048  */
00049 
00050 #ifndef HAVE_STRERROR
00051 
00052 LINKAGE_HIDDEN
00053 char *
00054 strerror(int n)
00055 {
00056     extern int      sys_nerr;
00057     extern char     *sys_errlist[];
00058     static char     buffer[16];
00059 
00060     if (n < 1 || n > sys_nerr)
00061     {
00062             sprintf(buffer, "Error %d", n);
00063             return buffer;
00064     }
00065     return sys_errlist[n];
00066 }
00067 
00068 #endif /* !HAVE_STRERROR */
00069 
00070 
00071 #ifndef HAVE_STRCASECMP
00072 
00073 LINKAGE_HIDDEN
00074 int
00075 strcasecmp(const char *s1, const char *s2)
00076 {
00077     int             c1;
00078     int             c2;
00079 
00080     for (;;)
00081     {
00082         c1 = (unsigned char)*s1++;
00083         if (islower(c1))
00084             c1 = toupper(c1);
00085         c2 = (unsigned char)*s2++;
00086         if (islower(c2))
00087             c2 = toupper(c2);
00088         if (c1 != c2)
00089         {
00090             /*
00091              * if s1 is a leading substring of s2, must
00092              * return -1, even if the next character of s2
00093              * is negative.
00094              */
00095             if (!c1)
00096                 return -1;
00097             if (c1 < c2)
00098                 return -1;
00099             return 1;
00100         }
00101         if (!c1)
00102             return 0;
00103     }
00104 }
00105 
00106 #endif /* !HAVE_STRCASECMP */
00107 
00108 
00109 #ifndef HAVE_STRSIGNAL
00110 
00111 LINKAGE_HIDDEN
00112 char *
00113 strsignal(int n)
00114 {
00115     switch (n)
00116     {
00117 #ifdef SIGHUP
00118     case SIGHUP:
00119             return "hang up [SIGHUP]";
00120 #endif /* SIGHUP */
00121 
00122 #ifdef SIGINT
00123     case SIGINT:
00124             return "user interrupt [SIGINT]";
00125 #endif /* SIGINT */
00126 
00127 #ifdef SIGQUIT
00128     case SIGQUIT:
00129             return "user quit [SIGQUIT]";
00130 #endif /* SIGQUIT */
00131 
00132 #ifdef SIGILL
00133     case SIGILL:
00134             return "illegal instruction [SIGILL]";
00135 #endif /* SIGILL */
00136 
00137 #ifdef SIGTRAP
00138     case SIGTRAP:
00139             return "trace trap [SIGTRAP]";
00140 #endif /* SIGTRAP */
00141 
00142 #ifdef SIGIOT
00143     case SIGIOT:
00144             return "abort [SIGIOT]";
00145 #endif /* SIGIOT */
00146 
00147 #ifdef SIGEMT
00148     case SIGEMT:
00149             return "EMT instruction [SIGEMT]";
00150 #endif /* SIGEMT */
00151 
00152 #ifdef SIGFPE
00153     case SIGFPE:
00154             return "floating point exception [SIGFPE]";
00155 #endif /* SIGFPE */
00156 
00157 #ifdef SIGKILL
00158     case SIGKILL:
00159             return "kill [SIGKILL]";
00160 #endif /* SIGKILL */
00161 
00162 #ifdef SIGBUS
00163     case SIGBUS:
00164             return "bus error [SIGBUS]";
00165 #endif /* SIGBUS */
00166 
00167 #ifdef SIGSEGV
00168     case SIGSEGV:
00169             return "segmentation violation [SIGSEGV]";
00170 #endif /* SIGSEGV */
00171 
00172 #ifdef SIGSYS
00173     case SIGSYS:
00174             return "bad argument to system call [SIGSYS]";
00175 #endif /* SIGSYS */
00176 
00177 #ifdef SIGPIPE
00178     case SIGPIPE:
00179             return "write on a pipe with no one to read it [SIGPIPE]";
00180 #endif /* SIGPIPE */
00181 
00182 #ifdef SIGALRM
00183     case SIGALRM:
00184             return "alarm clock [SIGALRM]";
00185 #endif /* SIGALRM */
00186 
00187 #ifdef SIGTERM
00188     case SIGTERM:
00189             return "software termination [SIGTERM]";
00190 #endif /* SIGTERM */
00191 
00192 #ifdef SIGUSR1
00193     case SIGUSR1:
00194             return "user defined signal one [SIGUSR1]";
00195 #endif /* SIGUSR1 */
00196 
00197 #ifdef SIGUSR2
00198     case SIGUSR2:
00199             return "user defined signal two [SIGUSR2]";
00200 #endif /* SIGUSR2 */
00201 
00202 #ifdef SIGCLD
00203     case SIGCLD:
00204             return "death of child [SIGCLD]";
00205 #endif /* SIGCLD */
00206 
00207 #ifdef SIGPWR
00208     case SIGPWR:
00209             return "power failure [SIGPWR]";
00210 #endif /* SIGPWR */
00211     }
00212     return 0;
00213 }
00214 
00215 #endif /* !HAVE_STRSIGNAL */
00216 
00217 
00218 const char *
00219 explain_strsignal(int n)
00220 {
00221     static char buffer[16];
00222     const char *s = strsignal(n);
00223     if (s && *s)
00224         return s;
00225     snprintf(buffer, sizeof(buffer), "signal %d", n);
00226     return buffer;
00227 }
00228 
00229 
00230 char *
00231 explain_strendcpy(char *dst, const char *src, const char *end)
00232 {
00233     if (dst < end)
00234     {
00235         /* leave room for terminating NUL */
00236         end--;
00237         while (dst < end && *src)
00238             *dst++ = *src++;
00239         *dst = '\0';
00240         if (*src)
00241         {
00242             /* return end parameter if truncated */
00243             dst++;
00244         }
00245     }
00246     return dst;
00247 }
00248 
00249 #ifndef HAVE_STRNSTR
00250 
00251 /* this should have LINKAGE_HIDDEN except that codegen needs it */
00252 
00253 char *
00254 strnstr(const char *haystack, const char *needle, size_t haystack_size)
00255 {
00256     size_t          needle_size;
00257     size_t          j;
00258 
00259     needle_size = strlen(needle);
00260     if (haystack_size < needle_size)
00261         return 0;
00262     for (j = 0; needle_size + j <= haystack_size; ++j)
00263     {
00264         if (0 == memcmp(haystack + j, needle, needle_size))
00265             return (char *)(haystack + j);
00266     }
00267     return 0;
00268 }
00269 
00270 #endif /* !HAVE_STRNSTR */
00271 
00272 
00273 /* vim: set ts=8 sw=4 et : */