00001 // XGetopt.cpp Version 1.1 00002 // 00003 // Author: Hans Dietrich 00004 // hdietrich2@hotmail.com 00005 // 00006 // Modified: David Smith 00007 // dave.s@earthcorp.com 00008 // Moved two char declarations from body of function so 00009 // that it can compile as a C function. 00010 // Thanks so much Hans 00011 // 00012 // This software is released into the public domain. 00013 // You are free to use it in any way you like. 00014 // 00015 // This software is provided "as is" with no expressed 00016 // or implied warranty. I accept no liability for any 00017 // damage or loss of business that this software may cause. 00018 // 00020 00021 #include <stdio.h> 00022 #include <string.h> 00023 #include "XGetopt.h" 00024 00026 // 00027 // X G e t o p t . c p p 00028 // 00029 // 00030 // NAME 00031 // getopt -- parse command line options 00032 // 00033 // SYNOPSIS 00034 // int getopt(int argc, char *argv[], char *optstring) 00035 // 00036 // extern char *optarg; 00037 // extern int optind; 00038 // 00039 // DESCRIPTION 00040 // The getopt() function parses the command line arguments. Its 00041 // arguments argc and argv are the argument count and array as 00042 // passed into the application on program invocation. In the case 00043 // of Visual C++ programs, argc and argv are available via the 00044 // variables __argc and __argv (double underscores), respectively. 00045 // getopt returns the next option letter in argv that matches a 00046 // letter in optstring. 00047 // 00048 // optstring is a string of recognized option letters; if a letter 00049 // is followed by a colon, the option is expected to have an argument 00050 // that may or may not be separated from it by white space. optarg 00051 // is set to point to the start of the option argument on return from 00052 // getopt. 00053 // 00054 // Option letters may be combined, e.g., "-ab" is equivalent to 00055 // "-a -b". Option letters are case sensitive. 00056 // 00057 // getopt places in the external variable optind the argv index 00058 // of the next argument to be processed. optind is initialized 00059 // to 0 before the first call to getopt. 00060 // 00061 // When all options have been processed (i.e., up to the first 00062 // non-option argument), getopt returns EOF, optarg will point 00063 // to the argument, and optind will be set to the argv index of 00064 // the argument. If there are no non-option arguments, optarg 00065 // will be set to NULL. 00066 // 00067 // The special option "--" may be used to delimit the end of the 00068 // options; EOF will be returned, and "--" (and everything after it) 00069 // will be skipped. 00070 // 00071 // RETURN VALUE 00072 // For option letters contained in the string optstring, getopt 00073 // will return the option letter. getopt returns a question mark (?) 00074 // when it encounters an option letter not included in optstring. 00075 // EOF is returned when processing is finished. 00076 // 00077 // BUGS 00078 // 1) Long options are not supported. 00079 // 2) The GNU double-colon extension is not supported. 00080 // 3) The environment variable POSIXLY_CORRECT is not supported. 00081 // 4) The + syntax is not supported. 00082 // 5) The automatic permutation of arguments is not supported. 00083 // 6) This implementation of getopt() returns EOF if an error is 00084 // encountered, instead of -1 as the latest standard requires. 00085 // 00086 // EXAMPLE 00087 // BOOL CMyApp::ProcessCommandLine(int argc, char *argv[]) 00088 // { 00089 // int c; 00090 // 00091 // while ((c = getopt(argc, argv, "aBn:")) != EOF) 00092 // { 00093 // switch (c) 00094 // { 00095 // case 'a': 00096 // TRACE(_T("option a\n")); 00097 // // 00098 // // set some flag here 00099 // // 00100 // break; 00101 // 00102 // case 'B': 00103 // TRACE( _T("option B\n")); 00104 // // 00105 // // set some other flag here 00106 // // 00107 // break; 00108 // 00109 // case 'n': 00110 // TRACE(_T("option n: value=%d\n"), atoi(optarg)); 00111 // // 00112 // // do something with value here 00113 // // 00114 // break; 00115 // 00116 // case '?': 00117 // TRACE(_T("ERROR: illegal option %s\n"), argv[optind-1]); 00118 // return FALSE; 00119 // break; 00120 // 00121 // default: 00122 // TRACE(_T("WARNING: no handler for option %c\n"), c); 00123 // return FALSE; 00124 // break; 00125 // } 00126 // } 00127 // // 00128 // // check for non-option args here 00129 // // 00130 // return TRUE; 00131 // } 00132 // 00134 00135 char *optarg; // global argument pointer 00136 int optind = 0; // global argv index 00137 00138 int getopt(int argc, char *argv[], char *optstring) 00139 { 00140 static char *next = NULL; 00141 char c, *cp; 00142 if (optind == 0) 00143 next = NULL; 00144 00145 optarg = NULL; 00146 00147 if (next == NULL || *next == '\0') 00148 { 00149 if (optind == 0) 00150 optind++; 00151 00152 if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0') 00153 { 00154 optarg = NULL; 00155 if (optind < argc) 00156 optarg = argv[optind]; 00157 return EOF; 00158 } 00159 00160 if (strcmp(argv[optind], "--") == 0) 00161 { 00162 optind++; 00163 optarg = NULL; 00164 if (optind < argc) 00165 optarg = argv[optind]; 00166 return EOF; 00167 } 00168 00169 next = argv[optind]+1; 00170 optind++; 00171 } 00172 00173 c = *next++; 00174 cp = strchr(optstring, c); 00175 00176 if (cp == NULL || c == ':') 00177 return '?'; 00178 00179 cp++; 00180 if (*cp == ':') 00181 { 00182 if (*next != '\0') 00183 { 00184 optarg = next; 00185 next = NULL; 00186 } 00187 else if (optind < argc) 00188 { 00189 optarg = argv[optind]; 00190 optind++; 00191 } 00192 else 00193 { 00194 return '?'; 00195 } 00196 } 00197 00198 return c; 00199 }