1d5ac70f0Sopenharmony_ci/** 2d5ac70f0Sopenharmony_ci * \file error.c 3d5ac70f0Sopenharmony_ci * \brief Error code handling routines 4d5ac70f0Sopenharmony_ci * \author Jaroslav Kysela <perex@perex.cz> 5d5ac70f0Sopenharmony_ci * \date 1998-2001 6d5ac70f0Sopenharmony_ci * 7d5ac70f0Sopenharmony_ci * Error code handling routines. 8d5ac70f0Sopenharmony_ci */ 9d5ac70f0Sopenharmony_ci/* 10d5ac70f0Sopenharmony_ci * Copyright (c) 1998 by Jaroslav Kysela <perex@perex.cz> 11d5ac70f0Sopenharmony_ci * 12d5ac70f0Sopenharmony_ci * snd_strerror routine needs to be recoded for the locale support 13d5ac70f0Sopenharmony_ci * 14d5ac70f0Sopenharmony_ci * 15d5ac70f0Sopenharmony_ci * This library is free software; you can redistribute it and/or modify 16d5ac70f0Sopenharmony_ci * it under the terms of the GNU Lesser General Public License as 17d5ac70f0Sopenharmony_ci * published by the Free Software Foundation; either version 2.1 of 18d5ac70f0Sopenharmony_ci * the License, or (at your option) any later version. 19d5ac70f0Sopenharmony_ci * 20d5ac70f0Sopenharmony_ci * This program is distributed in the hope that it will be useful, 21d5ac70f0Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 22d5ac70f0Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23d5ac70f0Sopenharmony_ci * GNU Lesser General Public License for more details. 24d5ac70f0Sopenharmony_ci * 25d5ac70f0Sopenharmony_ci * You should have received a copy of the GNU Lesser General Public 26d5ac70f0Sopenharmony_ci * License along with this library; if not, write to the Free Software 27d5ac70f0Sopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 28d5ac70f0Sopenharmony_ci * 29d5ac70f0Sopenharmony_ci */ 30d5ac70f0Sopenharmony_ci 31d5ac70f0Sopenharmony_ci#include "local.h" 32d5ac70f0Sopenharmony_ci#include <stdio.h> 33d5ac70f0Sopenharmony_ci#include <stdlib.h> 34d5ac70f0Sopenharmony_ci#include <stdarg.h> 35d5ac70f0Sopenharmony_ci#include <string.h> 36d5ac70f0Sopenharmony_ci 37d5ac70f0Sopenharmony_ci/** 38d5ac70f0Sopenharmony_ci * Array of error codes in US ASCII. 39d5ac70f0Sopenharmony_ci */ 40d5ac70f0Sopenharmony_cistatic const char *snd_error_codes[] = 41d5ac70f0Sopenharmony_ci{ 42d5ac70f0Sopenharmony_ci "Sound protocol is not compatible" 43d5ac70f0Sopenharmony_ci}; 44d5ac70f0Sopenharmony_ci 45d5ac70f0Sopenharmony_ci/** 46d5ac70f0Sopenharmony_ci * \brief Returns the message for an error code. 47d5ac70f0Sopenharmony_ci * \param errnum The error code number, which must be a system error code 48d5ac70f0Sopenharmony_ci * or an ALSA error code. 49d5ac70f0Sopenharmony_ci * \return The ASCII description of the given numeric error code. 50d5ac70f0Sopenharmony_ci */ 51d5ac70f0Sopenharmony_ciconst char *snd_strerror(int errnum) 52d5ac70f0Sopenharmony_ci{ 53d5ac70f0Sopenharmony_ci if (errnum < 0) 54d5ac70f0Sopenharmony_ci errnum = -errnum; 55d5ac70f0Sopenharmony_ci if (errnum < SND_ERROR_BEGIN) 56d5ac70f0Sopenharmony_ci return (const char *) strerror(errnum); 57d5ac70f0Sopenharmony_ci errnum -= SND_ERROR_BEGIN; 58d5ac70f0Sopenharmony_ci if ((unsigned int) errnum >= sizeof(snd_error_codes) / sizeof(const char *)) 59d5ac70f0Sopenharmony_ci return "Unknown error"; 60d5ac70f0Sopenharmony_ci return snd_error_codes[errnum]; 61d5ac70f0Sopenharmony_ci} 62d5ac70f0Sopenharmony_ci 63d5ac70f0Sopenharmony_ci#ifndef DOC_HIDDEN 64d5ac70f0Sopenharmony_ci#ifdef HAVE___THREAD 65d5ac70f0Sopenharmony_ci#define TLS_PFX __thread 66d5ac70f0Sopenharmony_ci#else 67d5ac70f0Sopenharmony_ci#define TLS_PFX /* NOP */ 68d5ac70f0Sopenharmony_ci#endif 69d5ac70f0Sopenharmony_ci#endif 70d5ac70f0Sopenharmony_ci 71d5ac70f0Sopenharmony_cistatic TLS_PFX snd_local_error_handler_t local_error = NULL; 72d5ac70f0Sopenharmony_ci 73d5ac70f0Sopenharmony_ci/** 74d5ac70f0Sopenharmony_ci * \brief Install local error handler 75d5ac70f0Sopenharmony_ci * \param func The local error handler function 76d5ac70f0Sopenharmony_ci * \retval Previous local error handler function 77d5ac70f0Sopenharmony_ci */ 78d5ac70f0Sopenharmony_cisnd_local_error_handler_t snd_lib_error_set_local(snd_local_error_handler_t func) 79d5ac70f0Sopenharmony_ci{ 80d5ac70f0Sopenharmony_ci snd_local_error_handler_t old = local_error; 81d5ac70f0Sopenharmony_ci local_error = func; 82d5ac70f0Sopenharmony_ci return old; 83d5ac70f0Sopenharmony_ci} 84d5ac70f0Sopenharmony_ci 85d5ac70f0Sopenharmony_ci/** 86d5ac70f0Sopenharmony_ci * \brief The default error handler function. 87d5ac70f0Sopenharmony_ci * \param file The filename where the error was hit. 88d5ac70f0Sopenharmony_ci * \param line The line number. 89d5ac70f0Sopenharmony_ci * \param function The function name. 90d5ac70f0Sopenharmony_ci * \param err The error code. 91d5ac70f0Sopenharmony_ci * \param fmt The message (including the format characters). 92d5ac70f0Sopenharmony_ci * \param ... Optional arguments. 93d5ac70f0Sopenharmony_ci * 94d5ac70f0Sopenharmony_ci * If a local error function has been installed for the current thread by 95d5ac70f0Sopenharmony_ci * \ref snd_lib_error_set_local, it is called. Otherwise, prints the error 96d5ac70f0Sopenharmony_ci * message including location to \c stderr. 97d5ac70f0Sopenharmony_ci */ 98d5ac70f0Sopenharmony_cistatic void snd_lib_error_default(const char *file, int line, const char *function, int err, const char *fmt, ...) 99d5ac70f0Sopenharmony_ci{ 100d5ac70f0Sopenharmony_ci va_list arg; 101d5ac70f0Sopenharmony_ci va_start(arg, fmt); 102d5ac70f0Sopenharmony_ci if (local_error) { 103d5ac70f0Sopenharmony_ci local_error(file, line, function, err, fmt, arg); 104d5ac70f0Sopenharmony_ci va_end(arg); 105d5ac70f0Sopenharmony_ci return; 106d5ac70f0Sopenharmony_ci } 107d5ac70f0Sopenharmony_ci fprintf(stderr, "ALSA lib %s:%i:(%s) ", file, line, function); 108d5ac70f0Sopenharmony_ci vfprintf(stderr, fmt, arg); 109d5ac70f0Sopenharmony_ci if (err) 110d5ac70f0Sopenharmony_ci fprintf(stderr, ": %s", snd_strerror(err)); 111d5ac70f0Sopenharmony_ci putc('\n', stderr); 112d5ac70f0Sopenharmony_ci va_end(arg); 113d5ac70f0Sopenharmony_ci} 114d5ac70f0Sopenharmony_ci 115d5ac70f0Sopenharmony_ci/** 116d5ac70f0Sopenharmony_ci * \ingroup Error 117d5ac70f0Sopenharmony_ci * Pointer to the error handler function. 118d5ac70f0Sopenharmony_ci * For internal use only. 119d5ac70f0Sopenharmony_ci */ 120d5ac70f0Sopenharmony_cisnd_lib_error_handler_t snd_lib_error = snd_lib_error_default; 121d5ac70f0Sopenharmony_ci 122d5ac70f0Sopenharmony_ci/** 123d5ac70f0Sopenharmony_ci * \brief Sets the error handler. 124d5ac70f0Sopenharmony_ci * \param handler The pointer to the new error handler function. 125d5ac70f0Sopenharmony_ci * 126d5ac70f0Sopenharmony_ci * This function sets a new error handler, or (if \c handler is \c NULL) 127d5ac70f0Sopenharmony_ci * the default one which prints the error messages to \c stderr. 128d5ac70f0Sopenharmony_ci */ 129d5ac70f0Sopenharmony_ciint snd_lib_error_set_handler(snd_lib_error_handler_t handler) 130d5ac70f0Sopenharmony_ci{ 131d5ac70f0Sopenharmony_ci snd_lib_error = handler == NULL ? snd_lib_error_default : handler; 132d5ac70f0Sopenharmony_ci#ifndef NDEBUG 133d5ac70f0Sopenharmony_ci if (snd_lib_error != snd_lib_error_default) 134d5ac70f0Sopenharmony_ci snd_err_msg = snd_lib_error; 135d5ac70f0Sopenharmony_ci#endif 136d5ac70f0Sopenharmony_ci return 0; 137d5ac70f0Sopenharmony_ci} 138d5ac70f0Sopenharmony_ci 139d5ac70f0Sopenharmony_ci/** 140d5ac70f0Sopenharmony_ci * \brief Returns the ALSA sound library version in ASCII format 141d5ac70f0Sopenharmony_ci * \return The ASCII description of the used ALSA sound library. 142d5ac70f0Sopenharmony_ci */ 143d5ac70f0Sopenharmony_ciconst char *snd_asoundlib_version(void) 144d5ac70f0Sopenharmony_ci{ 145d5ac70f0Sopenharmony_ci return SND_LIB_VERSION_STR; 146d5ac70f0Sopenharmony_ci} 147d5ac70f0Sopenharmony_ci 148d5ac70f0Sopenharmony_ci#ifndef NDEBUG 149d5ac70f0Sopenharmony_ci/* 150d5ac70f0Sopenharmony_ci * internal error handling 151d5ac70f0Sopenharmony_ci */ 152d5ac70f0Sopenharmony_cistatic void snd_err_msg_default(const char *file, int line, const char *function, int err, const char *fmt, ...) 153d5ac70f0Sopenharmony_ci{ 154d5ac70f0Sopenharmony_ci va_list arg; 155d5ac70f0Sopenharmony_ci const char *verbose; 156d5ac70f0Sopenharmony_ci 157d5ac70f0Sopenharmony_ci verbose = getenv("LIBASOUND_DEBUG"); 158d5ac70f0Sopenharmony_ci if (! verbose || ! *verbose) 159d5ac70f0Sopenharmony_ci return; 160d5ac70f0Sopenharmony_ci va_start(arg, fmt); 161d5ac70f0Sopenharmony_ci fprintf(stderr, "ALSA lib %s:%i:(%s) ", file, line, function); 162d5ac70f0Sopenharmony_ci vfprintf(stderr, fmt, arg); 163d5ac70f0Sopenharmony_ci if (err) 164d5ac70f0Sopenharmony_ci fprintf(stderr, ": %s", snd_strerror(err)); 165d5ac70f0Sopenharmony_ci putc('\n', stderr); 166d5ac70f0Sopenharmony_ci va_end(arg); 167d5ac70f0Sopenharmony_ci#ifdef ALSA_DEBUG_ASSERT 168d5ac70f0Sopenharmony_ci verbose = getenv("LIBASOUND_DEBUG_ASSERT"); 169d5ac70f0Sopenharmony_ci if (verbose && *verbose) 170d5ac70f0Sopenharmony_ci assert(0); 171d5ac70f0Sopenharmony_ci#endif 172d5ac70f0Sopenharmony_ci} 173d5ac70f0Sopenharmony_ci 174d5ac70f0Sopenharmony_ci/** 175d5ac70f0Sopenharmony_ci * The ALSA error message handler 176d5ac70f0Sopenharmony_ci */ 177d5ac70f0Sopenharmony_cisnd_lib_error_handler_t snd_err_msg = snd_err_msg_default; 178d5ac70f0Sopenharmony_ci 179d5ac70f0Sopenharmony_ci#endif 180d5ac70f0Sopenharmony_ci 181d5ac70f0Sopenharmony_ci/** 182d5ac70f0Sopenharmony_ci * \brief Copy a C-string into a sized buffer 183d5ac70f0Sopenharmony_ci * \param dst Where to copy the string to 184d5ac70f0Sopenharmony_ci * \param src Where to copy the string from 185d5ac70f0Sopenharmony_ci * \param size Size of destination buffer 186d5ac70f0Sopenharmony_ci * \retval The source string length 187d5ac70f0Sopenharmony_ci * 188d5ac70f0Sopenharmony_ci * The result is always a valid NUL-terminated string that fits 189d5ac70f0Sopenharmony_ci * in the buffer (unless, of course, the buffer size is zero). 190d5ac70f0Sopenharmony_ci * It does not pad out the result like strncpy() does. 191d5ac70f0Sopenharmony_ci */ 192d5ac70f0Sopenharmony_cisize_t snd_strlcpy(char *dst, const char *src, size_t size) 193d5ac70f0Sopenharmony_ci{ 194d5ac70f0Sopenharmony_ci size_t ret = strlen(src); 195d5ac70f0Sopenharmony_ci if (size) { 196d5ac70f0Sopenharmony_ci size_t len = ret >= size ? size - 1 : ret; 197d5ac70f0Sopenharmony_ci memcpy(dst, src, len); 198d5ac70f0Sopenharmony_ci dst[len] = '\0'; 199d5ac70f0Sopenharmony_ci } 200d5ac70f0Sopenharmony_ci return ret; 201d5ac70f0Sopenharmony_ci} 202