๐ŸŽ€ Toy Gemini Client Written in C99
cli retro gemini gemtext terminal tls lightweight minimal c99 gemini-protocol
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

deps(flag.h): update

Fuwn 0364b75f 65e32e70

+223 -227
+223 -227
include/viv/flag.h
··· 43 43 #ifdef FLAG_IMPLEMENTATION 44 44 45 45 typedef enum { 46 - FLAG_BOOL = 0, 47 - FLAG_UINT64, 48 - FLAG_SIZE, 49 - FLAG_STR, 50 - COUNT_FLAG_TYPES, 46 + FLAG_BOOL = 0, 47 + FLAG_UINT64, 48 + FLAG_SIZE, 49 + FLAG_STR, 50 + COUNT_FLAG_TYPES, 51 51 } Flag_Type; 52 52 53 53 static_assert(COUNT_FLAG_TYPES == 4, "Exhaustive Flag_Value definition"); 54 54 typedef union { 55 - char *as_str; 56 - uint64_t as_uint64; 57 - bool as_bool; 58 - size_t as_size; 55 + char *as_str; 56 + uint64_t as_uint64; 57 + bool as_bool; 58 + size_t as_size; 59 59 } Flag_Value; 60 60 61 61 typedef enum { 62 - FLAG_NO_ERROR = 0, 63 - FLAG_ERROR_UNKNOWN, 64 - FLAG_ERROR_NO_VALUE, 65 - FLAG_ERROR_INVALID_NUMBER, 66 - FLAG_ERROR_INTEGER_OVERFLOW, 67 - FLAG_ERROR_INVALID_SIZE_SUFFIX, 68 - COUNT_FLAG_ERRORS, 62 + FLAG_NO_ERROR = 0, 63 + FLAG_ERROR_UNKNOWN, 64 + FLAG_ERROR_NO_VALUE, 65 + FLAG_ERROR_INVALID_NUMBER, 66 + FLAG_ERROR_INTEGER_OVERFLOW, 67 + FLAG_ERROR_INVALID_SIZE_SUFFIX, 68 + COUNT_FLAG_ERRORS, 69 69 } Flag_Error; 70 70 71 71 typedef struct { 72 - Flag_Type type; 73 - char *name; 74 - char *desc; 75 - Flag_Value val; 76 - Flag_Value def; 72 + Flag_Type type; 73 + char *name; 74 + char *desc; 75 + Flag_Value val; 76 + Flag_Value def; 77 77 } Flag; 78 78 79 79 #ifndef FLAGS_CAP ··· 81 81 #endif 82 82 83 83 typedef struct { 84 - Flag flags[FLAGS_CAP]; 85 - size_t flags_count; 84 + Flag flags[FLAGS_CAP]; 85 + size_t flags_count; 86 86 87 - Flag_Error flag_error; 88 - char *flag_error_name; 87 + Flag_Error flag_error; 88 + char *flag_error_name; 89 89 90 - int rest_argc; 91 - char **rest_argv; 90 + int rest_argc; 91 + char **rest_argv; 92 92 } Flag_Context; 93 93 94 94 static Flag_Context flag_global_context; 95 95 96 96 Flag *flag_new(Flag_Type type, const char *name, const char *desc) 97 97 { 98 - Flag_Context *c = &flag_global_context; 98 + Flag_Context *c = &flag_global_context; 99 99 100 - assert(c->flags_count < FLAGS_CAP); 101 - Flag *flag = &c->flags[c->flags_count++]; 102 - memset(flag, 0, sizeof(*flag)); 103 - flag->type = type; 104 - // NOTE: I won't touch them I promise Kappa 105 - flag->name = (char*) name; 106 - flag->desc = (char*) desc; 107 - return flag; 100 + assert(c->flags_count < FLAGS_CAP); 101 + Flag *flag = &c->flags[c->flags_count++]; 102 + memset(flag, 0, sizeof(*flag)); 103 + flag->type = type; 104 + // NOTE: I won't touch them I promise Kappa 105 + flag->name = (char*) name; 106 + flag->desc = (char*) desc; 107 + return flag; 108 108 } 109 109 110 110 char *flag_name(void *val) 111 111 { 112 - Flag *flag = (Flag*) ((char*) val - offsetof(Flag, val)); 113 - return flag->name; 112 + Flag *flag = (Flag*) ((char*) val - offsetof(Flag, val)); 113 + return flag->name; 114 114 } 115 115 116 116 bool *flag_bool(const char *name, bool def, const char *desc) 117 117 { 118 - Flag *flag = flag_new(FLAG_BOOL, name, desc); 119 - flag->def.as_bool = def; 120 - flag->val.as_bool = def; 121 - return &flag->val.as_bool; 118 + Flag *flag = flag_new(FLAG_BOOL, name, desc); 119 + flag->def.as_bool = def; 120 + flag->val.as_bool = def; 121 + return &flag->val.as_bool; 122 122 } 123 123 124 124 uint64_t *flag_uint64(const char *name, uint64_t def, const char *desc) 125 125 { 126 - Flag *flag = flag_new(FLAG_UINT64, name, desc); 127 - flag->val.as_uint64 = def; 128 - flag->def.as_uint64 = def; 129 - return &flag->val.as_uint64; 126 + Flag *flag = flag_new(FLAG_UINT64, name, desc); 127 + flag->val.as_uint64 = def; 128 + flag->def.as_uint64 = def; 129 + return &flag->val.as_uint64; 130 130 } 131 131 132 132 size_t *flag_size(const char *name, uint64_t def, const char *desc) 133 133 { 134 - Flag *flag = flag_new(FLAG_SIZE, name, desc); 135 - flag->val.as_size = def; 136 - flag->def.as_size = def; 137 - return &flag->val.as_size; 134 + Flag *flag = flag_new(FLAG_SIZE, name, desc); 135 + flag->val.as_size = def; 136 + flag->def.as_size = def; 137 + return &flag->val.as_size; 138 138 } 139 139 140 140 char **flag_str(const char *name, const char *def, const char *desc) 141 141 { 142 - Flag *flag = flag_new(FLAG_STR, name, desc); 143 - flag->val.as_str = (char*) def; 144 - flag->def.as_str = (char*) def; 145 - return &flag->val.as_str; 142 + Flag *flag = flag_new(FLAG_STR, name, desc); 143 + flag->val.as_str = (char*) def; 144 + flag->def.as_str = (char*) def; 145 + return &flag->val.as_str; 146 146 } 147 147 148 148 static char *flag_shift_args(int *argc, char ***argv) 149 149 { 150 - assert(*argc > 0); 151 - char *result = **argv; 152 - *argv += 1; 153 - *argc -= 1; 154 - return result; 150 + assert(*argc > 0); 151 + char *result = **argv; 152 + *argv += 1; 153 + *argc -= 1; 154 + return result; 155 155 } 156 156 157 157 int flag_rest_argc(void) 158 158 { 159 - return flag_global_context.rest_argc; 159 + return flag_global_context.rest_argc; 160 160 } 161 161 162 162 char **flag_rest_argv(void) 163 163 { 164 - return flag_global_context.rest_argv; 164 + return flag_global_context.rest_argv; 165 165 } 166 166 167 167 bool flag_parse(int argc, char **argv) 168 168 { 169 - Flag_Context *c = &flag_global_context; 169 + Flag_Context *c = &flag_global_context; 170 170 171 - flag_shift_args(&argc, &argv); 172 - 173 - while (argc > 0) { 174 - char *flag = flag_shift_args(&argc, &argv); 171 + flag_shift_args(&argc, &argv); 175 172 176 - if (*flag != '-') { 177 - // NOTE: pushing flag back into args 178 - c->rest_argc = argc + 1; 179 - c->rest_argv = argv - 1; 180 - return true; 181 - } 173 + while (argc > 0) { 174 + char *flag = flag_shift_args(&argc, &argv); 182 175 183 - if (strcmp(flag, "--") == 0) { 184 - // NOTE: but if it's the terminator we don't need to push it back 185 - c->rest_argc = argc; 186 - c->rest_argv = argv; 187 - return true; 188 - } 176 + if (*flag != '-') { 177 + // NOTE: pushing flag back into args 178 + c->rest_argc = argc + 1; 179 + c->rest_argv = argv - 1; 180 + return true; 181 + } 189 182 190 - // NOTE: remove the dash 191 - flag += 1; 183 + if (strcmp(flag, "--") == 0) { 184 + // NOTE: but if it's the terminator we don't need to push it back 185 + c->rest_argc = argc; 186 + c->rest_argv = argv; 187 + return true; 188 + } 192 189 193 - bool found = false; 194 - for (size_t i = 0; i < c->flags_count; ++i) { 195 - if (strcmp(c->flags[i].name, flag) == 0) { 196 - static_assert(COUNT_FLAG_TYPES == 4, "Exhaustive flag type parsing"); 197 - switch (c->flags[i].type) { 198 - case FLAG_BOOL: { 199 - c->flags[i].val.as_bool = true; 200 - } 201 - break; 190 + // NOTE: remove the dash 191 + flag += 1; 202 192 203 - case FLAG_STR: { 204 - if (argc == 0) { 205 - c->flag_error = FLAG_ERROR_NO_VALUE; 206 - c->flag_error_name = flag; 207 - return false; 208 - } 209 - char *arg = flag_shift_args(&argc, &argv); 210 - c->flags[i].val.as_str = arg; 211 - } 212 - break; 193 + bool found = false; 194 + for (size_t i = 0; i < c->flags_count; ++i) { 195 + if (strcmp(c->flags[i].name, flag) == 0) { 196 + static_assert(COUNT_FLAG_TYPES == 4, "Exhaustive flag type parsing"); 197 + switch (c->flags[i].type) { 198 + case FLAG_BOOL: { 199 + c->flags[i].val.as_bool = true; 200 + } 201 + break; 213 202 214 - case FLAG_UINT64: { 215 - if (argc == 0) { 216 - c->flag_error = FLAG_ERROR_NO_VALUE; 217 - c->flag_error_name = flag; 218 - return false; 219 - } 220 - char *arg = flag_shift_args(&argc, &argv); 203 + case FLAG_STR: { 204 + if (argc == 0) { 205 + c->flag_error = FLAG_ERROR_NO_VALUE; 206 + c->flag_error_name = flag; 207 + return false; 208 + } 209 + char *arg = flag_shift_args(&argc, &argv); 210 + c->flags[i].val.as_str = arg; 211 + } 212 + break; 221 213 222 - static_assert(sizeof(unsigned long long int) == sizeof(uint64_t), "The original author designed this for x86_64 machine with the compiler that expects unsigned long long int and uint64_t to be the same thing, so they could use strtoull() function to parse it. Please adjust this code for your case and maybe even send the patch to upstream to make it work on a wider range of environments."); 223 - char *endptr; 224 - // TODO: replace strtoull with a custom solution 225 - // That way we can get rid of the dependency on errno and static_assert 226 - unsigned long long int result = strtoull(arg, &endptr, 10); 214 + case FLAG_UINT64: { 215 + if (argc == 0) { 216 + c->flag_error = FLAG_ERROR_NO_VALUE; 217 + c->flag_error_name = flag; 218 + return false; 219 + } 220 + char *arg = flag_shift_args(&argc, &argv); 227 221 228 - if (*endptr != '\0') { 229 - c->flag_error = FLAG_ERROR_INVALID_NUMBER; 230 - c->flag_error_name = flag; 231 - return false; 232 - } 222 + static_assert(sizeof(unsigned long long int) == sizeof(uint64_t), "The original author designed this for x86_64 machine with the compiler that expects unsigned long long int and uint64_t to be the same thing, so they could use strtoull() function to parse it. Please adjust this code for your case and maybe even send the patch to upstream to make it work on a wider range of environments."); 223 + char *endptr; 224 + // TODO: replace strtoull with a custom solution 225 + // That way we can get rid of the dependency on errno and static_assert 226 + unsigned long long int result = strtoull(arg, &endptr, 10); 233 227 234 - if (result == ULLONG_MAX && errno == ERANGE) { 235 - c->flag_error = FLAG_ERROR_INTEGER_OVERFLOW; 236 - c->flag_error_name = flag; 237 - return false; 238 - } 228 + if (*endptr != '\0') { 229 + c->flag_error = FLAG_ERROR_INVALID_NUMBER; 230 + c->flag_error_name = flag; 231 + return false; 232 + } 239 233 240 - c->flags[i].val.as_uint64 = result; 241 - } 242 - break; 234 + if (result == ULLONG_MAX && errno == ERANGE) { 235 + c->flag_error = FLAG_ERROR_INTEGER_OVERFLOW; 236 + c->flag_error_name = flag; 237 + return false; 238 + } 243 239 244 - case FLAG_SIZE: { 245 - if (argc == 0) { 246 - c->flag_error = FLAG_ERROR_NO_VALUE; 247 - c->flag_error_name = flag; 248 - return false; 249 - } 250 - char *arg = flag_shift_args(&argc, &argv); 240 + c->flags[i].val.as_uint64 = result; 241 + } 242 + break; 251 243 252 - static_assert(sizeof(unsigned long long int) == sizeof(size_t), "The original author designed this for x86_64 machine with the compiler that expects unsigned long long int and size_t to be the same thing, so they could use strtoull() function to parse it. Please adjust this code for your case and maybe even send the patch to upstream to make it work on a wider range of environments."); 253 - char *endptr; 254 - // TODO: replace strtoull with a custom solution 255 - // That way we can get rid of the dependency on errno and static_assert 256 - unsigned long long int result = strtoull(arg, &endptr, 10); 244 + case FLAG_SIZE: { 245 + if (argc == 0) { 246 + c->flag_error = FLAG_ERROR_NO_VALUE; 247 + c->flag_error_name = flag; 248 + return false; 249 + } 250 + char *arg = flag_shift_args(&argc, &argv); 257 251 258 - // TODO: handle more multiplicative suffixes like in dd(1). From the dd(1) man page: 259 - // > N and BYTES may be followed by the following 260 - // > multiplicative suffixes: c =1, w =2, b =512, kB =1000, K 261 - // > =1024, MB =1000*1000, M =1024*1024, xM =M, GB 262 - // > =1000*1000*1000, G =1024*1024*1024, and so on for T, P, 263 - // > E, Z, Y. 264 - if (strcmp(endptr, "K") == 0) { 265 - result *= 1024; 266 - } else if (strcmp(endptr, "M") == 0) { 267 - result *= 1024*1024; 268 - } else if (strcmp(endptr, "G") == 0) { 269 - result *= 1024*1024*1024; 270 - } else if (strcmp(endptr, "") != 0) { 271 - c->flag_error = FLAG_ERROR_INVALID_SIZE_SUFFIX; 272 - c->flag_error_name = flag; 273 - // TODO: capability to report what exactly is the wrong suffix 274 - return false; 275 - } 252 + static_assert(sizeof(unsigned long long int) == sizeof(size_t), "The original author designed this for x86_64 machine with the compiler that expects unsigned long long int and size_t to be the same thing, so they could use strtoull() function to parse it. Please adjust this code for your case and maybe even send the patch to upstream to make it work on a wider range of environments."); 253 + char *endptr; 254 + // TODO: replace strtoull with a custom solution 255 + // That way we can get rid of the dependency on errno and static_assert 256 + unsigned long long int result = strtoull(arg, &endptr, 10); 276 257 277 - if (result == ULLONG_MAX && errno == ERANGE) { 278 - c->flag_error = FLAG_ERROR_INTEGER_OVERFLOW; 279 - c->flag_error_name = flag; 280 - return false; 281 - } 258 + // TODO: handle more multiplicative suffixes like in dd(1). From the dd(1) man page: 259 + // > N and BYTES may be followed by the following 260 + // > multiplicative suffixes: c =1, w =2, b =512, kB =1000, K 261 + // > =1024, MB =1000*1000, M =1024*1024, xM =M, GB 262 + // > =1000*1000*1000, G =1024*1024*1024, and so on for T, P, 263 + // > E, Z, Y. 264 + if (strcmp(endptr, "K") == 0) { 265 + result *= 1024; 266 + } else if (strcmp(endptr, "M") == 0) { 267 + result *= 1024*1024; 268 + } else if (strcmp(endptr, "G") == 0) { 269 + result *= 1024*1024*1024; 270 + } else if (strcmp(endptr, "") != 0) { 271 + c->flag_error = FLAG_ERROR_INVALID_SIZE_SUFFIX; 272 + c->flag_error_name = flag; 273 + // TODO: capability to report what exactly is the wrong suffix 274 + return false; 275 + } 282 276 283 - c->flags[i].val.as_size = result; 284 - } 285 - break; 277 + if (result == ULLONG_MAX && errno == ERANGE) { 278 + c->flag_error = FLAG_ERROR_INTEGER_OVERFLOW; 279 + c->flag_error_name = flag; 280 + return false; 281 + } 286 282 287 - case COUNT_FLAG_TYPES: 288 - default: { 289 - assert(0 && "unreachable"); 290 - exit(69); 291 - } 292 - } 283 + c->flags[i].val.as_size = result; 284 + } 285 + break; 293 286 294 - found = true; 295 - } 287 + case COUNT_FLAG_TYPES: 288 + default: { 289 + assert(0 && "unreachable"); 290 + exit(69); 291 + } 296 292 } 297 293 298 - if (!found) { 299 - c->flag_error = FLAG_ERROR_UNKNOWN; 300 - c->flag_error_name = flag; 301 - return false; 302 - } 294 + found = true; 295 + } 303 296 } 304 297 305 - c->rest_argc = argc; 306 - c->rest_argv = argv; 307 - return true; 298 + if (!found) { 299 + c->flag_error = FLAG_ERROR_UNKNOWN; 300 + c->flag_error_name = flag; 301 + return false; 302 + } 303 + } 304 + 305 + c->rest_argc = argc; 306 + c->rest_argv = argv; 307 + return true; 308 308 } 309 309 310 310 void flag_print_options(FILE *stream) 311 311 { 312 - Flag_Context *c = &flag_global_context; 313 - for (size_t i = 0; i < c->flags_count; ++i) { 314 - Flag *flag = &c->flags[i]; 312 + Flag_Context *c = &flag_global_context; 313 + for (size_t i = 0; i < c->flags_count; ++i) { 314 + Flag *flag = &c->flags[i]; 315 315 316 - fprintf(stream, " -%s\n", flag->name); 317 - fprintf(stream, " %s\n", flag->desc); 318 - static_assert(COUNT_FLAG_TYPES == 4, "Exhaustive flag type defaults printing"); 319 - switch (c->flags[i].type) { 320 - case FLAG_BOOL: 321 - if (flag->def.as_bool) { 322 - fprintf(stream, " default: %s\n", flag->def.as_bool ? "true" : "false"); 323 - } 324 - break; 325 - case FLAG_UINT64: 326 - fprintf(stream, " default: %" PRIu64 "\n", flag->def.as_uint64); 327 - break; 328 - case FLAG_SIZE: 329 - fprintf(stream, " default: %zu\n", flag->def.as_size); 330 - break; 331 - case FLAG_STR: 332 - if (flag->def.as_str) { 333 - fprintf(stream, " default: %s\n", flag->def.as_str); 334 - } 335 - break; 336 - default: 337 - assert(0 && "unreachable"); 338 - exit(69); 316 + fprintf(stream, " -%s\n", flag->name); 317 + fprintf(stream, " %s\n", flag->desc); 318 + static_assert(COUNT_FLAG_TYPES == 4, "Exhaustive flag type defaults printing"); 319 + switch (c->flags[i].type) { 320 + case FLAG_BOOL: 321 + if (flag->def.as_bool) { 322 + fprintf(stream, " Default: %s\n", flag->def.as_bool ? "true" : "false"); 339 323 } 324 + break; 325 + case FLAG_UINT64: 326 + fprintf(stream, " Default: %" PRIu64 "\n", flag->def.as_uint64); 327 + break; 328 + case FLAG_SIZE: 329 + fprintf(stream, " Default: %zu\n", flag->def.as_size); 330 + break; 331 + case FLAG_STR: 332 + if (flag->def.as_str) { 333 + fprintf(stream, " Default: %s\n", flag->def.as_str); 334 + } 335 + break; 336 + default: 337 + assert(0 && "unreachable"); 338 + exit(69); 340 339 } 340 + } 341 341 } 342 342 343 343 void flag_print_error(FILE *stream) 344 344 { 345 - Flag_Context *c = &flag_global_context; 346 - static_assert(COUNT_FLAG_ERRORS == 6, "Exhaustive flag error printing"); 347 - switch (c->flag_error) { 345 + Flag_Context *c = &flag_global_context; 346 + static_assert(COUNT_FLAG_ERRORS == 6, "Exhaustive flag error printing"); 347 + switch (c->flag_error) { 348 348 case FLAG_NO_ERROR: 349 - // NOTE: don't call flag_print_error() if flag_parse() didn't return false, okay? ._. 350 - fprintf( 351 - stream, 352 - "operation failed successfully! please tell the developer of this software that " 353 - "they don't know what they are doing!" 354 - ); 355 - break; 349 + // NOTE: don't call flag_print_error() if flag_parse() didn't return false, okay? ._. 350 + fprintf(stream, "Operation Failed Successfully! Please tell the developer of this software that they don't know what they are doing! :)"); 351 + break; 356 352 case FLAG_ERROR_UNKNOWN: 357 - fprintf(stream, "error: -%s: unknown flag\n", c->flag_error_name); 358 - break; 353 + fprintf(stream, "ERROR: -%s: unknown flag\n", c->flag_error_name); 354 + break; 359 355 case FLAG_ERROR_NO_VALUE: 360 - fprintf(stream, "error: -%s: no value provided\n", c->flag_error_name); 361 - break; 356 + fprintf(stream, "ERROR: -%s: no value provided\n", c->flag_error_name); 357 + break; 362 358 case FLAG_ERROR_INVALID_NUMBER: 363 - fprintf(stream, "error: -%s: invalid number\n", c->flag_error_name); 364 - break; 359 + fprintf(stream, "ERROR: -%s: invalid number\n", c->flag_error_name); 360 + break; 365 361 case FLAG_ERROR_INTEGER_OVERFLOW: 366 - fprintf(stream, "error: -%s: integer overflow\n", c->flag_error_name); 367 - break; 362 + fprintf(stream, "ERROR: -%s: integer overflow\n", c->flag_error_name); 363 + break; 368 364 case FLAG_ERROR_INVALID_SIZE_SUFFIX: 369 - fprintf(stream, "error: -%s: invalid size suffix\n", c->flag_error_name); 370 - break; 365 + fprintf(stream, "ERROR: -%s: invalid size suffix\n", c->flag_error_name); 366 + break; 371 367 case COUNT_FLAG_ERRORS: 372 368 default: 373 - assert(0 && "unreachable"); 374 - exit(69); 375 - } 369 + assert(0 && "unreachable"); 370 + exit(69); 371 + } 376 372 } 377 373 378 374 #endif