Wrapper for Clustal Omega.
[jabaws.git] / binaries / src / clustalo / src / squid / getopt.c
1 /*****************************************************************
2  * SQUID - a library of functions for biological sequence analysis
3  * Copyright (C) 1992-2002 Washington University School of Medicine
4  * 
5  *     This source code is freely distributed under the terms of the
6  *     GNU General Public License. See the files COPYRIGHT and LICENSE
7  *     for details.
8  *****************************************************************/
9
10 /* RCS $Id: getopt.c 217 2011-03-19 10:27:10Z andreas $ (Original squid RCS Id: getopt.c,v 1.7 2001/02/21 21:09:10 eddy Exp)
11  */
12
13 #include <stdio.h>
14 #include <string.h>
15 #include <stdlib.h>
16
17 #include "squid.h"
18
19 /* Function: Getopt()
20  * 
21  * Purpose:  Portable command line option parsing with abbreviated
22  *           option switches. Replaces UNIX getopt(). Using UNIX getopt()
23  *           hinders portability to non-UNIX platforms, and getopt()
24  *           is also limited to single letter options.
25  *
26  *           Getopt() implements a superset of UNIX getopt().
27  *           All of getopt()'s single-character switch behavior
28  *           is emulated, and "--" by itself terminates the options.
29  *           Additionally, Getopt() provides extended switches
30  *           like "--youroptionhere", and Getopt() type checks
31  *           arguments.  
32  * 
33  *           Extended options must start with "--", as in "--option1".
34  *           Normal options must start with "-", as in "-o".
35  *           Normal options may be concatenated, as in "-a -b" == "-ab".
36  *           
37  *           See bottom of this .c file after #fdef GETOPT_TESTDRIVER
38  *           for an example of calling Getopt().
39  *           
40  * Args:     argc  - from main(). number of elems in argv.
41  *           argv  - from main(). argv[0] is the name of the command.
42  *           opt   - array of opt_s structures, defining option switches
43  *           nopts - number of switches in opt
44  *           usage - a (possibly long) string to print if usage error.
45  *           ret_optind - RETURN: the index in argv[] of the next 
46  *                        valid command-line token.
47  *           ret_optname- RETURN: ptr to the name of option switch 
48  *                        seen, or NULL if no option was seen.
49  *           ret_optarg - RETURN: ptr to the optional argument, if any;
50  *                        NULL if option takes no argument.
51  *                        
52  * Return:   1 if a valid option was parsed.
53  *           0 if no option was found, and command-line parsing is complete.
54  *           Die()'s here if an error is detected.
55  */
56 int
57 Getopt(int argc, char **argv, struct opt_s *opt, int nopts, char *usage,
58        int *ret_optind, char **ret_optname, char **ret_optarg)
59 {
60   int i;
61   int arglen;
62   int nmatch;
63   static int optind   = 1;        /* init to 1 on first call  */
64   static char *optptr = NULL;     /* ptr to next valid switch */
65   int opti = 0;                   /* init only to silence gcc uninit warnings */
66
67   /* Check to see if we've run out of options.
68    * A '-' by itself is an argument (e.g. "read from stdin")
69    * not an option.
70    */
71   if (optind >= argc || argv[optind][0] != '-' || strcmp(argv[optind], "-") == 0)
72     { 
73       *ret_optind  = optind; 
74       *ret_optarg  = NULL; 
75       *ret_optname = NULL; 
76       return 0; 
77     }
78
79   /* Check to see if we're being told that this is the end
80    * of the options with the special "--" flag.
81    */
82   if (strcmp(argv[optind], "--") == 0)
83     { 
84       optind++;
85       *ret_optind  = optind; 
86       *ret_optname = NULL;
87       *ret_optarg  = NULL; 
88       return 0; 
89     }
90
91   /* We have a real option. Find which one it is.
92    * We handle single letter switches "-o" separately
93    * from full switches "--option", based on the "-" vs. "--"
94    * prefix -- single letter switches can be concatenated
95    * as long as they don't have arguments.
96    */
97                                 /* full option */
98   if (optptr == NULL && strncmp(argv[optind], "--", 2) == 0)
99     {
100       /* Use optptr to parse argument in options of form "--foo=666"
101        */
102       if ((optptr = strchr(argv[optind], '=')) != NULL)
103         { *optptr = '\0'; optptr++; }
104
105       arglen = strlen(argv[optind]);
106       nmatch = 0;
107       for (i = 0; i < nopts; i++)
108         if (opt[i].single == FALSE && 
109             strncmp(opt[i].name, argv[optind], arglen) == 0)
110           { 
111             nmatch++;
112             opti = i;
113             if (arglen == strlen(opt[i].name)) break; /* exact match, stop now */
114           }
115       if (nmatch > 1 && arglen != strlen(opt[i].name)) 
116         Die("Option \"%s\" is ambiguous; please be more specific.\n%s",
117             argv[optind], usage);
118       if (nmatch == 0)
119         Die("No such option \"%s\".\n%s", argv[optind], usage);
120
121       *ret_optname = opt[opti].name;
122
123       /* Set the argument, if there is one
124        */
125       if (opt[opti].argtype != sqdARG_NONE) 
126         {
127           if (optptr != NULL)
128             {                   /* --foo=666 style */
129               *ret_optarg = optptr;
130               optptr = NULL;
131               optind++;
132             }
133           else if (optind+1 >= argc)
134             Die("Option %s requires an argument\n%s", opt[opti].name, usage);
135           else                  /* "--foo 666" style */
136             {
137               *ret_optarg = argv[optind+1];
138               optind+=2;
139             }
140         }
141       else  /* sqdARG_NONE */
142         {
143           if (optptr != NULL) 
144             Die("Option %s does not take an argument\n%s", opt[opti].name, usage);
145           *ret_optarg = NULL;
146           optind++;
147         }
148     }
149   else                          /* else, a single letter option "-o" */
150     {
151                                 /* find the option */
152       if (optptr == NULL) 
153         optptr = argv[optind]+1;
154       for (opti = -1, i = 0; i < nopts; i++)
155         if (opt[i].single == TRUE && *optptr == opt[i].name[1])
156           { opti = i; break; }
157       if (opti == -1)
158         Die("No such option \"%c\".\n%s", *optptr, usage);
159       *ret_optname = opt[opti].name;
160
161                                 /* set the argument, if there is one */
162       if (opt[opti].argtype != sqdARG_NONE) 
163         {
164           if (*(optptr+1) != '\0')   /* attached argument */
165             {
166               *ret_optarg = optptr+1;
167               optind++;
168             }
169           else if (optind+1 < argc) /* unattached argument */
170             {
171               *ret_optarg = argv[optind+1];
172               optind+=2;              
173             }
174           else Die("Option %s requires an argument\n%s", opt[opti].name, usage);
175
176           optptr = NULL;        /* can't concatenate after an argument */
177         }
178       else  /* sqdARG_NONE */
179         {
180           *ret_optarg = NULL;
181           if (*(optptr+1) != '\0')   /* concatenation */
182             optptr++; 
183           else
184             {
185               optind++;                /* move to next field */
186               optptr = NULL;
187             }
188         }
189
190     }
191
192   /* Type check the argument, if there is one
193    */
194   if (opt[opti].argtype != sqdARG_NONE) 
195     {
196       if (opt[opti].argtype == sqdARG_INT && ! IsInt(*ret_optarg))
197         Die("Option %s requires an integer argument\n%s",
198             opt[opti].name, usage);
199       else if (opt[opti].argtype == sqdARG_FLOAT && ! IsReal(*ret_optarg))
200         Die("Option %s requires a numerical argument\n%s",
201             opt[opti].name, usage);
202       else if (opt[opti].argtype == sqdARG_CHAR && strlen(*ret_optarg) != 1)
203         Die("Option %s requires a single-character argument\n%s",
204             opt[opti].name, usage);
205       /* sqdARG_STRING is always ok, no type check necessary */
206     }
207
208   *ret_optind = optind;
209   return 1;
210 }
211
212
213
214 #ifdef GETOPT_TESTDRIVER 
215 /* cc -DGETOPT_TESTDRIVER -L ~/lib/squid.linux/ getopt.c -lsquid
216  */
217 struct opt_s OPTIONS[] = {
218   { "--test1", FALSE, sqdARG_INT    },
219   { "--test2", FALSE, sqdARG_FLOAT  },
220   { "--test3", FALSE, sqdARG_STRING },
221   { "--test4", FALSE, sqdARG_CHAR   },
222   { "-a",      TRUE,  sqdARG_NONE   },
223   { "-b",      TRUE,  sqdARG_INT    },
224 };
225 #define NOPTIONS (sizeof(OPTIONS) / sizeof(struct opt_s))
226     
227 int
228 main(int argc, char **argv)
229 {
230   int   optind;
231   char *optarg;
232   char *optname;
233
234   while (Getopt(argc, argv, OPTIONS, NOPTIONS, "Usage/help here",
235                 &optind, &optname, &optarg))
236     {
237       printf("Option:   index: %d name: %s argument: %s\n",
238              optind, optname, optarg);
239     }
240   while (optind < argc)
241     {
242       printf("Argument: index: %d name: %s\n", optind, argv[optind]);
243       optind++;
244     }
245
246
247 }
248
249
250 #endif /*GETOPT_TESTDRIVER*/