├── .gitignore ├── LICENSE ├── README.md ├── appveyor.yml ├── article.md ├── getopt.c ├── getopt.h ├── getopt.sln └── getopt.vcxproj /.gitignore: -------------------------------------------------------------------------------- 1 | Win32/ 2 | x64/ 3 | .vs/ 4 | *.user -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | getopt port for Visual C++ 2 | ========================== 3 | 4 | [![Build status](https://ci.appveyor.com/api/projects/status/reb7dt6x7jdn1700/branch/master?svg=true)](https://ci.appveyor.com/project/qmfrederik/getopt/branch/master) 5 | 6 | This repository contains a port of getopt which can be used with Visual C++. It is intended to be used with vcpkg. 7 | 8 | The Visual C++ port was originally done by Ludvik Jerabek, and described in the [Full getopt Port for Unicode and Multibyte Microsoft Visual C, C++, or MFC Projects](https://www.codeproject.com/Articles/157001/Full-getopt-Port-for-Unicode-and-Multibyte-Microso/) 9 | article. This repository contains a copy of that code and the article. -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | build_script: 2 | - msbuild getopt.sln /p:Configuration=Debug /p:Platform=Win32 /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" 3 | - msbuild getopt.sln /p:Configuration=Debug /p:Platform=x64 /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" 4 | - msbuild getopt.sln /p:Configuration=Release /p:Platform=Win32 /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" 5 | - msbuild getopt.sln /p:Configuration=Release /p:Platform=x64 /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" 6 | -------------------------------------------------------------------------------- /article.md: -------------------------------------------------------------------------------- 1 | Full getopt Port for Unicode and Multibyte Microsoft Visual C, C++, or MFC Projects 2 | =================================================================================== 3 | 4 | Ludvik Jerabek, 15 Oct 2012 5 | 6 | Originally published at https://www.codeproject.com/Articles/157001/Full-getopt-Port-for-Unicode-and-Multibyte-Microso/ 7 | 8 | 9 | Introduction 10 | ------------ 11 | 12 | This software was written after hours of searching for a robust Microsoft C and C++ implementation of getopt, 13 | which led to devoid results. 14 | 15 | This software is a modification of the Free Software Foundation, Inc. getopt library for parsing command line arguments 16 | and its purpose is to provide a Microsoft Visual C friendly derivative. The source code provides functionality for both 17 | Unicode and Multibyte builds and supports `getopt`, `getopt_long`, and `getopt_long_only`. Additionally the code supports the 18 | `POSIXLY_CORRECT` environment flag. The library uses the `_UNICODE` preprocessor directive when defining the `getopt`, `getopt_long`, 19 | and `getopt_long_only` functions. These functions are mapped back to `getopt_a`\`getopt_w`, `getopt_long_a`\`getopt_long_w`, and 20 | `getopt_long_only_a`\`getopt_long_only_w` respectively. This improvement was made to allow a single DLL to be used in both 21 | multibyte and Unicode projects. 22 | 23 | The original GNU code used several header and implementation files containing numerous preprocessor directives specific 24 | to Linux environments which have been removed. After removing unneeded dependencies, it was condensed into a single 25 | header and implementation file which can be compiled into a DLL, LIB, or directly included into any Visual C, C++, or MFC 26 | project. The getopt library can be used by proprietary software, however; certain measures need to be taken to ensure 27 | proprietary code adheres to the Lesser GNU Public License for non-derivative works. Please refer to the licensing section 28 | of this article for more details on how this software is licensed. 29 | 30 | For the sake of brevity, this article doesn't discuss how to use the `getopt` functions. Anyone new to using the `getopt` 31 | functions should refer to the GNU tutorial for using getopt. 32 | 33 | Licensing 34 | --------- 35 | 36 | Since `getopt` is licensed under LGPL, it is free to use in proprietary software under some restrictions. 37 | When using this library as part of a proprietary software solution, it is important that the library is used as 38 | a dynamically linked library (DLL) and is not statically linked or directly compiled into proprietary source code. 39 | Static linkage requires that your software be released GPL. Therefore, by keeping the library separately referenced 40 | via Dynamic Link Library (DLL), allows the DLL to be modified and updated without changing the proprietary software 41 | which utilizes the library; under this condition proprietary software is said to "use" the library. Thus, it is not 42 | considered to be a derivative work and can be distributed freely under any license. 43 | 44 | Preprocessor Definitions 45 | ------------------------ 46 | 47 | Compiling `getopt` as a Dynamic Link Library (DLL) requires the preprocessor definition of `EXPORTS_GETOPT`. 48 | The definition of `EXPORTS_GETOPT` sets the internal preprocessor definition `_GETOPT_API` to the value `__declspec(dllexport)`. 49 | Compiling getopt as a Static Library (LIB) or directly including the source and header file within a project requires the 50 | preprocessor definition of `STATIC_GETOPT`. The definition of `STATIC_GETOPT` clears the value of the internal preprocessor definition 51 | of `_GETOPT_API`. Compiling software to use _getopt.dll_ requires that no library specific preprocessor definitions be used. 52 | When no library specific preprocessor definitions are used the value assigned to the internal preprocessor definition `_GETOPT_API` is `__declspec(dllimport)`. 53 | 54 | The code segment below demonstrates the logic outlined above: 55 | 56 | ```c 57 | #if defined(EXPORTS_GETOPT) && defined(STATIC_GETOPT) 58 | #error "The preprocessor definitions of EXPORTS_GETOPT 59 | and STATIC_GETOPT can only be used individually" 60 | #elif defined(STATIC_GETOPT) 61 | #pragma message("Warning static builds of getopt violate the Lesser GNU Public License") 62 | #define _GETOPT_API 63 | #elif defined(EXPORTS_GETOPT) 64 | #pragma message("Exporting getopt library") 65 | #define _GETOPT_API __declspec(dllexport) 66 | #else 67 | #pragma message("Importing getopt library") 68 | #define _GETOPT_API __declspec(dllimport) 69 | #endif 70 | ``` 71 | 72 | The following code segment located in _getopt.h_ is responsible for mapping the correct version of the `getopt`, `getopt_long`, 73 | and `getopt_long_only` functions. The `getopt` functions appended with `_a` to denote ANSI characters using the char type and 74 | Unicode functions are appended with `_w` to denote wide characters using the `wchar_t` type. 75 | 76 | ```c 77 | #ifdef _UNICODE 78 | #define getopt getopt_w 79 | #define getopt_long getopt_long_w 80 | #define getopt_long_only getopt_long_only_w 81 | #define option option_w 82 | #define optarg optarg_w 83 | #else 84 | #define getopt getopt_a 85 | #define getopt_long getopt_long_a 86 | #define getopt_long_only getopt_long_only_a 87 | #define option option_a 88 | #define optarg optarg_a 89 | #endif 90 | ``` 91 | 92 | Using the Code 93 | --------------- 94 | 95 | The code is used identical to GNU `getopt`. 96 | 97 | ```c 98 | #include 99 | #include 100 | #include "tchar.h" 101 | #include "getopt.h" 102 | 103 | int _tmain(int argc, TCHAR** argv) 104 | { 105 | static int verbose_flag; 106 | int c; 107 | 108 | while (1) 109 | { 110 | static struct option long_options[] = 111 | { 112 | {_T("verbose"), ARG_NONE, &verbose_flag, 1}, 113 | {_T("brief"), ARG_NONE, &verbose_flag, 0}, 114 | {_T("add"), ARG_NONE, 0, _T('a')}, 115 | {_T("append"), ARG_NONE, 0, _T('b')}, 116 | {_T("delete"), ARG_REQ, 0, _T('d')}, 117 | {_T("create"), ARG_REQ, 0, _T('c')}, 118 | {_T("file"), ARG_REQ, 0 , _T('f')}, 119 | { ARG_NULL , ARG_NULL , ARG_NULL , ARG_NULL } 120 | }; 121 | 122 | int option_index = 0; 123 | c = getopt_long(argc, argv, _T("abc:d:f:"), long_options, &option_index); 124 | 125 | // Check for end of operation or error 126 | if (c == -1) 127 | break; 128 | 129 | // Handle options 130 | switch (c) 131 | { 132 | case 0: 133 | /* If this option set a flag, do nothing else now. */ 134 | if (long_options[option_index].flag != 0) 135 | break; 136 | _tprintf (_T("option %s"), long_options[option_index].name); 137 | if (optarg) 138 | _tprintf (_T(" with arg %s"), optarg); 139 | _tprintf (_T("\n")); 140 | break; 141 | 142 | case _T('a'): 143 | _tprintf(_T("option -a\n")); 144 | break; 145 | 146 | case _T('b'): 147 | _tprintf(_T("option -b\n")); 148 | break; 149 | 150 | case _T('c'): 151 | _tprintf (_T("option -c with value `%s'\n"), optarg); 152 | break; 153 | 154 | case _T('d'): 155 | _tprintf (_T("option -d with value `%s'\n"), optarg); 156 | break; 157 | 158 | case _T('f'): 159 | _tprintf (_T("option -f with value `%s'\n"), optarg); 160 | break; 161 | 162 | case '?': 163 | /* getopt_long already printed an error message. */ 164 | break; 165 | 166 | default: 167 | abort(); 168 | } 169 | } 170 | 171 | if (verbose_flag) 172 | _tprintf (_T("verbose flag is set\n")); 173 | 174 | 175 | if (optind < argc) 176 | { 177 | _tprintf (_T("non-option ARGV-elements: ")); 178 | while (optind < argc) _tprintf (_T("%s "), argv[optind++]); 179 | _tprintf (_T("\n")); 180 | } 181 | return 0; 182 | } 183 | ``` 184 | 185 | Using this Code with C++ Precompiled Headers 186 | -------------------------------------------- 187 | 188 | When using this code statically within a C++ project with precompiled headers, it is necessary to rename `getopt.c` 189 | to `getopt.cpp` in order to circumvent the following compiler error: 190 | 191 | ``` 192 | "C1853 - Precompiled header file is from a previous version of the compiler, 193 | or the precompiled header is C++ and you are using it from C (or vice versa)." 194 | ``` 195 | 196 | Additionally precompiled header file must be added as the first include of the `getopt.c` or `getopt.cpp` file. 197 | For example, if you are using _stdafx.h_ as the precompiled header, the following would be expected: 198 | 199 | ``` 200 | // File comments removed 201 | #include "stdafx.h" 202 | #define _CRT_SECURE_NO_WARNINGS 203 | #include 204 | #include 205 | #include "getopt.h" 206 | ``` 207 | 208 | History 209 | ------- 210 | 211 | - 02/03/2011 - Initial release 212 | - 02/20/2011 - Fixed L4 compiler warnings 213 | - 07/05/2011 - Added no_argument, required_argument, optional_argument def 214 | - 08/05/2011 - Fixed non-argument runtime bug which caused runtime exception 215 | - 08/09/2011 - Added code to export functions for DLL and LIB 216 | - 02/15/2012 - Fixed _GETOPT_THROW definition missing in implementation file 217 | - 08/03/2012 - Created separate functions for char and wchar_t characters so single DLL can do both Unicode and ANSI 218 | - 10/15/2012 - Modified to match latest GNU features 219 | - 06/19/2015 - Fixed maximum option limitation caused by option_a (255) and option_w (65535) structure val variable 220 | 221 | License 222 | ------- 223 | 224 | This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3) -------------------------------------------------------------------------------- /getopt.c: -------------------------------------------------------------------------------- 1 | /* Getopt for Microsoft C 2 | This code is a modification of the Free Software Foundation, Inc. 3 | Getopt library for parsing command line argument the purpose was 4 | to provide a Microsoft Visual C friendly derivative. This code 5 | provides functionality for both Unicode and Multibyte builds. 6 | 7 | Date: 02/03/2011 - Ludvik Jerabek - Initial Release 8 | Version: 1.0 9 | Comment: Supports getopt, getopt_long, and getopt_long_only 10 | and POSIXLY_CORRECT environment flag 11 | License: LGPL 12 | 13 | Revisions: 14 | 15 | 02/03/2011 - Ludvik Jerabek - Initial Release 16 | 02/20/2011 - Ludvik Jerabek - Fixed compiler warnings at Level 4 17 | 07/05/2011 - Ludvik Jerabek - Added no_argument, required_argument, optional_argument defs 18 | 08/03/2011 - Ludvik Jerabek - Fixed non-argument runtime bug which caused runtime exception 19 | 08/09/2011 - Ludvik Jerabek - Added code to export functions for DLL and LIB 20 | 02/15/2012 - Ludvik Jerabek - Fixed _GETOPT_THROW definition missing in implementation file 21 | 08/01/2012 - Ludvik Jerabek - Created separate functions for char and wchar_t characters so single dll can do both unicode and ansi 22 | 10/15/2012 - Ludvik Jerabek - Modified to match latest GNU features 23 | 06/19/2015 - Ludvik Jerabek - Fixed maximum option limitation caused by option_a (255) and option_w (65535) structure val variable 24 | 25 | **DISCLAIMER** 26 | THIS MATERIAL IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 27 | EITHER EXPRESS OR IMPLIED, INCLUDING, BUT Not LIMITED TO, THE 28 | IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 29 | PURPOSE, OR NON-INFRINGEMENT. SOME JURISDICTIONS DO NOT ALLOW THE 30 | EXCLUSION OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSION MAY NOT 31 | APPLY TO YOU. IN NO EVENT WILL I BE LIABLE TO ANY PARTY FOR ANY 32 | DIRECT, INDIRECT, SPECIAL OR OTHER CONSEQUENTIAL DAMAGES FOR ANY 33 | USE OF THIS MATERIAL INCLUDING, WITHOUT LIMITATION, ANY LOST 34 | PROFITS, BUSINESS INTERRUPTION, LOSS OF PROGRAMS OR OTHER DATA ON 35 | YOUR INFORMATION HANDLING SYSTEM OR OTHERWISE, EVEN If WE ARE 36 | EXPRESSLY ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 37 | */ 38 | #define _CRT_SECURE_NO_WARNINGS 39 | #include 40 | #include 41 | #include 42 | #include "getopt.h" 43 | 44 | #ifdef __cplusplus 45 | #define _GETOPT_THROW throw() 46 | #else 47 | #define _GETOPT_THROW 48 | #endif 49 | 50 | int optind = 1; 51 | int opterr = 1; 52 | int optopt = '?'; 53 | enum ENUM_ORDERING { REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER }; 54 | 55 | // 56 | // 57 | // Ansi structures and functions follow 58 | // 59 | // 60 | 61 | static struct _getopt_data_a 62 | { 63 | int optind; 64 | int opterr; 65 | int optopt; 66 | char *optarg; 67 | int __initialized; 68 | char *__nextchar; 69 | enum ENUM_ORDERING __ordering; 70 | int __posixly_correct; 71 | int __first_nonopt; 72 | int __last_nonopt; 73 | } getopt_data_a; 74 | char *optarg_a; 75 | 76 | static void exchange_a(char **argv, struct _getopt_data_a *d) 77 | { 78 | int bottom = d->__first_nonopt; 79 | int middle = d->__last_nonopt; 80 | int top = d->optind; 81 | char *tem; 82 | while (top > middle && middle > bottom) 83 | { 84 | if (top - middle > middle - bottom) 85 | { 86 | int len = middle - bottom; 87 | register int i; 88 | for (i = 0; i < len; i++) 89 | { 90 | tem = argv[bottom + i]; 91 | argv[bottom + i] = argv[top - (middle - bottom) + i]; 92 | argv[top - (middle - bottom) + i] = tem; 93 | } 94 | top -= len; 95 | } 96 | else 97 | { 98 | int len = top - middle; 99 | register int i; 100 | for (i = 0; i < len; i++) 101 | { 102 | tem = argv[bottom + i]; 103 | argv[bottom + i] = argv[middle + i]; 104 | argv[middle + i] = tem; 105 | } 106 | bottom += len; 107 | } 108 | } 109 | d->__first_nonopt += (d->optind - d->__last_nonopt); 110 | d->__last_nonopt = d->optind; 111 | } 112 | static const char *_getopt_initialize_a (const char *optstring, struct _getopt_data_a *d, int posixly_correct) 113 | { 114 | d->__first_nonopt = d->__last_nonopt = d->optind; 115 | d->__nextchar = NULL; 116 | d->__posixly_correct = posixly_correct | !!getenv("POSIXLY_CORRECT"); 117 | if (optstring[0] == '-') 118 | { 119 | d->__ordering = RETURN_IN_ORDER; 120 | ++optstring; 121 | } 122 | else if (optstring[0] == '+') 123 | { 124 | d->__ordering = REQUIRE_ORDER; 125 | ++optstring; 126 | } 127 | else if (d->__posixly_correct) 128 | d->__ordering = REQUIRE_ORDER; 129 | else 130 | d->__ordering = PERMUTE; 131 | return optstring; 132 | } 133 | int _getopt_internal_r_a (int argc, char *const *argv, const char *optstring, const struct option_a *longopts, int *longind, int long_only, struct _getopt_data_a *d, int posixly_correct) 134 | { 135 | int print_errors = d->opterr; 136 | if (argc < 1) 137 | return -1; 138 | d->optarg = NULL; 139 | if (d->optind == 0 || !d->__initialized) 140 | { 141 | if (d->optind == 0) 142 | d->optind = 1; 143 | optstring = _getopt_initialize_a (optstring, d, posixly_correct); 144 | d->__initialized = 1; 145 | } 146 | else if (optstring[0] == '-' || optstring[0] == '+') 147 | optstring++; 148 | if (optstring[0] == ':') 149 | print_errors = 0; 150 | if (d->__nextchar == NULL || *d->__nextchar == '\0') 151 | { 152 | if (d->__last_nonopt > d->optind) 153 | d->__last_nonopt = d->optind; 154 | if (d->__first_nonopt > d->optind) 155 | d->__first_nonopt = d->optind; 156 | if (d->__ordering == PERMUTE) 157 | { 158 | if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind) 159 | exchange_a ((char **) argv, d); 160 | else if (d->__last_nonopt != d->optind) 161 | d->__first_nonopt = d->optind; 162 | while (d->optind < argc && (argv[d->optind][0] != '-' || argv[d->optind][1] == '\0')) 163 | d->optind++; 164 | d->__last_nonopt = d->optind; 165 | } 166 | if (d->optind != argc && !strcmp(argv[d->optind], "--")) 167 | { 168 | d->optind++; 169 | if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind) 170 | exchange_a((char **) argv, d); 171 | else if (d->__first_nonopt == d->__last_nonopt) 172 | d->__first_nonopt = d->optind; 173 | d->__last_nonopt = argc; 174 | d->optind = argc; 175 | } 176 | if (d->optind == argc) 177 | { 178 | if (d->__first_nonopt != d->__last_nonopt) 179 | d->optind = d->__first_nonopt; 180 | return -1; 181 | } 182 | if ((argv[d->optind][0] != '-' || argv[d->optind][1] == '\0')) 183 | { 184 | if (d->__ordering == REQUIRE_ORDER) 185 | return -1; 186 | d->optarg = argv[d->optind++]; 187 | return 1; 188 | } 189 | d->__nextchar = (argv[d->optind] + 1 + (longopts != NULL && argv[d->optind][1] == '-')); 190 | } 191 | if (longopts != NULL && (argv[d->optind][1] == '-' || (long_only && (argv[d->optind][2] || !strchr(optstring, argv[d->optind][1]))))) 192 | { 193 | char *nameend; 194 | unsigned int namelen; 195 | const struct option_a *p; 196 | const struct option_a *pfound = NULL; 197 | struct option_list 198 | { 199 | const struct option_a *p; 200 | struct option_list *next; 201 | } *ambig_list = NULL; 202 | int exact = 0; 203 | int indfound = -1; 204 | int option_index; 205 | for (nameend = d->__nextchar; *nameend && *nameend != '='; nameend++); 206 | namelen = (unsigned int)(nameend - d->__nextchar); 207 | for (p = longopts, option_index = 0; p->name; p++, option_index++) 208 | if (!strncmp(p->name, d->__nextchar, namelen)) 209 | { 210 | if (namelen == (unsigned int)strlen(p->name)) 211 | { 212 | pfound = p; 213 | indfound = option_index; 214 | exact = 1; 215 | break; 216 | } 217 | else if (pfound == NULL) 218 | { 219 | pfound = p; 220 | indfound = option_index; 221 | } 222 | else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val) 223 | { 224 | struct option_list *newp = (struct option_list*)alloca(sizeof(*newp)); 225 | newp->p = p; 226 | newp->next = ambig_list; 227 | ambig_list = newp; 228 | } 229 | } 230 | if (ambig_list != NULL && !exact) 231 | { 232 | if (print_errors) 233 | { 234 | struct option_list first; 235 | first.p = pfound; 236 | first.next = ambig_list; 237 | ambig_list = &first; 238 | fprintf (stderr, "%s: option '%s' is ambiguous; possibilities:", argv[0], argv[d->optind]); 239 | do 240 | { 241 | fprintf (stderr, " '--%s'", ambig_list->p->name); 242 | ambig_list = ambig_list->next; 243 | } 244 | while (ambig_list != NULL); 245 | fputc ('\n', stderr); 246 | } 247 | d->__nextchar += strlen(d->__nextchar); 248 | d->optind++; 249 | d->optopt = 0; 250 | return '?'; 251 | } 252 | if (pfound != NULL) 253 | { 254 | option_index = indfound; 255 | d->optind++; 256 | if (*nameend) 257 | { 258 | if (pfound->has_arg) 259 | d->optarg = nameend + 1; 260 | else 261 | { 262 | if (print_errors) 263 | { 264 | if (argv[d->optind - 1][1] == '-') 265 | { 266 | fprintf(stderr, "%s: option '--%s' doesn't allow an argument\n",argv[0], pfound->name); 267 | } 268 | else 269 | { 270 | fprintf(stderr, "%s: option '%c%s' doesn't allow an argument\n",argv[0], argv[d->optind - 1][0],pfound->name); 271 | } 272 | } 273 | d->__nextchar += strlen(d->__nextchar); 274 | d->optopt = pfound->val; 275 | return '?'; 276 | } 277 | } 278 | else if (pfound->has_arg == 1) 279 | { 280 | if (d->optind < argc) 281 | d->optarg = argv[d->optind++]; 282 | else 283 | { 284 | if (print_errors) 285 | { 286 | fprintf(stderr,"%s: option '--%s' requires an argument\n",argv[0], pfound->name); 287 | } 288 | d->__nextchar += strlen(d->__nextchar); 289 | d->optopt = pfound->val; 290 | return optstring[0] == ':' ? ':' : '?'; 291 | } 292 | } 293 | d->__nextchar += strlen(d->__nextchar); 294 | if (longind != NULL) 295 | *longind = option_index; 296 | if (pfound->flag) 297 | { 298 | *(pfound->flag) = pfound->val; 299 | return 0; 300 | } 301 | return pfound->val; 302 | } 303 | if (!long_only || argv[d->optind][1] == '-' || strchr(optstring, *d->__nextchar) == NULL) 304 | { 305 | if (print_errors) 306 | { 307 | if (argv[d->optind][1] == '-') 308 | { 309 | fprintf(stderr, "%s: unrecognized option '--%s'\n",argv[0], d->__nextchar); 310 | } 311 | else 312 | { 313 | fprintf(stderr, "%s: unrecognized option '%c%s'\n",argv[0], argv[d->optind][0], d->__nextchar); 314 | } 315 | } 316 | d->__nextchar = (char *)""; 317 | d->optind++; 318 | d->optopt = 0; 319 | return '?'; 320 | } 321 | } 322 | { 323 | char c = *d->__nextchar++; 324 | char *temp = (char*)strchr(optstring, c); 325 | if (*d->__nextchar == '\0') 326 | ++d->optind; 327 | if (temp == NULL || c == ':' || c == ';') 328 | { 329 | if (print_errors) 330 | { 331 | fprintf(stderr, "%s: invalid option -- '%c'\n", argv[0], c); 332 | } 333 | d->optopt = c; 334 | return '?'; 335 | } 336 | if (temp[0] == 'W' && temp[1] == ';') 337 | { 338 | char *nameend; 339 | const struct option_a *p; 340 | const struct option_a *pfound = NULL; 341 | int exact = 0; 342 | int ambig = 0; 343 | int indfound = 0; 344 | int option_index; 345 | if (longopts == NULL) 346 | goto no_longs; 347 | if (*d->__nextchar != '\0') 348 | { 349 | d->optarg = d->__nextchar; 350 | d->optind++; 351 | } 352 | else if (d->optind == argc) 353 | { 354 | if (print_errors) 355 | { 356 | fprintf(stderr,"%s: option requires an argument -- '%c'\n",argv[0], c); 357 | } 358 | d->optopt = c; 359 | if (optstring[0] == ':') 360 | c = ':'; 361 | else 362 | c = '?'; 363 | return c; 364 | } 365 | else 366 | d->optarg = argv[d->optind++]; 367 | for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != '='; nameend++); 368 | for (p = longopts, option_index = 0; p->name; p++, option_index++) 369 | if (!strncmp(p->name, d->__nextchar, nameend - d->__nextchar)) 370 | { 371 | if ((unsigned int) (nameend - d->__nextchar) == strlen(p->name)) 372 | { 373 | pfound = p; 374 | indfound = option_index; 375 | exact = 1; 376 | break; 377 | } 378 | else if (pfound == NULL) 379 | { 380 | pfound = p; 381 | indfound = option_index; 382 | } 383 | else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val) 384 | ambig = 1; 385 | } 386 | if (ambig && !exact) 387 | { 388 | if (print_errors) 389 | { 390 | fprintf(stderr, "%s: option '-W %s' is ambiguous\n",argv[0], d->optarg); 391 | } 392 | d->__nextchar += strlen(d->__nextchar); 393 | d->optind++; 394 | return '?'; 395 | } 396 | if (pfound != NULL) 397 | { 398 | option_index = indfound; 399 | if (*nameend) 400 | { 401 | if (pfound->has_arg) 402 | d->optarg = nameend + 1; 403 | else 404 | { 405 | if (print_errors) 406 | { 407 | fprintf(stderr, "%s: option '-W %s' doesn't allow an argument\n",argv[0], pfound->name); 408 | } 409 | d->__nextchar += strlen(d->__nextchar); 410 | return '?'; 411 | } 412 | } 413 | else if (pfound->has_arg == 1) 414 | { 415 | if (d->optind < argc) 416 | d->optarg = argv[d->optind++]; 417 | else 418 | { 419 | if (print_errors) 420 | { 421 | fprintf(stderr, "%s: option '-W %s' requires an argument\n",argv[0], pfound->name); 422 | } 423 | d->__nextchar += strlen(d->__nextchar); 424 | return optstring[0] == ':' ? ':' : '?'; 425 | } 426 | } 427 | else 428 | d->optarg = NULL; 429 | d->__nextchar += strlen(d->__nextchar); 430 | if (longind != NULL) 431 | *longind = option_index; 432 | if (pfound->flag) 433 | { 434 | *(pfound->flag) = pfound->val; 435 | return 0; 436 | } 437 | return pfound->val; 438 | } 439 | no_longs: 440 | d->__nextchar = NULL; 441 | return 'W'; 442 | } 443 | if (temp[1] == ':') 444 | { 445 | if (temp[2] == ':') 446 | { 447 | if (*d->__nextchar != '\0') 448 | { 449 | d->optarg = d->__nextchar; 450 | d->optind++; 451 | } 452 | else 453 | d->optarg = NULL; 454 | d->__nextchar = NULL; 455 | } 456 | else 457 | { 458 | if (*d->__nextchar != '\0') 459 | { 460 | d->optarg = d->__nextchar; 461 | d->optind++; 462 | } 463 | else if (d->optind == argc) 464 | { 465 | if (print_errors) 466 | { 467 | fprintf(stderr,"%s: option requires an argument -- '%c'\n",argv[0], c); 468 | } 469 | d->optopt = c; 470 | if (optstring[0] == ':') 471 | c = ':'; 472 | else 473 | c = '?'; 474 | } 475 | else 476 | d->optarg = argv[d->optind++]; 477 | d->__nextchar = NULL; 478 | } 479 | } 480 | return c; 481 | } 482 | } 483 | int _getopt_internal_a (int argc, char *const *argv, const char *optstring, const struct option_a *longopts, int *longind, int long_only, int posixly_correct) 484 | { 485 | int result; 486 | getopt_data_a.optind = optind; 487 | getopt_data_a.opterr = opterr; 488 | result = _getopt_internal_r_a (argc, argv, optstring, longopts,longind, long_only, &getopt_data_a,posixly_correct); 489 | optind = getopt_data_a.optind; 490 | optarg_a = getopt_data_a.optarg; 491 | optopt = getopt_data_a.optopt; 492 | return result; 493 | } 494 | int getopt_a (int argc, char *const *argv, const char *optstring) _GETOPT_THROW 495 | { 496 | return _getopt_internal_a (argc, argv, optstring, (const struct option_a *) 0, (int *) 0, 0, 0); 497 | } 498 | int getopt_long_a (int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index) _GETOPT_THROW 499 | { 500 | return _getopt_internal_a (argc, argv, options, long_options, opt_index, 0, 0); 501 | } 502 | int getopt_long_only_a (int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index) _GETOPT_THROW 503 | { 504 | return _getopt_internal_a (argc, argv, options, long_options, opt_index, 1, 0); 505 | } 506 | int _getopt_long_r_a (int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index, struct _getopt_data_a *d) 507 | { 508 | return _getopt_internal_r_a (argc, argv, options, long_options, opt_index,0, d, 0); 509 | } 510 | int _getopt_long_only_r_a (int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index, struct _getopt_data_a *d) 511 | { 512 | return _getopt_internal_r_a (argc, argv, options, long_options, opt_index, 1, d, 0); 513 | } 514 | 515 | // 516 | // 517 | // Unicode Structures and Functions 518 | // 519 | // 520 | 521 | static struct _getopt_data_w 522 | { 523 | int optind; 524 | int opterr; 525 | int optopt; 526 | wchar_t *optarg; 527 | int __initialized; 528 | wchar_t *__nextchar; 529 | enum ENUM_ORDERING __ordering; 530 | int __posixly_correct; 531 | int __first_nonopt; 532 | int __last_nonopt; 533 | } getopt_data_w; 534 | wchar_t *optarg_w; 535 | 536 | static void exchange_w(wchar_t **argv, struct _getopt_data_w *d) 537 | { 538 | int bottom = d->__first_nonopt; 539 | int middle = d->__last_nonopt; 540 | int top = d->optind; 541 | wchar_t *tem; 542 | while (top > middle && middle > bottom) 543 | { 544 | if (top - middle > middle - bottom) 545 | { 546 | int len = middle - bottom; 547 | register int i; 548 | for (i = 0; i < len; i++) 549 | { 550 | tem = argv[bottom + i]; 551 | argv[bottom + i] = argv[top - (middle - bottom) + i]; 552 | argv[top - (middle - bottom) + i] = tem; 553 | } 554 | top -= len; 555 | } 556 | else 557 | { 558 | int len = top - middle; 559 | register int i; 560 | for (i = 0; i < len; i++) 561 | { 562 | tem = argv[bottom + i]; 563 | argv[bottom + i] = argv[middle + i]; 564 | argv[middle + i] = tem; 565 | } 566 | bottom += len; 567 | } 568 | } 569 | d->__first_nonopt += (d->optind - d->__last_nonopt); 570 | d->__last_nonopt = d->optind; 571 | } 572 | static const wchar_t *_getopt_initialize_w (const wchar_t *optstring, struct _getopt_data_w *d, int posixly_correct) 573 | { 574 | d->__first_nonopt = d->__last_nonopt = d->optind; 575 | d->__nextchar = NULL; 576 | d->__posixly_correct = posixly_correct | !!_wgetenv(L"POSIXLY_CORRECT"); 577 | if (optstring[0] == L'-') 578 | { 579 | d->__ordering = RETURN_IN_ORDER; 580 | ++optstring; 581 | } 582 | else if (optstring[0] == L'+') 583 | { 584 | d->__ordering = REQUIRE_ORDER; 585 | ++optstring; 586 | } 587 | else if (d->__posixly_correct) 588 | d->__ordering = REQUIRE_ORDER; 589 | else 590 | d->__ordering = PERMUTE; 591 | return optstring; 592 | } 593 | int _getopt_internal_r_w (int argc, wchar_t *const *argv, const wchar_t *optstring, const struct option_w *longopts, int *longind, int long_only, struct _getopt_data_w *d, int posixly_correct) 594 | { 595 | int print_errors = d->opterr; 596 | if (argc < 1) 597 | return -1; 598 | d->optarg = NULL; 599 | if (d->optind == 0 || !d->__initialized) 600 | { 601 | if (d->optind == 0) 602 | d->optind = 1; 603 | optstring = _getopt_initialize_w (optstring, d, posixly_correct); 604 | d->__initialized = 1; 605 | } 606 | else if (optstring[0] == L'-' || optstring[0] == L'+') 607 | optstring++; 608 | if (optstring[0] == L':') 609 | print_errors = 0; 610 | if (d->__nextchar == NULL || *d->__nextchar == L'\0') 611 | { 612 | if (d->__last_nonopt > d->optind) 613 | d->__last_nonopt = d->optind; 614 | if (d->__first_nonopt > d->optind) 615 | d->__first_nonopt = d->optind; 616 | if (d->__ordering == PERMUTE) 617 | { 618 | if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind) 619 | exchange_w((wchar_t **) argv, d); 620 | else if (d->__last_nonopt != d->optind) 621 | d->__first_nonopt = d->optind; 622 | while (d->optind < argc && (argv[d->optind][0] != L'-' || argv[d->optind][1] == L'\0')) 623 | d->optind++; 624 | d->__last_nonopt = d->optind; 625 | } 626 | if (d->optind != argc && !wcscmp(argv[d->optind], L"--")) 627 | { 628 | d->optind++; 629 | if (d->__first_nonopt != d->__last_nonopt && d->__last_nonopt != d->optind) 630 | exchange_w((wchar_t **) argv, d); 631 | else if (d->__first_nonopt == d->__last_nonopt) 632 | d->__first_nonopt = d->optind; 633 | d->__last_nonopt = argc; 634 | d->optind = argc; 635 | } 636 | if (d->optind == argc) 637 | { 638 | if (d->__first_nonopt != d->__last_nonopt) 639 | d->optind = d->__first_nonopt; 640 | return -1; 641 | } 642 | if ((argv[d->optind][0] != L'-' || argv[d->optind][1] == L'\0')) 643 | { 644 | if (d->__ordering == REQUIRE_ORDER) 645 | return -1; 646 | d->optarg = argv[d->optind++]; 647 | return 1; 648 | } 649 | d->__nextchar = (argv[d->optind] + 1 + (longopts != NULL && argv[d->optind][1] == L'-')); 650 | } 651 | if (longopts != NULL && (argv[d->optind][1] == L'-' || (long_only && (argv[d->optind][2] || !wcschr(optstring, argv[d->optind][1]))))) 652 | { 653 | wchar_t *nameend; 654 | unsigned int namelen; 655 | const struct option_w *p; 656 | const struct option_w *pfound = NULL; 657 | struct option_list 658 | { 659 | const struct option_w *p; 660 | struct option_list *next; 661 | } *ambig_list = NULL; 662 | int exact = 0; 663 | int indfound = -1; 664 | int option_index; 665 | for (nameend = d->__nextchar; *nameend && *nameend != L'='; nameend++); 666 | namelen = (unsigned int)(nameend - d->__nextchar); 667 | for (p = longopts, option_index = 0; p->name; p++, option_index++) 668 | if (!wcsncmp(p->name, d->__nextchar, namelen)) 669 | { 670 | if (namelen == (unsigned int)wcslen(p->name)) 671 | { 672 | pfound = p; 673 | indfound = option_index; 674 | exact = 1; 675 | break; 676 | } 677 | else if (pfound == NULL) 678 | { 679 | pfound = p; 680 | indfound = option_index; 681 | } 682 | else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val) 683 | { 684 | struct option_list *newp = (struct option_list*)alloca(sizeof(*newp)); 685 | newp->p = p; 686 | newp->next = ambig_list; 687 | ambig_list = newp; 688 | } 689 | } 690 | if (ambig_list != NULL && !exact) 691 | { 692 | if (print_errors) 693 | { 694 | struct option_list first; 695 | first.p = pfound; 696 | first.next = ambig_list; 697 | ambig_list = &first; 698 | fwprintf(stderr, L"%s: option '%s' is ambiguous; possibilities:", argv[0], argv[d->optind]); 699 | do 700 | { 701 | fwprintf (stderr, L" '--%s'", ambig_list->p->name); 702 | ambig_list = ambig_list->next; 703 | } 704 | while (ambig_list != NULL); 705 | fputwc (L'\n', stderr); 706 | } 707 | d->__nextchar += wcslen(d->__nextchar); 708 | d->optind++; 709 | d->optopt = 0; 710 | return L'?'; 711 | } 712 | if (pfound != NULL) 713 | { 714 | option_index = indfound; 715 | d->optind++; 716 | if (*nameend) 717 | { 718 | if (pfound->has_arg) 719 | d->optarg = nameend + 1; 720 | else 721 | { 722 | if (print_errors) 723 | { 724 | if (argv[d->optind - 1][1] == L'-') 725 | { 726 | fwprintf(stderr, L"%s: option '--%s' doesn't allow an argument\n",argv[0], pfound->name); 727 | } 728 | else 729 | { 730 | fwprintf(stderr, L"%s: option '%c%s' doesn't allow an argument\n",argv[0], argv[d->optind - 1][0],pfound->name); 731 | } 732 | } 733 | d->__nextchar += wcslen(d->__nextchar); 734 | d->optopt = pfound->val; 735 | return L'?'; 736 | } 737 | } 738 | else if (pfound->has_arg == 1) 739 | { 740 | if (d->optind < argc) 741 | d->optarg = argv[d->optind++]; 742 | else 743 | { 744 | if (print_errors) 745 | { 746 | fwprintf(stderr,L"%s: option '--%s' requires an argument\n",argv[0], pfound->name); 747 | } 748 | d->__nextchar += wcslen(d->__nextchar); 749 | d->optopt = pfound->val; 750 | return optstring[0] == L':' ? L':' : L'?'; 751 | } 752 | } 753 | d->__nextchar += wcslen(d->__nextchar); 754 | if (longind != NULL) 755 | *longind = option_index; 756 | if (pfound->flag) 757 | { 758 | *(pfound->flag) = pfound->val; 759 | return 0; 760 | } 761 | return pfound->val; 762 | } 763 | if (!long_only || argv[d->optind][1] == L'-' || wcschr(optstring, *d->__nextchar) == NULL) 764 | { 765 | if (print_errors) 766 | { 767 | if (argv[d->optind][1] == L'-') 768 | { 769 | fwprintf(stderr, L"%s: unrecognized option '--%s'\n",argv[0], d->__nextchar); 770 | } 771 | else 772 | { 773 | fwprintf(stderr, L"%s: unrecognized option '%c%s'\n",argv[0], argv[d->optind][0], d->__nextchar); 774 | } 775 | } 776 | d->__nextchar = (wchar_t *)L""; 777 | d->optind++; 778 | d->optopt = 0; 779 | return L'?'; 780 | } 781 | } 782 | { 783 | wchar_t c = *d->__nextchar++; 784 | wchar_t *temp = (wchar_t*)wcschr(optstring, c); 785 | if (*d->__nextchar == L'\0') 786 | ++d->optind; 787 | if (temp == NULL || c == L':' || c == L';') 788 | { 789 | if (print_errors) 790 | { 791 | fwprintf(stderr, L"%s: invalid option -- '%c'\n", argv[0], c); 792 | } 793 | d->optopt = c; 794 | return L'?'; 795 | } 796 | if (temp[0] == L'W' && temp[1] == L';') 797 | { 798 | wchar_t *nameend; 799 | const struct option_w *p; 800 | const struct option_w *pfound = NULL; 801 | int exact = 0; 802 | int ambig = 0; 803 | int indfound = 0; 804 | int option_index; 805 | if (longopts == NULL) 806 | goto no_longs; 807 | if (*d->__nextchar != L'\0') 808 | { 809 | d->optarg = d->__nextchar; 810 | d->optind++; 811 | } 812 | else if (d->optind == argc) 813 | { 814 | if (print_errors) 815 | { 816 | fwprintf(stderr,L"%s: option requires an argument -- '%c'\n",argv[0], c); 817 | } 818 | d->optopt = c; 819 | if (optstring[0] == L':') 820 | c = L':'; 821 | else 822 | c = L'?'; 823 | return c; 824 | } 825 | else 826 | d->optarg = argv[d->optind++]; 827 | for (d->__nextchar = nameend = d->optarg; *nameend && *nameend != L'='; nameend++); 828 | for (p = longopts, option_index = 0; p->name; p++, option_index++) 829 | if (!wcsncmp(p->name, d->__nextchar, nameend - d->__nextchar)) 830 | { 831 | if ((unsigned int) (nameend - d->__nextchar) == wcslen(p->name)) 832 | { 833 | pfound = p; 834 | indfound = option_index; 835 | exact = 1; 836 | break; 837 | } 838 | else if (pfound == NULL) 839 | { 840 | pfound = p; 841 | indfound = option_index; 842 | } 843 | else if (long_only || pfound->has_arg != p->has_arg || pfound->flag != p->flag || pfound->val != p->val) 844 | ambig = 1; 845 | } 846 | if (ambig && !exact) 847 | { 848 | if (print_errors) 849 | { 850 | fwprintf(stderr, L"%s: option '-W %s' is ambiguous\n",argv[0], d->optarg); 851 | } 852 | d->__nextchar += wcslen(d->__nextchar); 853 | d->optind++; 854 | return L'?'; 855 | } 856 | if (pfound != NULL) 857 | { 858 | option_index = indfound; 859 | if (*nameend) 860 | { 861 | if (pfound->has_arg) 862 | d->optarg = nameend + 1; 863 | else 864 | { 865 | if (print_errors) 866 | { 867 | fwprintf(stderr, L"%s: option '-W %s' doesn't allow an argument\n",argv[0], pfound->name); 868 | } 869 | d->__nextchar += wcslen(d->__nextchar); 870 | return L'?'; 871 | } 872 | } 873 | else if (pfound->has_arg == 1) 874 | { 875 | if (d->optind < argc) 876 | d->optarg = argv[d->optind++]; 877 | else 878 | { 879 | if (print_errors) 880 | { 881 | fwprintf(stderr, L"%s: option '-W %s' requires an argument\n",argv[0], pfound->name); 882 | } 883 | d->__nextchar += wcslen(d->__nextchar); 884 | return optstring[0] == L':' ? L':' : L'?'; 885 | } 886 | } 887 | else 888 | d->optarg = NULL; 889 | d->__nextchar += wcslen(d->__nextchar); 890 | if (longind != NULL) 891 | *longind = option_index; 892 | if (pfound->flag) 893 | { 894 | *(pfound->flag) = pfound->val; 895 | return 0; 896 | } 897 | return pfound->val; 898 | } 899 | no_longs: 900 | d->__nextchar = NULL; 901 | return L'W'; 902 | } 903 | if (temp[1] == L':') 904 | { 905 | if (temp[2] == L':') 906 | { 907 | if (*d->__nextchar != L'\0') 908 | { 909 | d->optarg = d->__nextchar; 910 | d->optind++; 911 | } 912 | else 913 | d->optarg = NULL; 914 | d->__nextchar = NULL; 915 | } 916 | else 917 | { 918 | if (*d->__nextchar != L'\0') 919 | { 920 | d->optarg = d->__nextchar; 921 | d->optind++; 922 | } 923 | else if (d->optind == argc) 924 | { 925 | if (print_errors) 926 | { 927 | fwprintf(stderr,L"%s: option requires an argument -- '%c'\n",argv[0], c); 928 | } 929 | d->optopt = c; 930 | if (optstring[0] == L':') 931 | c = L':'; 932 | else 933 | c = L'?'; 934 | } 935 | else 936 | d->optarg = argv[d->optind++]; 937 | d->__nextchar = NULL; 938 | } 939 | } 940 | return c; 941 | } 942 | } 943 | int _getopt_internal_w (int argc, wchar_t *const *argv, const wchar_t *optstring, const struct option_w *longopts, int *longind, int long_only, int posixly_correct) 944 | { 945 | int result; 946 | getopt_data_w.optind = optind; 947 | getopt_data_w.opterr = opterr; 948 | result = _getopt_internal_r_w (argc, argv, optstring, longopts,longind, long_only, &getopt_data_w,posixly_correct); 949 | optind = getopt_data_w.optind; 950 | optarg_w = getopt_data_w.optarg; 951 | optopt = getopt_data_w.optopt; 952 | return result; 953 | } 954 | int getopt_w (int argc, wchar_t *const *argv, const wchar_t *optstring) _GETOPT_THROW 955 | { 956 | return _getopt_internal_w (argc, argv, optstring, (const struct option_w *) 0, (int *) 0, 0, 0); 957 | } 958 | int getopt_long_w (int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index) _GETOPT_THROW 959 | { 960 | return _getopt_internal_w (argc, argv, options, long_options, opt_index, 0, 0); 961 | } 962 | int getopt_long_only_w (int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index) _GETOPT_THROW 963 | { 964 | return _getopt_internal_w (argc, argv, options, long_options, opt_index, 1, 0); 965 | } 966 | int _getopt_long_r_w (int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index, struct _getopt_data_w *d) 967 | { 968 | return _getopt_internal_r_w (argc, argv, options, long_options, opt_index,0, d, 0); 969 | } 970 | int _getopt_long_only_r_w (int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index, struct _getopt_data_w *d) 971 | { 972 | return _getopt_internal_r_w (argc, argv, options, long_options, opt_index, 1, d, 0); 973 | } -------------------------------------------------------------------------------- /getopt.h: -------------------------------------------------------------------------------- 1 | /* Getopt for Microsoft C 2 | This code is a modification of the Free Software Foundation, Inc. 3 | Getopt library for parsing command line argument the purpose was 4 | to provide a Microsoft Visual C friendly derivative. This code 5 | provides functionality for both Unicode and Multibyte builds. 6 | 7 | Date: 02/03/2011 - Ludvik Jerabek - Initial Release 8 | Version: 1.0 9 | Comment: Supports getopt, getopt_long, and getopt_long_only 10 | and POSIXLY_CORRECT environment flag 11 | License: LGPL 12 | 13 | Revisions: 14 | 15 | 02/03/2011 - Ludvik Jerabek - Initial Release 16 | 02/20/2011 - Ludvik Jerabek - Fixed compiler warnings at Level 4 17 | 07/05/2011 - Ludvik Jerabek - Added no_argument, required_argument, optional_argument defs 18 | 08/03/2011 - Ludvik Jerabek - Fixed non-argument runtime bug which caused runtime exception 19 | 08/09/2011 - Ludvik Jerabek - Added code to export functions for DLL and LIB 20 | 02/15/2012 - Ludvik Jerabek - Fixed _GETOPT_THROW definition missing in implementation file 21 | 08/01/2012 - Ludvik Jerabek - Created separate functions for char and wchar_t characters so single dll can do both unicode and ansi 22 | 10/15/2012 - Ludvik Jerabek - Modified to match latest GNU features 23 | 06/19/2015 - Ludvik Jerabek - Fixed maximum option limitation caused by option_a (255) and option_w (65535) structure val variable 24 | 25 | **DISCLAIMER** 26 | THIS MATERIAL IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 27 | EITHER EXPRESS OR IMPLIED, INCLUDING, BUT Not LIMITED TO, THE 28 | IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 29 | PURPOSE, OR NON-INFRINGEMENT. SOME JURISDICTIONS DO NOT ALLOW THE 30 | EXCLUSION OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSION MAY NOT 31 | APPLY TO YOU. IN NO EVENT WILL I BE LIABLE TO ANY PARTY FOR ANY 32 | DIRECT, INDIRECT, SPECIAL OR OTHER CONSEQUENTIAL DAMAGES FOR ANY 33 | USE OF THIS MATERIAL INCLUDING, WITHOUT LIMITATION, ANY LOST 34 | PROFITS, BUSINESS INTERRUPTION, LOSS OF PROGRAMS OR OTHER DATA ON 35 | YOUR INFORMATION HANDLING SYSTEM OR OTHERWISE, EVEN If WE ARE 36 | EXPRESSLY ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 37 | */ 38 | #ifndef __GETOPT_H_ 39 | #define __GETOPT_H_ 40 | 41 | #ifdef _GETOPT_API 42 | #undef _GETOPT_API 43 | #endif 44 | 45 | #if defined(EXPORTS_GETOPT) && defined(STATIC_GETOPT) 46 | #error "The preprocessor definitions of EXPORTS_GETOPT and STATIC_GETOPT can only be used individually" 47 | #elif defined(STATIC_GETOPT) 48 | #pragma message("Warning static builds of getopt violate the Lesser GNU Public License") 49 | #define _GETOPT_API 50 | #elif defined(EXPORTS_GETOPT) 51 | #pragma message("Exporting getopt library") 52 | #define _GETOPT_API __declspec(dllexport) 53 | #else 54 | #pragma message("Importing getopt library") 55 | #define _GETOPT_API __declspec(dllimport) 56 | #endif 57 | 58 | // Change behavior for C\C++ 59 | #ifdef __cplusplus 60 | #define _BEGIN_EXTERN_C extern "C" { 61 | #define _END_EXTERN_C } 62 | #define _GETOPT_THROW throw() 63 | #else 64 | #define _BEGIN_EXTERN_C 65 | #define _END_EXTERN_C 66 | #define _GETOPT_THROW 67 | #endif 68 | 69 | // Standard GNU options 70 | #define null_argument 0 /*Argument Null*/ 71 | #define no_argument 0 /*Argument Switch Only*/ 72 | #define required_argument 1 /*Argument Required*/ 73 | #define optional_argument 2 /*Argument Optional*/ 74 | 75 | // Shorter Options 76 | #define ARG_NULL 0 /*Argument Null*/ 77 | #define ARG_NONE 0 /*Argument Switch Only*/ 78 | #define ARG_REQ 1 /*Argument Required*/ 79 | #define ARG_OPT 2 /*Argument Optional*/ 80 | 81 | #include 82 | #include 83 | 84 | _BEGIN_EXTERN_C 85 | 86 | extern _GETOPT_API int optind; 87 | extern _GETOPT_API int opterr; 88 | extern _GETOPT_API int optopt; 89 | 90 | // Ansi 91 | struct option_a 92 | { 93 | const char* name; 94 | int has_arg; 95 | int *flag; 96 | int val; 97 | }; 98 | extern _GETOPT_API char *optarg_a; 99 | extern _GETOPT_API int getopt_a(int argc, char *const *argv, const char *optstring) _GETOPT_THROW; 100 | extern _GETOPT_API int getopt_long_a(int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index) _GETOPT_THROW; 101 | extern _GETOPT_API int getopt_long_only_a(int argc, char *const *argv, const char *options, const struct option_a *long_options, int *opt_index) _GETOPT_THROW; 102 | 103 | // Unicode 104 | struct option_w 105 | { 106 | const wchar_t* name; 107 | int has_arg; 108 | int *flag; 109 | int val; 110 | }; 111 | extern _GETOPT_API wchar_t *optarg_w; 112 | extern _GETOPT_API int getopt_w(int argc, wchar_t *const *argv, const wchar_t *optstring) _GETOPT_THROW; 113 | extern _GETOPT_API int getopt_long_w(int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index) _GETOPT_THROW; 114 | extern _GETOPT_API int getopt_long_only_w(int argc, wchar_t *const *argv, const wchar_t *options, const struct option_w *long_options, int *opt_index) _GETOPT_THROW; 115 | 116 | _END_EXTERN_C 117 | 118 | #undef _BEGIN_EXTERN_C 119 | #undef _END_EXTERN_C 120 | #undef _GETOPT_THROW 121 | #undef _GETOPT_API 122 | 123 | #ifdef _UNICODE 124 | #define getopt getopt_w 125 | #define getopt_long getopt_long_w 126 | #define getopt_long_only getopt_long_only_w 127 | #define option option_w 128 | #define optarg optarg_w 129 | #else 130 | #define getopt getopt_a 131 | #define getopt_long getopt_long_a 132 | #define getopt_long_only getopt_long_only_a 133 | #define option option_a 134 | #define optarg optarg_a 135 | #endif 136 | #endif // __GETOPT_H_ 137 | -------------------------------------------------------------------------------- /getopt.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27705.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "getopt", "getopt.vcxproj", "{4BBAEAA1-9AD1-42D2-B6DC-7F73C4B3D238}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Win32 = Debug|Win32 11 | Debug|x64 = Debug|x64 12 | Release|Win32 = Release|Win32 13 | Release|x64 = Release|x64 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {4BBAEAA1-9AD1-42D2-B6DC-7F73C4B3D238}.Debug|Win32.ActiveCfg = Debug|Win32 17 | {4BBAEAA1-9AD1-42D2-B6DC-7F73C4B3D238}.Debug|Win32.Build.0 = Debug|Win32 18 | {4BBAEAA1-9AD1-42D2-B6DC-7F73C4B3D238}.Debug|x64.ActiveCfg = Debug|x64 19 | {4BBAEAA1-9AD1-42D2-B6DC-7F73C4B3D238}.Debug|x64.Build.0 = Debug|x64 20 | {4BBAEAA1-9AD1-42D2-B6DC-7F73C4B3D238}.Release|Win32.ActiveCfg = Release|Win32 21 | {4BBAEAA1-9AD1-42D2-B6DC-7F73C4B3D238}.Release|Win32.Build.0 = Release|Win32 22 | {4BBAEAA1-9AD1-42D2-B6DC-7F73C4B3D238}.Release|x64.ActiveCfg = Release|x64 23 | {4BBAEAA1-9AD1-42D2-B6DC-7F73C4B3D238}.Release|x64.Build.0 = Release|x64 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {4E6DE38C-035F-4DBE-9385-C35AC4C787ED} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /getopt.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {4BBAEAA1-9AD1-42D2-B6DC-7F73C4B3D238} 23 | GetOptTest 24 | Win32Proj 25 | 26 | 27 | 28 | DynamicLibrary 29 | Unicode 30 | v140 31 | 32 | 33 | DynamicLibrary 34 | Unicode 35 | v140 36 | 37 | 38 | DynamicLibrary 39 | Unicode 40 | true 41 | v140 42 | 43 | 44 | DynamicLibrary 45 | Unicode 46 | true 47 | v140 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | <_ProjectFileVersion>10.0.30319.1 67 | $(SolutionDir)$(Platform)\$(Configuration)\ 68 | $(SolutionDir)$(Platform)\$(Configuration)\ 69 | false 70 | false 71 | true 72 | true 73 | getopt 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | MaxSpeed 82 | true 83 | WIN32;NDEBUG;_CONSOLE;EXPORTS_GETOPT;%(PreprocessorDefinitions) 84 | MultiThreadedDLL 85 | true 86 | 87 | 88 | Level3 89 | ProgramDatabase 90 | 91 | 92 | $(OutDir)\getopt.dll 93 | true 94 | Console 95 | true 96 | true 97 | MachineX86 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | MaxSpeed 111 | true 112 | WIN32;NDEBUG;_CONSOLE;EXPORTS_GETOPT;%(PreprocessorDefinitions) 113 | MultiThreadedDLL 114 | true 115 | 116 | 117 | Level3 118 | ProgramDatabase 119 | 120 | 121 | $(OutDir)\getopt.dll 122 | true 123 | Console 124 | true 125 | true 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | Disabled 139 | WIN32;_DEBUG;_CONSOLE;EXPORTS_GETOPT;%(PreprocessorDefinitions) 140 | true 141 | EnableFastChecks 142 | MultiThreadedDebugDLL 143 | 144 | 145 | Level4 146 | EditAndContinue 147 | 148 | 149 | $(OutDir)\getopt.dll 150 | true 151 | Console 152 | MachineX86 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | Disabled 166 | WIN32;_DEBUG;_CONSOLE;EXPORTS_GETOPT;%(PreprocessorDefinitions) 167 | EnableFastChecks 168 | MultiThreadedDebugDLL 169 | 170 | 171 | Level4 172 | ProgramDatabase 173 | 174 | 175 | $(OutDir)\getopt.dll 176 | true 177 | Console 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | --------------------------------------------------------------------------------