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