reZo Labs

CLI Arguments

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...
Posted in Desktop Programming | Leave a comment

Leave a Reply


6 * = forty eight