2 * 2ooM: The Master of Orion II Reverse Engineering Project
3 * Utilities for out-of-band error propagation.
4 * Copyright © 2010, 2013-2014 Nick Bowler
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
31 #define _(s) dgettext(PACKAGE, s)
33 #if !defined(LBX_ERROR_LIMIT)
34 # define LBX_ERROR_LIMIT 256
37 static unsigned error_base, error_tip;
38 static int error_ring[LBX_ERROR_LIMIT];
40 static const char **user_errors;
41 static int user_error_count, user_error_max = 2;
43 #define MIN(a, b) ((a) < (b) ? (a) : (b))
45 int lbx_error_new(const char *str)
47 assert(user_error_count >= 0 && user_error_count <= user_error_max);
49 if (!user_errors || user_error_count == user_error_max) {
53 if (user_error_max >= MIN(SIZE_MAX, INT_MAX)/2 - LBX_EUBASE)
55 if (2 * user_error_max >= SIZE_MAX / sizeof *user_errors)
58 size = 2 * user_error_max * sizeof *user_errors;
59 new = realloc(user_errors, size);
66 user_errors[user_error_count] = str;
67 return LBX_EUBASE + user_error_count++;
70 int lbx_error_raise(int code)
72 if (code == LBX_EOK) {
74 } else if (code >= 0 && ((code >= LBX_EMAX && code < LBX_EUBASE)
75 || code >= LBX_EUBASE + user_error_count)) {
76 fprintf(stderr, "%s: invalid error code %d\n", __func__, code);
80 error_ring[error_tip++] = code;
81 error_tip %= LBX_ERROR_LIMIT;
83 if (error_tip == error_base) {
84 error_base = (error_base + 1) % LBX_ERROR_LIMIT;
91 static void getmsg(int error, const char **msg)
94 *msg = strerror(-error);
103 *msg = _("Bad magic number");
106 *msg = _("Invalid file format");
109 *msg = _("Invalid argument");
112 *msg = _("Memory allocation failed");
115 *msg = _("Unexpected end of file");
118 *msg = user_errors[error - LBX_EUBASE];
122 int lbx_error_peek(const char **msg)
124 int error = error_tip == error_base ? LBX_EOK : error_ring[error_base];
126 assert(error < LBX_EMAX || error >= LBX_EUBASE);
127 assert(error < LBX_EUBASE + user_error_count);
135 int lbx_error_get(const char **msg)
137 int error = lbx_error_peek(msg);
139 if (error != LBX_EOK)
140 error_base = (error_base + 1) % LBX_ERROR_LIMIT;