예제 #1
0
static int
_find_foreach_fn(void *data, size_t data_size, void *arg) {
	cfuopt_list_entry_t *opt = (cfuopt_list_entry_t *)data;
	_find_foreach_ds *ds = (_find_foreach_ds *)arg;
	size_t this_size = 0;
	cfulist_t *param_full_list = NULL;
	char *desc = NULL;
	_cfuopt_desc *desc_ds = CFU_OPT_ALLOC(_cfuopt_desc, 1);

	if (!data) return 0;

	param_full_list = cfulist_map(opt->param_names, _param_map_fn, opt);
	desc = cfulist_join(param_full_list, ", ");

	data_size = data_size;
	
	cfulist_destroy_with_free_fn(param_full_list, _simple_list_free_fn);

	desc_ds->desc = desc;
	desc_ds->entry = opt;
	cfulist_push(ds->desc_list, desc_ds);

	this_size = strlen(desc);
	if (this_size > ds->max_size) ds->max_size = this_size;

	return 0;
}
예제 #2
0
extern void
cfuopt_add_entry(cfuopt_t *context, const char *opt_str, void *arg_data,
	const char *description, const char *arg_description) {
	cfuopt_list_entry_t *entry = CFU_OPT_ALLOC(cfuopt_list_entry_t, 1);
	cfulist_t *param_list = NULL;
	cfuopt_arg_t arg_type = cfuopt_arg_invalid;
	struct _add_entry_struct entry_struct;
	int required = 0;

	parse_opt_str(opt_str, &param_list, &arg_type, &required);

	entry->arg_data = arg_data;
	entry->description = description;
	entry->arg_description = arg_description;
	entry->arg_type = arg_type;
	entry->required = required;
	entry->param_names = param_list;

	cfulist_push(context->option_list, (void *)entry);
	
	entry_struct.entry = entry;
	entry_struct.context = context;

	cfulist_foreach(param_list, _add_to_option_map, &entry_struct);
}
예제 #3
0
/*
  Parse a string like Perl's Getopt::Long takes, e.g.

  "verbose|v!",
  "file|f=s",
  "scale:f",
  "count:i"

  ! means boolean flag
  = means required
  : means optional
  s means arbitrary string (C string)
  f means float (double)
  i means integer (long)

*/
static void
parse_opt_str(const char *opt_str, cfulist_t **param_list, cfuopt_arg_t *type, int *is_required) {
	cfulist_t *params = cfulist_new();
	size_t num_names = 0;
	char **opt_names = cfustring_c_str_split(opt_str, &num_names, 0, "|", NULL);
	char *last_opt = NULL;
	char *pos = NULL;
	size_t opt_len = 0;
	cfuopt_arg_t arg_type = cfuopt_arg_invalid;
	int required = 0;
	size_t i = 0;

	if (num_names == 0) {
		cfulist_destroy(params);
		free(opt_names);
		return;
	}

	last_opt = opt_names[num_names - 1];
	opt_len = strlen(last_opt);
	if ( (pos = memchr((void *)last_opt, '=', opt_len)) ) {
		char *tmp = pos;
		required = 1;
		tmp++;
		if (*tmp) {
			CFUOPT_SET_TYPE(*tmp, arg_type);
			*pos = '\000';
		}
		else {
			arg_type = cfuopt_arg_invalid;
		}
	}
	else if ( (pos = memchr((void *)last_opt, ':', opt_len)) ) {
		char *tmp = pos;
		required = 0;
		tmp++;
		if (*tmp) {
			CFUOPT_SET_TYPE(*tmp, arg_type);
			*pos = '\000';
		}
		else {
			arg_type = cfuopt_arg_invalid;
		}
	}
	else if ( (pos = memchr((void *)last_opt, '!', opt_len)) ) {
		required = 0;
		arg_type = cfuopt_arg_bool;
		*pos = '\000';
	}

	for (i = 0; i < num_names; i++) {
		cfulist_push(params, opt_names[i]);
	}

	free(opt_names);
	*type = arg_type;
	*param_list = params;
	*is_required = required;
}
예제 #4
0
static int
_get_help_lines(void *data, size_t data_size, void *arg) {
	_cfuopt_desc *desc_ds = (_cfuopt_desc *)data;
	_help_lines_ds *ds = (_help_lines_ds *)arg;
	char *left_col = NULL;
	const char *desc = NULL;
	char *line = NULL;

	data_size = data_size;

	left_col = desc_ds->desc;
	
	if (!left_col) return 0;

	desc = desc_ds->entry->description;
	if (!desc) desc = "test desc";

	line = cfustring_sprintf_c_str(ds->fmt, left_col, desc);
	cfulist_push(ds->list, (void *)line);

	return 0;
	
}
예제 #5
0
int
cfulist_enqueue(cfulist_t *list, void *data) {
	return cfulist_push(list, data);
}
예제 #6
0
extern void
cfuopt_parse(cfuopt_t *context, int *argc, char ***argv, char **error) {
	int i = 0;
	char **args = *argv;
	int is_long_opt = 0;
	int is_short_opt = 0;
	int is_data = 0;
	int is_end_of_opt = 0;
	char *parsed_arg = NULL;
	const char *value = NULL;
	cfuopt_list_entry_t *entry = NULL;
	size_t extra_count = 0;

	error = error;

	if (!context) return;
	if (*argc < 1) return;

	context->progname = cfustring_dup_c_str(args[0]);
	
	if (*argc < 2) return;

	for (i = 1; i < *argc; i++) {
		char *cur_arg = args[i];
		entry = NULL;
		value = NULL;

		if (parsed_arg) free(parsed_arg);
		parsed_arg = NULL;
		
		check_arg(cur_arg, &is_long_opt, &is_short_opt, &is_data, &is_end_of_opt, &parsed_arg,
				  &value);
		if (is_long_opt || is_short_opt) {
			entry = (cfuopt_list_entry_t *)cfuhash_get(context->option_map, parsed_arg);
			if (parsed_arg) free(parsed_arg);
			parsed_arg = NULL;
		}
		else if (is_end_of_opt) {
			if (parsed_arg) free(parsed_arg);
			parsed_arg = NULL;
			i++;
			for (; i < *argc; i++) {
				cfulist_push(context->extra, args[i]);
			}
			break;
		}
		else if (is_data) {
			if (parsed_arg) free(parsed_arg);
			parsed_arg = NULL;
			cfulist_push(context->extra, args[i]);
			continue;
		}

		if (!entry) {
			/* FIXME: return error here if need be */
			continue;
		}

		switch (entry->arg_type) {
		  case cfuopt_arg_bool:
			  _set_entry_val(entry, "1");
			  break;
		  case cfuopt_arg_string:
		  case cfuopt_arg_int:
		  case cfuopt_arg_float:
			  if (value) {
				  if (entry->arg_data) {
					  _set_entry_val(entry, value);
				  }
			  } else {
				  i++;
				  if (i >= *argc) break; /* FIXME: set up error msg here */
				  check_arg(args[i], &is_long_opt, &is_short_opt, &is_data, &is_end_of_opt,
					  &parsed_arg, &value);
				  if (!is_data) {
					  i--;
					  break; /* FIXME: set up error msg here */
				  }
				  _set_entry_val(entry, parsed_arg);
				  free(parsed_arg);
				  parsed_arg = NULL;
			  }
			  break;
		  case cfuopt_arg_string_array:
			  break;
		  case cfuopt_arg_invalid:
			  /* FIXME: really should produce an error msg here */
			  break;
		  default:
			  break;
		}
		
	}

	extra_count = cfulist_num_entries(context->extra);
	*argc = extra_count + 1;
	{
		_update_extra_ds ds;
		size_t update_count = 0;
		ds.count = 1;
		ds.argv = args;
		update_count = cfulist_foreach(context->extra, _update_extra, (void *)&ds);
		assert(update_count + 1 == (unsigned)*argc);
	}
}