Skip to content

Commit

Permalink
cii: Add except
Browse files Browse the repository at this point in the history
  • Loading branch information
XuShaohua committed Nov 11, 2023
1 parent c678add commit 5839495
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 0 deletions.
2 changes: 2 additions & 0 deletions cii/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ set(CMAKE_C_STANDARD 11)

set(SOURCE_FILES
src/atom.c
src/except.c
src/hash.c
)
set(HEADER_FILES
include/cii/atom.h
include/cii/except.h
include/cii/hash.h
)

Expand Down
96 changes: 96 additions & 0 deletions cii/include/cii/except.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// Copyright (c) 2023 Xu Shaohua <[email protected]>. All rights reserved.
// Use of this source is governed by GNU General Public License
// that can be found in the LICENSE file.

#ifndef CII_EXCEPT_H_
#define CII_EXCEPT_H_

#include <setjmp.h>

struct except_s {
int type;
const char* reason;
};

typedef struct except_s except_t;

struct except_frame_s {
struct except_frame_s* prev;
jmp_buf env;
const char* file;
int line;
const except_t* exception;
};

typedef struct except_frame_s except_frame_t;

// Global exception stack frame.
extern except_frame_t* g_except_stack;

enum except_state_e {
except_state_entered = 0,
except_state_raised,
except_state_handled,
except_state_finalized,
};

/**
* It is a checked runtime error if e is null.
*
* @param e is a pointer to global or static except_t instance.
* @param file source file name where exception occurs.
* @param line line number where exception occurs.
*/
void except_raise(const except_t* e, const char* file, int line);

#define RAISE(e) except_raise(&(e), __FILE__, __LINE__)

#define REREAISE \
except_raise(except_frame.exception, except_frame.file, except_frame.line)

#define RETURN switch(0) default: return

#define TRY \
do { \
volatile except_state_e except_flag; \
except_frame_t except_frame; \
except_frame.prev = g_except_stack; \
g_except_stack = &except_frame; \
except_flag = setjmp(except_frame.env); \
if (except_flag == except_state_entered) { \

#define EXCEPT(e) \
if (except_flag == except_state_entered) { \
g_except_stack = except_stack->prev; \
} \
} else if (except_frame.exception == &(e)) { \
except_flag = except_state_handled;

#define ELSE \
if (except_flag == except_state_entered) { \
g_except_stack = except_stack->prev; \
} \
} else { \
except_flag = except_state_handled;

#define FINALLY \
if (except_flag == except_state_entered) { \
g_except_stack = except_stack->prev; \
} \
} \
{ \
if (except_flag == except_state_entered) { \
except_flag = except_state_finalized; \
}

#define END_TRY \
if (except_flag == except_state_entered) { \
g_except_stack = except_stack->prev; \
} \
} \
if (except_flag == except_raised) { \
RERAISE; \
} \
} while (0)

#endif // CII_EXCEPT_H_
16 changes: 16 additions & 0 deletions cii/include/cii/mem.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright (c) 2023 Xu Shaohua <[email protected]>. All rights reserved.
// Use of this source is governed by GNU General Public License
// that can be found in the LICENSE file.

#ifndef CII_MEM_H_
#define CII_MEM_H_

#include <stddef.h>

extern const except_t mem_failed;

void* mem_alloc(size_t nbytes, const char* file, int line);

void* mem_calloc(size_t count, size_t nbytes, const char* file, int line);

#endif // CII_MEM_H_
42 changes: 42 additions & 0 deletions cii/src/except.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright (c) 2023 Xu Shaohua <[email protected]>. All rights reserved.
// Use of this source is governed by GNU General Public License
// that can be found in the LICENSE file.

#include "cii/except.h"

#include <assert.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>

except_frame_t* g_except_stack = NULL;

void except_raise(const except_t* e, const char* file, int line) {
except_frame_t* frame = g_except_stack;
assert(e != NULL);

if (frame == NULL) {
// uncaught exception.
fprintf(stderr, "Uncaught exception");
if (e->reason != NULL) {
fprintf(stderr, " %s", e->reason);
} else {
fprintf(stderr, " at 0x%p", e);
}
if (file != NULL && line > 0) {
fprintf(stderr, " raised at %s:%d\n", file, line);
} else {
fprintf(stderr, "\n");
}
fprintf(stderr, "aborting...\n");
fflush(stderr);
abort();
}

frame->exception = e;
frame->file = file;
frame->line = line;
// pop except frame.
g_except_stack = frame->prev;
longjmp(frame->env, except_state_raised);
}
6 changes: 6 additions & 0 deletions cii/src/mem.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Copyright (c) 2023 Xu Shaohua <[email protected]>. All rights reserved.
// Use of this source is governed by GNU General Public License
// that can be found in the LICENSE file.

#include "cii/mem.h"

0 comments on commit 5839495

Please sign in to comment.