I’m sure you all know what CLI arguments are, if not then head to Wikipedia for a great article on them. Well, as far as programming goes. It’s very useful to have code which you can use multiple times, without having to edit (or slight edits), in order to use in another program.
I thought I would share my CLI arguments C code which I’m currently using in multiple programs. A few things to note however, that this code will most certainly change from time to time, as I optimize and make improvments to it. Another note, the code is currently for *nix CLI, however, it can easily be altered to work on Windows as well, as Windows CLI tends to use the “/key value” notion of passing arguments. You could possibly use #ifdef win32 macro to check if we’re parsing *nix or win32 style CLI arguments.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 | /** * CLI Argument Parser * * @author Gareth Stones <gareth@rezolabs.com> * @license GNU General Public License */ #include <stdio.h> #include <stdlib.h> #include <string.h> /** * Function prototype's */ void argumentShort (char *key, char *value); void argumentLong (char *key, char *value); char *argumentGetKey (char *key); char *argumentGetValue (char *key); /** * Send argv[i] && argv[i+1] off to there correct parser's */ int main (int argc, char *argv[]) { if (argc == 1) { fprintf(stderr, "usage: %s (arguments)\n", argv[0]); return -1; } int i; for (i = 1; i < argc; i++) { char *current = (char*) malloc(sizeof(char*) * strlen(argv[i])); snprintf(current, strlen(argv[i]), "%s", argv[i]); if (*(current) == '-' && *(current+1) == '-') argumentLong(argv[i], argv[i+1]); else if (*(current) == '-' && *(current+1) != '-') argumentShort(argv[i], argv[i+1]); free(current); } return 0; } /** * Parse short CLI argument's * * @accept -k * -k value * -k=value */ void argumentShort (char *key, char *value) { if (strlen(key) <= 1) { fprintf(stderr, "Invalid CLI argument length (short).\n"); exit(-1); } /** * Settings that do not require usage of value argument */ if (strncmp(key, "-e", 2) == 0 && strlen(key) == 2 && value == NULL) printf("%s argument with no value, setting to default\n", key); /** * Check if we're dealing with -k=value if value is NULL */ if (value == NULL) { if (strchr(key, '=') != NULL) { value = argumentGetValue(key); key = argumentGetKey(key); } else return; } if (strncmp(key, "-e", 2) == 0 && strlen(key) == 2) printf("%s %s\n", key, value); } /** * Parse long CLI argument's * * @accept --key * --key value * --key=value */ void argumentLong (char *key, char *value) { if (strlen(key) <= 2) { fprintf(stderr, "Invalid CLI argument length (long)\n"); exit(-1); } /** * Settings that do not require usage of value argument */ if (strncmp(key, "--example", 9) == 0 && strlen(key) == 9 && value == NULL) printf("%s with no value, setting to default\n", key); /** * Check if we're dealing with --key=value if value is NULL */ if (value == NULL) { if (strchr(key, '=') != NULL) { value = argumentGetValue(key); key = argumentGetKey(key); } else return; } if (strncmp(key, "--example", 9) == 0 && strlen(key) == 9) printf("%s %s\n", key, value); } /** * Extract key from -k=value or --key=value syntax */ char *argumentGetKey (char *key) { return strtok(key, "="); } /** * Extract value from -k=value or --key=value syntax */ char *argumentGetValue (char *key) { char *value; value = strtok(key, "="); value = strtok(NULL, "="); return value; } |
Example of possible usage,
1 2 3 | % ./program -k=value --key=value % ./program -k value % etc... |