Home | History | Annotate | Download | only in re2c
      1 /*
      2  Author: Marcus Boerger <helly (at) users.sourceforge.net>
      3 */
      4 
      5 #include <stdio.h>
      6 #include <string.h>
      7 #include <assert.h>
      8 #include <stdlib.h>
      9 #include "mbo_getopt.h"
     10 #define OPTERRCOLON (1)
     11 #define OPTERRNF (2)
     12 #define OPTERRARG (3)
     13 
     14 static int mbo_opt_error(int argc, char * const *argv, int oint, int optchr, int err, int show_err)
     15 {
     16 	if (show_err)
     17 	{
     18 		fprintf(stderr, "Error in argument %d, char %d: ", oint, optchr + 1);
     19 
     20 		switch (err)
     21 		{
     22 
     23 			case OPTERRCOLON:
     24 			fprintf(stderr, ": in flags\n");
     25 			break;
     26 
     27 			case OPTERRNF:
     28 			fprintf(stderr, "option not found %c\n", argv[oint][optchr]);
     29 			break;
     30 
     31 			case OPTERRARG:
     32 			fprintf(stderr, "no argument for option %c\n", argv[oint][optchr]);
     33 			break;
     34 
     35 			default:
     36 			fprintf(stderr, "unknown\n");
     37 			break;
     38 		}
     39 	}
     40 
     41 	return ('?');
     42 }
     43 
     44 int mbo_getopt(int argc, char* const *argv, const mbo_opt_struct opts[], char **optarg, int *optind, int show_err)
     45 {
     46 	static int optchr = 0;
     47 	static int dash = 0; /* have already seen the - */
     48 	int arg_start = 2;
     49 
     50 	int opts_idx = -1;
     51 
     52 	if (*optind >= argc)
     53 	{
     54 		return (EOF);
     55 	}
     56 
     57 	if (!dash)
     58 	{
     59 		if ((argv[*optind][0] != '-'))
     60 		{
     61 			return (EOF);
     62 		}
     63 		else
     64 		{
     65 			if (!argv[*optind][1])
     66 			{
     67 				/*
     68 				* use to specify stdin. Need to let pgm process this and
     69 				* the following args
     70 				*/
     71 				return (EOF);
     72 			}
     73 		}
     74 	}
     75 
     76 	if ((argv[*optind][0] == '-') && (argv[*optind][1] == '-'))
     77 	{
     78 		/* '--' indicates end of args if not followed by a known long option name */
     79 
     80 		while (1)
     81 		{
     82 			opts_idx++;
     83 
     84 			if (opts[opts_idx].opt_char == '-')
     85 			{
     86 				(*optind)++;
     87 				return (EOF);
     88 			}
     89 			else if (opts[opts_idx].opt_name && !strcmp(&argv[*optind][2], opts[opts_idx].opt_name))
     90 			{
     91 				break;
     92 			}
     93 		}
     94 
     95 		optchr = 0;
     96 		dash = 1;
     97 		arg_start = 2 + strlen(opts[opts_idx].opt_name);
     98 	}
     99 
    100 	if (!dash)
    101 	{
    102 		dash = 1;
    103 		optchr = 1;
    104 	}
    105 
    106 	/* Check if the guy tries to do a -: kind of flag */
    107 	if (argv[*optind][optchr] == ':')
    108 	{
    109 		dash = 0;
    110 		(*optind)++;
    111 		return (mbo_opt_error(argc, argv, *optind - 1, optchr, OPTERRCOLON, show_err));
    112 	}
    113 
    114 	if (opts_idx < 0)
    115 	{
    116 		while (1)
    117 		{
    118 			opts_idx++;
    119 
    120 			if (opts[opts_idx].opt_char == '-')
    121 			{
    122 				int errind = *optind;
    123 				int errchr = optchr;
    124 
    125 				if (!argv[*optind][optchr + 1])
    126 				{
    127 					dash = 0;
    128 					(*optind)++;
    129 				}
    130 				else
    131 				{
    132 					optchr++;
    133 				}
    134 
    135 				return (mbo_opt_error(argc, argv, errind, errchr, OPTERRNF, show_err));
    136 			}
    137 			else if (argv[*optind][optchr] == opts[opts_idx].opt_char)
    138 			{
    139 				break;
    140 			}
    141 		}
    142 	}
    143 
    144 	if (opts[opts_idx].need_param)
    145 	{
    146 		/* Check for cases where the value of the argument
    147 		is in the form -<arg> <val> or in the form -<arg><val> */
    148 		dash = 0;
    149 
    150 		if (!argv[*optind][arg_start])
    151 		{
    152 			(*optind)++;
    153 
    154 			if (*optind == argc)
    155 			{
    156 				return (mbo_opt_error(argc, argv, *optind - 1, optchr, OPTERRARG, show_err));
    157 			}
    158 
    159 			*optarg = argv[(*optind)++];
    160 		}
    161 		else
    162 		{
    163 			*optarg = &argv[*optind][arg_start];
    164 			(*optind)++;
    165 		}
    166 
    167 		return opts[opts_idx].opt_char;
    168 	}
    169 	else
    170 	{
    171 		if (arg_start == 2)
    172 		{
    173 			if (!argv[*optind][optchr + 1])
    174 			{
    175 				dash = 0;
    176 				(*optind)++;
    177 			}
    178 			else
    179 			{
    180 				optchr++;
    181 			}
    182 		}
    183 		else
    184 		{
    185 			(*optind)++;
    186 		}
    187 
    188 		return opts[opts_idx].opt_char;
    189 	}
    190 
    191 	assert(0);
    192 	return (0);	/* never reached */
    193 }
    194 
    195