Skip to content

Commit 2c0caa6

Browse files
authored
Update 2024-03-21-setjmp-plus-longjmp-equals-goto-but-awesome.md
1 parent 8259d8f commit 2c0caa6

File tree

1 file changed

+12
-15
lines changed

1 file changed

+12
-15
lines changed

_posts/2024-03-21-setjmp-plus-longjmp-equals-goto-but-awesome.md

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@ If you've ever written a decently sized C program before, you will have struggle
88

99
I am implementing [my modding language called grug]({{ site.baseurl }} {% link _posts/2024-02-29-creating-the-perfect-modding-language.md %}) in C right now, and so far I have just printed the error and exited the program whenever an error was encountered.
1010

11-
Here is a snippet from grug's tokenizer. The if-statement is necessary to prevent `tokens.tokens[token_index]` from segfaulting the entire game whenever a mod has a typo in it:
11+
Here is a snippet from grug's tokenizer. The if-statement is necessary to prevent `tokens[token_index]` from segfaulting the entire game whenever a mod has a typo in it:
1212

1313
```bettercpp
14-
static token get_token(size_t token_index) {
14+
struct token peek_token(size_t token_index) {
1515
if (token_index >= tokens.size) {
16-
fprintf(stderr, "token_index %zu was out of bounds in get_token()\n", token_index);
16+
fprintf(stderr, "token_index %zu was out of bounds in peek_token()\n", token_index);
1717
exit(EXIT_FAILURE);
1818
}
19-
return tokens.tokens[token_index];
19+
return tokens[token_index];
2020
}
2121
```
2222

@@ -40,20 +40,20 @@ bool error_happened = false;
4040
Which are used to print the message to a buffer, and to remember that something went wrong, like so:
4141

4242
```bettercpp
43-
static token get_token(size_t token_index) {
43+
struct token peek_token(size_t token_index) {
4444
if (token_index >= tokens.size) {
45-
snprintf(error_msg, sizeof(error_msg), "token_index %zu was out of bounds in get_token()", token_index);
45+
snprintf(error_msg, sizeof(error_msg), "token_index %zu was out of bounds in peek_token()", token_index);
4646
error_happened = true;
47-
return (token){0}; // Just `return;` won't compile, so return an empty token :(
47+
return (struct token){0}; // Just `return;` won't compile, so return an empty token :(
4848
}
49-
return tokens.tokens[token_index];
49+
return tokens[token_index];
5050
}
5151
```
5252

5353
But now that the program doesn't immediately exit on error, `if (error_happened) return;` has to pasted after every single call that can directly or indirectly(!) throw an error:
5454

5555
```bettercpp
56-
token token = get_token(i);
56+
struct token token = peek_token(i);
5757
if (error_happened) return;
5858
char *token_type_str = get_token_type_str[token.type];
5959
```
@@ -140,12 +140,9 @@ Compiling and running this program with `gcc foo.c && ./a.out` [on godbolt.org](
140140
And this is how grug finally uses `snprintf()` and `longjmp()` to throw a formatted error message in a few dozen spots:
141141

142142
```bettercpp
143-
static token get_token(size_t token_index) {
144-
if (token_index >= tokens.size) {
145-
snprintf(error_msg, sizeof(error_msg), "token_index %zu was out of bounds in get_token()", token_index);
146-
longjmp(jmp_buffer, 1);
147-
}
148-
return tokens.tokens[token_index];
143+
struct token peek_token(size_t token_index) {
144+
grug_assert(token_index < tokens_size, "token_index %zu was out of bounds in peek_token()", token_index);
145+
return tokens[token_index];
149146
}
150147
```
151148

0 commit comments

Comments
 (0)