Skip to content

Instantly share code, notes, and snippets.

@Tpaefawzen
Created February 19, 2026 13:01
Show Gist options
  • Select an option

  • Save Tpaefawzen/382cb384211c0f57bde05b0337f8481d to your computer and use it in GitHub Desktop.

Select an option

Save Tpaefawzen/382cb384211c0f57bde05b0337f8481d to your computer and use it in GitHub Desktop.
Use array of jmp_buf and setjmp() and longjmp() for error handing
#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>
typedef unsigned char u8;
typedef enum {
ParseError_InvalidCharacter,
ParseError_Overflow,
ParseError__end,
} ParseError;
static u8 parseU8(char *my_str0, jmp_buf parse_err[ParseError__end]) {
enum { u8_max = 255, };
u8* my_str = (u8*)my_str0;
u8 ret = 0;
if (*my_str == 0) longjmp(parse_err[ParseError_InvalidCharacter], 1);
for (u8 c; (c = *my_str); my_str++) {
if (c < '0' || '9' < c) longjmp(parse_err[ParseError_InvalidCharacter], 1);
u8 n = c - '0';
if ( (ret > u8_max/10) || (n > u8_max - ret*10) ) longjmp(parse_err[ParseError_Overflow], 1);
ret = ret * 10 + n;
}
return ret;
}
typedef struct {
int has_g;
char** rest_args;
u8 val_n;
} MyOptResult;
typedef enum {
GetOptError_UnknownOption,
GetOptError_MissingArgument,
GetOptError__end,
} GetOptError;
static MyOptResult parseArgs(int argc, char **argv, jmp_buf parse_err[ParseError__end], jmp_buf get_opt_err[GetOptError__end]) {
static char *default_rest_args[] = {"World", 0, };
MyOptResult ret;
ret.has_g = 0;
ret.val_n = 1;
ret.rest_args = default_rest_args;
if (argc < 2) return ret;
int i;
for (i = 1; i < argc && argv[i][0] == '-' && argv[i][1]; i++) {
if (argv[i][1] == 0) break;
if (argv[i][1] == '-' && argv[i][2] == 0) { i++; break; }
char c;
for (int j = 1; (c = argv[i][j]); j++) {
switch (c) {
case 'g': ret.has_g = 1; break;
case 'n':
{
char *arg_of_n = &argv[i][++j];
if (*arg_of_n == 0) arg_of_n = argv[++i];
if (i >= argc) longjmp(get_opt_err[GetOptError_MissingArgument], 1);
ret.val_n = parseU8(arg_of_n, parse_err);
}
break;
default: longjmp(get_opt_err[GetOptError_UnknownOption], 1);
}
if (c == 'n') break;
}
}
if (i < argc) ret.rest_args = &argv[i];
return ret;
}
int main(int argc, char **argv) {
jmp_buf parse_err[ParseError__end], get_opt_err[GetOptError__end];
volatile char *err_str = 0;
if (setjmp(parse_err[ParseError_InvalidCharacter])) {
err_str = "InvalidCharacter";
} else if (setjmp(parse_err[ParseError_Overflow])) {
err_str = "Overflow";
} else if (setjmp(get_opt_err[GetOptError_UnknownOption])) {
err_str = "UnknownOption";
} else if (setjmp(get_opt_err[GetOptError_MissingArgument])) {
err_str = "MissingArgument";
}
if (err_str) {
fprintf(stderr, "Error: %s\n", err_str);
exit(1);
}
MyOptResult arg_result = parseArgs(argc, argv, parse_err, get_opt_err);
for (u8 i = arg_result.val_n; i--; )
for (char **p_a = arg_result.rest_args; *p_a; p_a++)
printf("%s, %s!\n", arg_result.has_g ? "Goodbye" : "Hello", *p_a);
}
## Synopsis
./hello [-g] [-n num_repeats] [Args ...]
@Tpaefawzen
Copy link
Author

Obtw today I learned that placing label for goto statement to end of body of for-loop (or block) is C23 feature.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment