173 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			173 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2003, 2007-14 Matteo Frigo
 | |
|  * Copyright (c) 2003, 2007-14 Massachusetts Institute of Technology
 | |
|  *
 | |
|  * This program is free software; you can redistribute it and/or modify
 | |
|  * it under the terms of the GNU General Public License as published by
 | |
|  * the Free Software Foundation; either version 2 of the License, or
 | |
|  * (at your option) any later version.
 | |
|  *
 | |
|  * This program is distributed in the hope that it will be useful,
 | |
|  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
|  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
|  * GNU General Public License for more details.
 | |
|  *
 | |
|  * You should have received a copy of the GNU General Public License
 | |
|  * along with this program; if not, write to the Free Software
 | |
|  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 | |
|  *
 | |
|  */
 | |
| 
 | |
| #include <string.h>
 | |
| #include <stdio.h>
 | |
| 
 | |
| #include "config.h"
 | |
| #include "my-getopt.h"
 | |
| 
 | |
| int my_optind = 1;
 | |
| const char *my_optarg = 0;
 | |
| static const char *scan_pointer = 0;
 | |
| 
 | |
| void my_usage(const char *progname, const struct my_option *opt)
 | |
| {
 | |
|     int i;
 | |
|     size_t col = 0;
 | |
| 
 | |
|     fprintf(stdout, "Usage: %s", progname);
 | |
|     col += (strlen(progname) + 7);
 | |
|     for (i = 0; opt[i].long_name; i++) {
 | |
| 	size_t option_len;
 | |
| 
 | |
| 	option_len = strlen(opt[i].long_name);
 | |
| 	if (col >= 80 - (option_len + 16)) {
 | |
| 	    fputs("\n\t", stdout);
 | |
| 	    col = 8;
 | |
| 	}
 | |
| 	fprintf(stdout, " [--%s", opt[i].long_name);
 | |
| 	col += (option_len + 4);
 | |
| 	if (opt[i].short_name < 128) {
 | |
| 	    fprintf(stdout, " | -%c", opt[i].short_name);
 | |
| 	    col += 5;
 | |
| 	}
 | |
| 	switch (opt[i].argtype) {
 | |
| 	    case REQARG:
 | |
| 		 fputs(" arg]", stdout);
 | |
| 		 col += 5;
 | |
| 		 break;
 | |
| 	    case OPTARG:
 | |
| 		 fputs(" [arg]]", stdout);
 | |
| 		 col += 10;
 | |
| 		 break;
 | |
| 	    default:
 | |
| 		 fputs("]", stdout);
 | |
| 		 col++;
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     fputs ("\n", stdout);
 | |
| }
 | |
| 
 | |
| int my_getopt(int argc, char *argv[], const struct my_option *optarray)
 | |
| {
 | |
|      const char *p;
 | |
|      const struct my_option *l;
 | |
| 
 | |
|      if (scan_pointer && *scan_pointer) {
 | |
| 	  /* continue a previously scanned argv[] element */
 | |
| 	  p = scan_pointer;
 | |
| 	  goto short_option;
 | |
|      } else {
 | |
| 	  /* new argv[] element */
 | |
| 	  if (my_optind >= argc)
 | |
| 	       return -1; /* no more options */
 | |
| 
 | |
| 	  p = argv[my_optind];
 | |
|      
 | |
| 	  if (*p++ != '-')  
 | |
| 	       return (-1); /* not an option */
 | |
| 
 | |
| 	  if (!*p) 
 | |
| 	       return (-1); /* string is exactly '-' */
 | |
| 	       
 | |
| 	  ++my_optind;
 | |
|      }
 | |
| 
 | |
|      if (*p == '-') {
 | |
| 	  /* long option */
 | |
| 	  scan_pointer = 0;
 | |
| 	  my_optarg = 0;
 | |
| 
 | |
| 	  ++p;
 | |
| 	  
 | |
| 	  for (l = optarray; l->short_name; ++l) {
 | |
| 	       size_t len = strlen(l->long_name);
 | |
| 	       if (!strncmp(l->long_name, p, len) && 
 | |
| 		   (!p[len] || p[len] == '=')) {
 | |
| 		    switch (l->argtype) {
 | |
| 			case NOARG: 
 | |
| 			     goto ok;
 | |
| 			case OPTARG: 
 | |
| 			     if (p[len] == '=')
 | |
| 				  my_optarg = p + len + 1;
 | |
| 			     goto ok;
 | |
| 			case REQARG: 
 | |
| 			     if (p[len] == '=') {
 | |
| 				  my_optarg = p + len + 1;
 | |
| 				  goto ok;
 | |
| 			     }
 | |
| 			     if (my_optind >= argc) {
 | |
| 				  fprintf(stderr, 
 | |
| 					  "option --%s requires an argument\n",
 | |
| 					  l->long_name);
 | |
| 				  return '?';
 | |
| 			     }
 | |
| 			     my_optarg = argv[my_optind];
 | |
| 			     ++my_optind;
 | |
| 			     goto ok;
 | |
| 		    }
 | |
| 	       }
 | |
| 	  }
 | |
|      } else {
 | |
|      short_option:
 | |
| 	  scan_pointer = 0;
 | |
| 	  my_optarg = 0;
 | |
| 
 | |
| 	  for (l = optarray; l->short_name; ++l) {
 | |
| 	       if (l->short_name == (char)l->short_name &&
 | |
| 		   *p == l->short_name) {
 | |
| 		    ++p;
 | |
| 		    switch (l->argtype) {
 | |
| 			case NOARG: 
 | |
| 			     scan_pointer = p;
 | |
| 			     goto ok;
 | |
| 			case OPTARG: 
 | |
| 			     if (*p)
 | |
| 				  my_optarg = p;
 | |
| 			     goto ok;
 | |
| 			case REQARG: 
 | |
| 			     if (*p) {
 | |
| 				  my_optarg = p;
 | |
| 			     } else {
 | |
| 				  if (my_optind >= argc) {
 | |
| 				       fprintf(stderr, 
 | |
| 					  "option -%c requires an argument\n",
 | |
| 					  l->short_name);
 | |
| 				       return '?';
 | |
| 				  }
 | |
| 				  my_optarg = argv[my_optind];
 | |
| 				  ++my_optind;
 | |
| 			     }
 | |
| 			     goto ok;
 | |
| 		    }
 | |
| 	       }
 | |
| 	  }
 | |
|      }
 | |
| 
 | |
|      fprintf(stderr, "unrecognized option %s\n", argv[my_optind - 1]);
 | |
|      return '?';
 | |
| 
 | |
|  ok:
 | |
|      return l->short_name;
 | |
| }
 | |
| 
 | 
