При написании библиотеки столкнулся с рядом проблем, которые мне трудно решить. Поэтому публикую исходный код тестовой версии библиотеки. Я использую ANSI C'99 совместимый компилятор пока (в конце вычищу код для C'89), поэтому по ходу могут встречаться комментарии в стиле С++.
В тестовой версии библиотеки все глобальные переменные прямо лежат внутри заголовочного файла. Это сделано для упрощения отладки. Т.е. грубо говоря, эта версия всего лишь модель. После получения работоспособной модели все глобальные переменные будут локализованы в исходном файле библиотеки, будут статическими и доступ к ним будет осуществляться только через функции.
Цель создания библиотеки:
* Получить преимущества обработки исключений в языке С. О различиях между SEH и обычным подходом проверки возвращаемых значений функцией можно почитать у Б. Страуструпа в 14 главе русского "Язык программирования С++"* Получить высокопортируемую библиотеку, которую можно будет использовать на любой платформе, где есть стандартная библиотека С.
Из недостатков можно выделить:
* _Синтаксическую_ (но не идеологическую) несовместимость с С++ ;(* Незащищённость от многопоточночти из-за применения статических переменных. В планах, после завершения варианта для однопоточных переменных приступить к реализации версии, корректно работающей с многопоточными приложениями
Общая Концепция библиотеки состоит в следующем:
Код: Выделить всё
//..............
TRY {
// тестируемый код1
TRY {
// вложенный тестируемый код2
THROW (100);
// продолжение вложенного кода, который не выполнится
}
CATCH (200) {
// обработчик 1
}
CATCH (100) {
// обработчик 2, в который мы попадём
THROW (10);
// код, который никогда не выполнится
}
CATCHALL {
// код, обрабатывающий все остальные ситуации
}
TRYEND; // конец вложенного обработчика
}
CATCHALL {
// обработка всех исключительных ситуаций. Сюда мы попадём по строчке THROW (10);
}
TRYEND;
// ................
Код: Выделить всё
/* excpt.h -- тестовая версия заголовочного файла */
#ifndef N0PEXCEPT_H_
# define N0PEXCEPT_H_
# ifdef __cplusplus
extern "C" {
# endif
# include <stdio.h>
# include <setjmp.h>
/* Включение или выключение кода обработки исключений. Для выключения
необходимо закоментировать строчку */
# define N0PEXCEPT_ON_
/* Максимальный уровень вложений обработчика исключений */
# define MAX_NESTED_LEVEL_ 40
//------------------------------------------------------------------------------
/* Состояние текущего прерывания */
typedef struct EXCPT_T EXCPT_T;
struct EXCPT_T {
/* Буффер для сохранения состояния */
jmp_buf jbuf;
/* Код возврата из setjmp() */
int ret;
}; /* EXCPT_T */
/* Текущий глобальный уровень вложенности обработчиков исключений */
int i = -1;
/* Текущий локальный уровень вложенности обработчиков исключений */
int j = -1;
/* Массив структур состояний */
EXCPT_T jbuf[MAX_NESTED_LEVEL_];
//------------------------------------------------------------------------------
# ifdef N0PEXCEPT_ON_
#define DBGTRYIN(func, num) \
printf("i=%d, j = %d >>> " #func ".TRY." #num " >>>\n", i, j)
#define DBGTRYOUT(func, num) \
printf("i=%d, j = %d <<< " #func ".TRY." #num " <<<\n", i, j)
#define DBGCATCHIN(func, num, val) \
printf("\ti=%d, j = %d >>> " #func ".CATCH(" #val ")." #num " >>>\n", i, j)
#define DBGCATCHOUT(func, num, val) \
printf("\ti=%d, j = %d <<< " #func ".CATCH(" #val ")." #num " <<<\n", i, j)
#define DBGCATCHALLIN(func, num) \
printf("\ti=%d, j = %d >>> " #func ".CATCHALL." #num " >>>\n", i, j)
#define DBGCATCHALLOUT(func, num) \
printf("\ti=%d, j = %d <<< " #func ".CATCHALL." #num " <<<\n", i, j)
/* Попытка выполнить кусок кода */
# define TRY \
do { \
j = i; \
j++; \
jbuf[j].ret = setjmp(jbuf[j].jbuf); \
if (0 == jbuf[j].ret) {
# define TRYEND \
i = j; \
} \
} while (0)
/* Перехват исключительной ситуации */
# define CATCH(x) \
i = j; \
} else if ((x) == jbuf[j].ret) {
# define CATCHALL \
i = j; \
} else {
/* Выброс исключительной ситуации */
# define THROW(x) \
longjmp(jbuf[j].jbuf, (x))
# else
# define TRY
# define TRYEND
# define CATCH(x) if (0)
# define CATCHALL if (0)
# define THROW(x)
# endif /* N0PEXCEPT_ON_ */
# ifdef __cplusplus
}
# endif
#endif /* N0PEXCEPT_H_ */