Blame tools/argsfilter/argsfilter.c

Packit 534379
// Copyright(c) 2018, Intel Corporation
Packit 534379
//
Packit 534379
// Redistribution  and  use  in source  and  binary  forms,  with  or  without
Packit 534379
// modification, are permitted provided that the following conditions are met:
Packit 534379
//
Packit 534379
// * Redistributions of  source code  must retain the  above copyright notice,
Packit 534379
//   this list of conditions and the following disclaimer.
Packit 534379
// * Redistributions in binary form must reproduce the above copyright notice,
Packit 534379
//   this list of conditions and the following disclaimer in the documentation
Packit 534379
//   and/or other materials provided with the distribution.
Packit 534379
// * Neither the name  of Intel Corporation  nor the names of its contributors
Packit 534379
//   may be used to  endorse or promote  products derived  from this  software
Packit 534379
//   without specific prior written permission.
Packit 534379
//
Packit 534379
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
Packit 534379
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,  BUT NOT LIMITED TO,  THE
Packit 534379
// IMPLIED WARRANTIES OF  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Packit 534379
// ARE DISCLAIMED.  IN NO EVENT  SHALL THE COPYRIGHT OWNER  OR CONTRIBUTORS BE
Packit 534379
// LIABLE  FOR  ANY  DIRECT,  INDIRECT,  INCIDENTAL,  SPECIAL,  EXEMPLARY,  OR
Packit 534379
// CONSEQUENTIAL  DAMAGES  (INCLUDING,  BUT  NOT LIMITED  TO,  PROCUREMENT  OF
Packit 534379
// SUBSTITUTE GOODS OR SERVICES;  LOSS OF USE,  DATA, OR PROFITS;  OR BUSINESS
Packit 534379
// INTERRUPTION)  HOWEVER CAUSED  AND ON ANY THEORY  OF LIABILITY,  WHETHER IN
Packit 534379
// CONTRACT,  STRICT LIABILITY,  OR TORT  (INCLUDING NEGLIGENCE  OR OTHERWISE)
Packit 534379
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  EVEN IF ADVISED OF THE
Packit 534379
// POSSIBILITY OF SUCH DAMAGE.
Packit 534379
#include "argsfilter.h"
Packit 534379
#include <getopt.h>
Packit 534379
#include <stdlib.h>
Packit 534379
#include <string.h>
Packit 534379
#ifdef _WIN32
Packit 534379
#define EX_OK 0
Packit 534379
#define EX_USAGE (-1)
Packit 534379
#define EX_SOFTWARE (-2)
Packit 534379
#else
Packit 534379
#include <sysexits.h>
Packit 534379
#endif
Packit 534379
Packit 534379
#define RETURN_ON_ERR(res, desc)                                               \
Packit 534379
	do {                                                                   \
Packit 534379
		if ((res) != FPGA_OK) {                                        \
Packit 534379
			optind = 1;                                            \
Packit 534379
			opterr = old_opterr;                                   \
Packit 534379
			fprintf(stderr, "Error %s: %s\n", (desc),              \
Packit 534379
				fpgaErrStr(res));                              \
Packit 534379
			return EX_SOFTWARE;                                    \
Packit 534379
		}                                                              \
Packit 534379
	} while (0)
Packit 534379
Packit 534379
int set_properties_from_args(fpga_properties filter, fpga_result *result,
Packit 534379
			     int *argc, char *argv[])
Packit 534379
{
Packit 534379
	// prefix the short options with '-' so that unrecognized options are
Packit 534379
	// ignored
Packit 534379
	const char *short_opts = "-:B:D:F:S:";
Packit 534379
	struct option longopts[] = {
Packit 534379
		{"bus", required_argument, NULL, 'B'},
Packit 534379
		{"device", required_argument, NULL, 'D'},
Packit 534379
		{"function", required_argument, NULL, 'F'},
Packit 534379
		{"socket-id", required_argument, NULL, 'S'},
Packit 534379
		{"segment", required_argument, NULL, 0xe},
Packit 534379
		{0, 0, 0, 0},
Packit 534379
	};
Packit 534379
	int supported_options = sizeof(longopts) / sizeof(longopts[0]) - 1;
Packit 534379
	int getopt_ret = -1;
Packit 534379
	int option_index = 0;
Packit 534379
	char *endptr = NULL;
Packit 534379
	int found_opts[] = {0, 0, 0, 0, 0};
Packit 534379
	int next_found = 0;
Packit 534379
	int old_opterr = opterr;
Packit 534379
	opterr = 0;
Packit 534379
	struct _args_filter_config {
Packit 534379
		int bus;
Packit 534379
		int device;
Packit 534379
		int function;
Packit 534379
		int socket_id;
Packit 534379
		int segment;
Packit 534379
	} args_filter_config = {
Packit 534379
		.bus = -1, .device = -1, .function = -1, .socket_id = -1,
Packit 534379
		.segment = -1 };
Packit 534379
Packit 534379
	while (-1
Packit 534379
	       != (getopt_ret = getopt_long(*argc, argv, short_opts, longopts,
Packit 534379
					    &option_index))) {
Packit 534379
		const char *tmp_optarg = optarg;
Packit 534379
Packit 534379
		if ((optarg) && ('=' == *tmp_optarg))
Packit 534379
			++tmp_optarg;
Packit 534379
Packit 534379
		switch (getopt_ret) {
Packit 534379
		case 'B': /* bus */
Packit 534379
			if (NULL == tmp_optarg)
Packit 534379
				break;
Packit 534379
			endptr = NULL;
Packit 534379
			args_filter_config.bus =
Packit 534379
				(int)strtoul(tmp_optarg, &endptr, 0);
Packit 534379
			if (endptr != tmp_optarg + strlen(tmp_optarg)) {
Packit 534379
				fprintf(stderr, "invalid bus: %s\n",
Packit 534379
					tmp_optarg);
Packit 534379
				return EX_USAGE;
Packit 534379
			}
Packit 534379
			found_opts[next_found++] = optind - 2;
Packit 534379
			break;
Packit 534379
Packit 534379
		case 'D': /* device */
Packit 534379
			if (NULL == tmp_optarg)
Packit 534379
				break;
Packit 534379
			endptr = NULL;
Packit 534379
			args_filter_config.device =
Packit 534379
				(int)strtoul(tmp_optarg, &endptr, 0);
Packit 534379
			if (endptr != tmp_optarg + strlen(tmp_optarg)) {
Packit 534379
				fprintf(stderr, "invalid device: %s\n",
Packit 534379
					tmp_optarg);
Packit 534379
				return EX_USAGE;
Packit 534379
			}
Packit 534379
			found_opts[next_found++] = optind - 2;
Packit 534379
			break;
Packit 534379
Packit 534379
		case 'F': /* function */
Packit 534379
			if (NULL == tmp_optarg)
Packit 534379
				break;
Packit 534379
			endptr = NULL;
Packit 534379
			args_filter_config.function =
Packit 534379
				(int)strtoul(tmp_optarg, &endptr, 0);
Packit 534379
			if (endptr != tmp_optarg + strlen(tmp_optarg)) {
Packit 534379
				fprintf(stderr, "invalid function: %s\n",
Packit 534379
					tmp_optarg);
Packit 534379
				return EX_USAGE;
Packit 534379
			}
Packit 534379
			found_opts[next_found++] = optind - 2;
Packit 534379
			break;
Packit 534379
Packit 534379
		case 'S': /* socket */
Packit 534379
			if (NULL == tmp_optarg)
Packit 534379
				break;
Packit 534379
			endptr = NULL;
Packit 534379
			args_filter_config.socket_id =
Packit 534379
				(int)strtoul(tmp_optarg, &endptr, 0);
Packit 534379
			if (endptr != tmp_optarg + strlen(tmp_optarg)) {
Packit 534379
				fprintf(stderr, "invalid socket: %s\n",
Packit 534379
					tmp_optarg);
Packit 534379
				return EX_USAGE;
Packit 534379
			}
Packit 534379
			found_opts[next_found++] = optind - 2;
Packit 534379
			break;
Packit 534379
		case 0xe: /* segment */
Packit 534379
			if (NULL == tmp_optarg)
Packit 534379
				break;
Packit 534379
			endptr = NULL;
Packit 534379
			args_filter_config.segment =
Packit 534379
				(int)strtoul(tmp_optarg, &endptr, 0);
Packit 534379
			if (endptr != tmp_optarg + strlen(tmp_optarg)) {
Packit 534379
				fprintf(stderr, "invalid segment: %s\n",
Packit 534379
					tmp_optarg);
Packit 534379
				return EX_USAGE;
Packit 534379
			}
Packit 534379
			found_opts[next_found++] = optind - 2;
Packit 534379
			break;
Packit 534379
		case ':': /* missing option argument */
Packit 534379
			fprintf(stderr, "Missing option argument\n");
Packit 534379
			return EX_USAGE;
Packit 534379
Packit 534379
		case '?':
Packit 534379
			break;
Packit 534379
		case 1:
Packit 534379
			break;
Packit 534379
		default: /* invalid option */
Packit 534379
			fprintf(stderr, "Invalid cmdline options\n");
Packit 534379
			return EX_USAGE;
Packit 534379
		}
Packit 534379
	}
Packit 534379
Packit 534379
	if (-1 != args_filter_config.bus) {
Packit 534379
		*result = fpgaPropertiesSetBus(filter, args_filter_config.bus);
Packit 534379
		RETURN_ON_ERR(*result, "setting bus");
Packit 534379
	}
Packit 534379
	if (-1 != args_filter_config.device) {
Packit 534379
		*result = fpgaPropertiesSetDevice(filter,
Packit 534379
						  args_filter_config.device);
Packit 534379
		RETURN_ON_ERR(*result, "setting device");
Packit 534379
	}
Packit 534379
Packit 534379
	if (-1 != args_filter_config.function) {
Packit 534379
		*result = fpgaPropertiesSetFunction(
Packit 534379
			filter, args_filter_config.function);
Packit 534379
		RETURN_ON_ERR(*result, "setting function");
Packit 534379
	}
Packit 534379
Packit 534379
	if (-1 != args_filter_config.socket_id) {
Packit 534379
		*result = fpgaPropertiesSetSocketID(
Packit 534379
			filter, args_filter_config.socket_id);
Packit 534379
		RETURN_ON_ERR(*result, "setting socket id");
Packit 534379
	}
Packit 534379
Packit 534379
	if (-1 != args_filter_config.segment) {
Packit 534379
		*result = fpgaPropertiesSetSegment(
Packit 534379
			filter, args_filter_config.segment);
Packit 534379
		RETURN_ON_ERR(*result, "setting segment");
Packit 534379
	}
Packit 534379
	// using the list of optind values
Packit 534379
	// shorten the argv vector starting with a decrease
Packit 534379
	// of 2 and incrementing that amount by two for each option found
Packit 534379
	int removed = 0;
Packit 534379
	int i, j;
Packit 534379
	for (i = 0; i < supported_options; ++i) {
Packit 534379
		if (found_opts[i]) {
Packit 534379
			for (j = found_opts[i] - removed; j < *argc - 2; j++) {
Packit 534379
				argv[j] = argv[j + 2];
Packit 534379
			}
Packit 534379
			removed += 2;
Packit 534379
		} else {
Packit 534379
			break;
Packit 534379
		}
Packit 534379
	}
Packit 534379
	*argc -= removed;
Packit 534379
	// restore getopt variables
Packit 534379
	// setting optind to zero will cause getopt to reinitialize for future
Packit 534379
	// calls within the program
Packit 534379
	optind = 0;
Packit 534379
	opterr = old_opterr;
Packit 534379
	return EX_OK;
Packit 534379
}