rcx

miscellaneous C library
git clone git://git.rr3.xyz/rcx
Log | Files | Refs | README | LICENSE

opt.c (1688B)


      1 #include <assert.h>
      2 #include <string.h>
      3 
      4 #include "rcx.h"
      5 #include "opt.h"
      6 
      7 void
      8 opt_init(opt_ctx *opt, int *argc, char **argv) {
      9 	opt->arg_used = false;
     10 	opt->cluster = 0;
     11 	opt->argc = argc;
     12 	opt->o = &argv[1];
     13 	opt->a = &argv[1];
     14 }
     15 
     16 bool
     17 opt_parse(opt_ctx *opt) {
     18 	if (opt->arg_used) {
     19 		if (opt->attached) {
     20 			opt->cluster = 0;
     21 		} else {
     22 			opt->o++;
     23 			(*opt->argc)--;
     24 		}
     25 		opt->arg_used = false;
     26 	}
     27 
     28 	if (opt->cluster) {
     29 		if ((opt->s = *++opt->cluster))
     30 			goto found_opt;
     31 		opt->cluster = 0;
     32 	}
     33 
     34 	bool skip = false;
     35 	for (; *opt->o; opt->o++) {
     36 		if (skip || (*opt->o)[0] != '-' || (*opt->o)[1] == '\0') {
     37 			/* Got an argument */
     38 			*opt->a++ = *opt->o;
     39 			continue;
     40 		}
     41 		(*opt->argc)--;
     42 		if ((*opt->o)[1] == '-' && (*opt->o)[2] == '\0') {
     43 			/* Got "--", so everything else is an argument */
     44 			skip = true;
     45 			continue;
     46 		}
     47 		/* Got an option */
     48 		if ((*opt->o)[1] == '-') { /* Long */
     49 			opt->s = 0;
     50 			opt->l = &(*opt->o)[2];
     51 		} else { /* Short */
     52 			opt->cluster = &(*opt->o)[1];
     53 			opt->s = *opt->cluster;
     54 			opt->l = "";
     55 		}
     56 		opt->o++;
     57 		goto found_opt;
     58 	}
     59 
     60 	/* End of option parsing */
     61 	*opt->a = 0;
     62 	return false;
     63 
     64 found_opt:
     65 	/* Find argument for option */
     66 	opt->arg = 0;
     67 	if ((opt->arg = strchr(opt->l, '='))) { /* "--opt=ARG" */
     68 		*opt->arg++ = '\0'; /* Null-terminate opt->l */
     69 		opt->attached = true;
     70 	} else if (opt->s && opt->cluster[1] != '\0') { /* "-oARG" */
     71 		opt->arg = &opt->cluster[1];
     72 		opt->attached = true;
     73 	} else { /* "-o ARG" or "--opt ARG" or nothing */
     74 		opt->arg = *opt->o;
     75 		opt->attached = false;
     76 	}
     77 	opt->avail = !!opt->arg;
     78 
     79 	return true;
     80 }
     81 
     82 char *
     83 opt_arg(opt_ctx *opt) {
     84 	assert(opt->avail);
     85 	opt->arg_used = true;
     86 	return opt->arg;
     87 }