syncfiles/macos/error.c
Dietrich Epp b1bcae531b Rework error handling
Previously, various error handling functions were defined, but not all
of them were even used. The new error handling functions handle the most
common cases:

- Assertions. These can be handled with `ASSERT()`, which gives the
  error location for debugging.

- Errors we don't know how to handle, like GetNewWindow returning NULL.
  These can be handled with `EXIT_INTERNAL()`, which gives the error
  location for debugging.

- Out of memory conditions. These can be handled with `ShowMemError()`.

- System errors in response to user operations. These can be handled
  with `ShowError()`.
2023-05-06 19:41:40 -04:00

123 lines
2.9 KiB
C

// Copyright 2022 Dietrich Epp.
// This file is part of SyncFiles. SyncFiles is licensed under the terms of the
// Mozilla Public License, version 2.0. See LICENSE.txt for details.
#include "macos/error.h"
#include "lib/defs.h"
#include "macos/main.h"
#include "macos/pstrbuilder.h"
#include "macos/resources.h"
#include <Dialogs.h>
#include <TextUtils.h>
enum {
// OK
kStrOK = 1,
// Quit
kStrQuit,
// An error of type ^2 occurred.
kStrErrorCode,
// Error at: ^1:^2
kStrErrorAt,
// Assertion: ^1
kStrAssertion,
// An internal error occurred.
kStrInternal,
// An unknown error occurred.
kStrUnknown,
// (Base value for error messages.)
kStrMessageBase
};
static void AppendErrorArray(struct PStrBuilder *str, int sep, int strNum,
int paramCount, const unsigned char *const *params)
{
Str255 message;
if (str->data[0] > 0 && sep != 0) {
PStrAppendChar(str, sep);
}
GetIndString(message, rSTRS_Errors, strNum);
if (message[0] == 0) {
PStrAppendChar(str, '?');
} else {
PStrAppendSubstitute(str, message, paramCount, params);
}
}
static void AppendError0(struct PStrBuilder *str, int sep, int strNum)
{
AppendErrorArray(str, sep, strNum, 0, NULL);
}
static void AppendError1(struct PStrBuilder *str, int sep, int strNum,
const unsigned char *strParam)
{
AppendErrorArray(str, sep, strNum, 1, &strParam);
}
static void AppendError2(struct PStrBuilder *str, int sep, int strNum,
const unsigned char *strParam, int intParam)
{
unsigned char num[16];
const unsigned char *params[2];
params[0] = strParam;
NumToString(intParam, num);
params[1] = num;
AppendErrorArray(str, sep, strNum, 2, params);
}
static void ShowErrorAlert(const unsigned char *message, int button)
{
Str255 buttonText;
GetIndString(buttonText, rSTRS_Errors, button);
ParamText(message, buttonText, NULL, NULL);
Alert(rAlrtError, NULL);
}
void ExitAssert(const unsigned char *file, int line,
const unsigned char *assertion)
{
struct PStrBuilder str;
PStrInit(&str);
AppendError0(&str, 0, kStrInternal);
if (file != NULL) {
AppendError2(&str, '\r', kStrErrorAt, file, line);
}
if (assertion != NULL) {
AppendError1(&str, '\r', kStrAssertion, assertion);
}
ShowErrorAlert(str.data, kStrQuit);
QuitApp();
}
void ShowError(ErrorCode err1, ErrorCode err2, short osErr,
const unsigned char *strParam)
{
struct PStrBuilder str;
PStrInit(&str);
if (err1 != kErrNone) {
AppendError1(&str, ' ', kStrMessageBase - 1 + err1, strParam);
}
if (err2 != kErrNone) {
AppendError1(&str, ' ', kStrMessageBase - 1 + err2, strParam);
}
if (osErr != 0) {
AppendError2(&str, ' ', kStrErrorCode, NULL, osErr);
}
if (str.data[0] == 0) {
AppendError0(&str, ' ', kStrUnknown);
}
ShowErrorAlert(str.data, kStrOK);
}
void ShowMemError(void)
{
ShowError(kErrOutOfMemory, kErrNone, MemError(), NULL);
}