#include #include #include #include #include #include #include // // . // . // warning: slices are not NULL-terminated, and should not be modified! // strdup them if you need to make modifications. typedef struct slice { char* ref; size_t len; } slice_t; typedef struct pair { slice_t key; slice_t value; } pair_t; pair_t* global_arg_table = NULL; size_t args_count = 0; void parse_arguments(int argc, char** argv) { if (argc <= 1) return; global_arg_table = calloc(argc - 1, sizeof(pair_t)); for (int i = 1; i < argc; i++) { char* current = argv[ i ]; char* eq_sign = strchr(current, '='); if (eq_sign == NULL) { printf( "argument error: " "moonpaste expects named arguments with values. example: 'foo=bar'\n" " in '%s'", current); exit(1); } // key size_t key_len = eq_sign - current; size_t key_start = 0; while (key_start < key_len && isspace(current[ key_start ])) { // trim start key_start++; key_len--; } while (key_len > 0 && isspace(current[ key_start + key_len - 1 ])) { // trim end key_len--; } if (key_len == 0) { printf( "argument error: empty key\n" " in '%s'\n", current); exit(1); } // value size_t value_start = eq_sign - current + 1; size_t value_len = strlen(current) - value_start; while (value_start < strlen(current) && isspace(current[ value_start ])) { // trim start value_start++; value_len--; } while (value_len > 0 && isspace(current[ value_start + value_len - 1 ])) { // trim end value_len--; } // store global_arg_table[ args_count ].key.ref = current + key_start; global_arg_table[ args_count ].key.len = key_len; global_arg_table[ args_count ].value.ref = current + value_start; global_arg_table[ args_count ].value.len = value_len; args_count++; } } // get a config option's value from argv. // if mandatory == true -> program errors char* get_config(char* key, bool mandatory) { size_t len = strlen(key); for (int i = 0; i < args_count; i++) { if (global_arg_table[ i ].key.len != len) continue; if (strncmp(key, global_arg_table[ i ].key.ref, len) != 0) continue; char* new_str = malloc(global_arg_table[ i ].value.len); memcpy(new_str, global_arg_table[ i ].value.ref, global_arg_table[ i ].value.len); return new_str; // free me! } if (!mandatory) return NULL; fprintf(stderr, "program expected argument %s but did not receive it.\n", key); // __builtin_unreachable(); return NULL; }