Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implements getopt for avr #9174

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
162 changes: 162 additions & 0 deletions cpu/atmega_common/getopt.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
/*
* Copyright (C) 2018 Viraj Sahai <vsahai@usc.edu, virajsahai32@gmail.com>
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
* details.
*/

/**
* @ingroup cpu_atmega_common
* @{
*
* @file getopt.c
* @brief Implementation of getopt lib.
*
*
* @author Viraj Sahai <vsahai@usc.edu, virajsahai32@gmail.com>
*
*/

#include <stdio.h>
#include <string.h>
#include "getopt.h"

char *optarg;
int optind = 1, opterr = 1, optopt;

int getopt(int argc, char *const argv[], const char *optstring)
{
char *loc_optstr = NULL;
char *loc_argvptr = NULL;
char opt;

optarg = NULL;

if (optind < 1 || optind >= argc) {
return -1;
}

if (*argv[optind] != '-' || !(argv[optind] + 1) || *(argv[optind] + 1) == '\0') {
return -1;
}

if (*(argv[optind] + 1) == '-') {
return -1;
}

opt = *(argv[optind] + 1);
loc_optstr = strchr(optstring, (int)opt);

if (loc_optstr == NULL) {
if (opterr && optstring[0] != ':') {
fprintf(stderr, "%s: unknown option -%c\n", argv[0], opt);
}
optopt = opt;
return '?';
}

if ((argv[optind] + 2) && *(argv[optind] + 2) != '\0') {
loc_argvptr = argv[optind] + 2;
}

++optind;
++loc_optstr;

if (*loc_optstr == ':') {
++loc_optstr;

if (*loc_optstr == ':') {
if (loc_argvptr != NULL) {
optarg = loc_argvptr;
}
}
else {
if (loc_argvptr != NULL) {
optarg = loc_argvptr;
}
else {
if (optind < argc && *(argv[optind]) != '-') {
optarg = argv[optind++];
}
else {
if (opterr && optstring[0] != ':') {
fprintf(stderr, "%s: missing argument for -%c\n", argv[0], opt);
}
if (optstring[0] == ':') {
return ':';
}
return '?';
}
}
}
}
return opt;
}

int getopt_r(int argc, char *const argv[], const char *optstring, opt_t *r)
{
char *loc_optstr = NULL;
char *loc_argvptr = NULL;
char opt;

if (r->optind < 1 || r->optind >= argc) {
return -1;
}

if (*argv[r->optind] != '-' || !(argv[r->optind] + 1) || *(argv[r->optind] + 1) == '\0') {
return -1;
}

if (*(argv[r->optind] + 1) == '-') {
return -1;
}

opt = *(argv[r->optind] + 1);
loc_optstr = strchr(optstring, (int)opt);

if (loc_optstr == NULL) {
if (r->opterr && optstring[0] != ':') {
fprintf(stderr, "%s: unknown option -%c\n", argv[0], opt);
}
r->optopt = opt;
return '?';
}

if ((argv[r->optind] + 2) && *(argv[r->optind] + 2) != '\0') {
loc_argvptr = argv[r->optind] + 2;
}

++r->optind;
++loc_optstr;

if (*loc_optstr == ':') {
++loc_optstr;

if (*loc_optstr == ':') {
if (loc_argvptr != NULL) {
r->optarg = loc_argvptr;
}
}
else {
if (loc_argvptr != NULL) {
r->optarg = loc_argvptr;
}
else {
if (r->optind < argc && *(argv[r->optind]) != '-') {
r->optarg = argv[r->optind++];
}
else {
if (r->opterr && optstring[0] != ':') {
fprintf(stderr, "%s: missing argument for -%c\n", argv[0], opt);
}
if (optstring[0] == ':') {
return ':';
}
return '?';
}
}
}
}
return opt;
}
93 changes: 93 additions & 0 deletions cpu/atmega_common/include/getopt.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Copyright (C) 2018 Viraj Sahai <vsahai@usc.edu, virajsahai32@gmail.com>
*
* This file is subject to the terms and conditions of the GNU Lesser General
* Public License v2.1. See the file LICENSE in the top level directory for more
* details.
*/

/**
* @ingroup cpu_atmega_common
* @{
*
* @file header
* @brief Implementation of getopt lib.
*
* This implements the getopt() and getopt_r() functionality.
* getopt_r() has a few caveats, make sure to use it correctly.
*
* @author Viraj Sahai <vsahai@usc.edu, virajsahai32@gmail.com>
*
*/

#ifndef GETOPT_H
#define GETOPT_H

#ifdef __cplusplus
extern "C" {
#endif

/**
* @brief Used to implement a MT safe re-entrant version of getopt().
*
* User can set error reporting on or off by setting opterr to 0 or 1.
* Care must be taken to ensure that optind is initialized to atleast 1.
* Use INIT_OPT_T or INIT_OPT_T_PTR for initialization.
* Arguments of the option will be returned in optarg.
*/
typedef struct {
char *optarg;
int optind;
int opterr;
int optopt;
} opt_t;

/**
* @brief Used to initialize opt_t* variable for use with getopt_r().
*
* Ensures that required variables pointed by opt_t* are initialized to prevent
* undefined behavior when using getopt_r().
*/
#define INIT_OPT_T_PTR &(opt_t){ NULL, 1, 1, -1 }

/**
* @brief Used to initialize opt_t variable for use with getopt_r().
*
* Ensures that required variables in opt_t are initialized to prevent
* undefined behavior when using getopt_r().
*/
#define INIT_OPT_T { NULL, 1, 1, -1 }

extern char *optarg;
extern int optind, opterr, optopt;

/**
* @brief Non re-entrant version of getopt.
*
* @param[in] argc The count of the number of arguments.
* @param[in] argv The array containing all the arguments.
* @param[in] optstring The string of expected options.
*
* @return ASCII value of the option if option was successfully found.
* '?' or ':' when unknown option is found or argument is missing.
*/
int getopt(int argc, char *const argv[], const char *optstring);

/**
* @brief Re-entrant version of getopt.
*
* @param[in] argc The count of the number of arguments.
* @param[in] argv The array containing all the arguments.
* @param[in] optstring The string of expected options.
* @param[out] r The per call struct for holding return args and other options.
*
* @return ASCII value of the option if option was successfully found.
* '?' or ':' when unknown option is found or argument is missing.
*/
int getopt_r(int argc, char *const argv[], const char *optstring, opt_t *r);

#ifdef __cplusplus
}
#endif

#endif /* GETOPT_H */