From 532aec52d4157c25768c774727a581eab1eeecbb Mon Sep 17 00:00:00 2001 From: Banana Date: Sun, 6 Aug 2023 22:06:39 +0200 Subject: [PATCH] adding utf8filenamecheck to the c tools --- c/README | 17 + c/utf8filenamecheck/linux/COPYING | 674 ++ c/utf8filenamecheck/linux/Makefile | 9 + c/utf8filenamecheck/linux/README | 18 + c/utf8filenamecheck/linux/USES | 1 + .../linux/bin/utf8filenamecheck | Bin 0 -> 16720 bytes .../linux/simdutf8check/simdutf8check.h | 457 ++ c/utf8filenamecheck/linux/utf8filenamecheck.c | 148 + c/utf8filenamecheck/windows/COPYING | 674 ++ c/utf8filenamecheck/windows/README | 35 + c/utf8filenamecheck/windows/USES | 2 + c/utf8filenamecheck/windows/argtable/LICENSE | 175 + .../windows/argtable/README.md | 203 + .../windows/argtable/argtable3.c | 5860 +++++++++++++++++ .../windows/argtable/argtable3.h | 277 + .../windows/argtable/examples/CMakeLists.txt | 46 + .../windows/argtable/examples/echo.c | 128 + .../windows/argtable/examples/ls.c | 326 + .../windows/argtable/examples/multisyntax.c | 239 + .../windows/argtable/examples/mv.c | 179 + .../windows/argtable/examples/myprog.c | 147 + .../windows/argtable/examples/myprog_C89.c | 165 + .../windows/argtable/examples/testargtable3.c | 58 + .../windows/argtable/examples/uname.c | 137 + .../windows/argtable/tests/CMakeLists.txt | 89 + .../windows/argtable/tests/CuTest.c | 325 + .../windows/argtable/tests/CuTest.h | 104 + .../argtable/tests/argtable3_private.h | 230 + .../windows/argtable/tests/testall.c | 76 + .../windows/argtable/tests/testargcmd.c | 92 + .../windows/argtable/tests/testargdate.c | 377 ++ .../windows/argtable/tests/testargdbl.c | 451 ++ .../windows/argtable/tests/testargdstr.c | 123 + .../windows/argtable/tests/testargfile.c | 752 +++ .../windows/argtable/tests/testarghashtable.c | 276 + .../windows/argtable/tests/testargint.c | 2018 ++++++ .../windows/argtable/tests/testarglit.c | 538 ++ .../windows/argtable/tests/testargrex.c | 299 + .../windows/argtable/tests/testargstr.c | 531 ++ .../windows/bin/utf8filenamecheck.exe | Bin 0 -> 591589 bytes c/utf8filenamecheck/windows/makefile.bat | 18 + c/utf8filenamecheck/windows/notes.txt | 5 + .../windows/simdutf8check/simdutf8check.h | 457 ++ .../windows/utf8filenamecheck.c | 147 + 44 files changed, 16883 insertions(+) create mode 100644 c/README create mode 100644 c/utf8filenamecheck/linux/COPYING create mode 100644 c/utf8filenamecheck/linux/Makefile create mode 100644 c/utf8filenamecheck/linux/README create mode 100644 c/utf8filenamecheck/linux/USES create mode 100755 c/utf8filenamecheck/linux/bin/utf8filenamecheck create mode 100644 c/utf8filenamecheck/linux/simdutf8check/simdutf8check.h create mode 100644 c/utf8filenamecheck/linux/utf8filenamecheck.c create mode 100644 c/utf8filenamecheck/windows/COPYING create mode 100644 c/utf8filenamecheck/windows/README create mode 100644 c/utf8filenamecheck/windows/USES create mode 100644 c/utf8filenamecheck/windows/argtable/LICENSE create mode 100644 c/utf8filenamecheck/windows/argtable/README.md create mode 100644 c/utf8filenamecheck/windows/argtable/argtable3.c create mode 100644 c/utf8filenamecheck/windows/argtable/argtable3.h create mode 100644 c/utf8filenamecheck/windows/argtable/examples/CMakeLists.txt create mode 100644 c/utf8filenamecheck/windows/argtable/examples/echo.c create mode 100644 c/utf8filenamecheck/windows/argtable/examples/ls.c create mode 100644 c/utf8filenamecheck/windows/argtable/examples/multisyntax.c create mode 100644 c/utf8filenamecheck/windows/argtable/examples/mv.c create mode 100644 c/utf8filenamecheck/windows/argtable/examples/myprog.c create mode 100644 c/utf8filenamecheck/windows/argtable/examples/myprog_C89.c create mode 100644 c/utf8filenamecheck/windows/argtable/examples/testargtable3.c create mode 100644 c/utf8filenamecheck/windows/argtable/examples/uname.c create mode 100644 c/utf8filenamecheck/windows/argtable/tests/CMakeLists.txt create mode 100644 c/utf8filenamecheck/windows/argtable/tests/CuTest.c create mode 100644 c/utf8filenamecheck/windows/argtable/tests/CuTest.h create mode 100644 c/utf8filenamecheck/windows/argtable/tests/argtable3_private.h create mode 100644 c/utf8filenamecheck/windows/argtable/tests/testall.c create mode 100644 c/utf8filenamecheck/windows/argtable/tests/testargcmd.c create mode 100644 c/utf8filenamecheck/windows/argtable/tests/testargdate.c create mode 100644 c/utf8filenamecheck/windows/argtable/tests/testargdbl.c create mode 100644 c/utf8filenamecheck/windows/argtable/tests/testargdstr.c create mode 100644 c/utf8filenamecheck/windows/argtable/tests/testargfile.c create mode 100644 c/utf8filenamecheck/windows/argtable/tests/testarghashtable.c create mode 100644 c/utf8filenamecheck/windows/argtable/tests/testargint.c create mode 100644 c/utf8filenamecheck/windows/argtable/tests/testarglit.c create mode 100644 c/utf8filenamecheck/windows/argtable/tests/testargrex.c create mode 100644 c/utf8filenamecheck/windows/argtable/tests/testargstr.c create mode 100644 c/utf8filenamecheck/windows/bin/utf8filenamecheck.exe create mode 100644 c/utf8filenamecheck/windows/makefile.bat create mode 100644 c/utf8filenamecheck/windows/notes.txt create mode 100644 c/utf8filenamecheck/windows/simdutf8check/simdutf8check.h create mode 100644 c/utf8filenamecheck/windows/utf8filenamecheck.c diff --git a/c/README b/c/README new file mode 100644 index 0000000..3e80216 --- /dev/null +++ b/c/README @@ -0,0 +1,17 @@ +# Klimbim Software collection, A bag full of things +# Copyright (C) 2011-2023 Johannes 'Banana' Keßler +# +# 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 3 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, see . + +A selection of C tools and examples \ No newline at end of file diff --git a/c/utf8filenamecheck/linux/COPYING b/c/utf8filenamecheck/linux/COPYING new file mode 100644 index 0000000..80e659d --- /dev/null +++ b/c/utf8filenamecheck/linux/COPYING @@ -0,0 +1,674 @@ +GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 3 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, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. \ No newline at end of file diff --git a/c/utf8filenamecheck/linux/Makefile b/c/utf8filenamecheck/linux/Makefile new file mode 100644 index 0000000..a1f91c7 --- /dev/null +++ b/c/utf8filenamecheck/linux/Makefile @@ -0,0 +1,9 @@ +CC=gcc +CFLAGS=-O2 --machine-arch=native -pipe -Wall +LIBS= + +# https://github.com/adamretter/utf8-validator-c +CFLAGS+=-Isimdutf8check/ + +all: utf8filenamecheck.c + $(CC) $(CFLAGS) -o bin/utf8filenamecheck utf8filenamecheck.c $(LIBS) \ No newline at end of file diff --git a/c/utf8filenamecheck/linux/README b/c/utf8filenamecheck/linux/README new file mode 100644 index 0000000..5cacc7d --- /dev/null +++ b/c/utf8filenamecheck/linux/README @@ -0,0 +1,18 @@ +# Klimbim Software collection, A bag full of things +# Copyright (C) 2011-2023 Johannes 'Banana' Keßler +# +# 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 3 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, see . + +# utf8filenamecheck +Small windows C tool to check if paths in a folder are utf-8 formatted \ No newline at end of file diff --git a/c/utf8filenamecheck/linux/USES b/c/utf8filenamecheck/linux/USES new file mode 100644 index 0000000..6aebec2 --- /dev/null +++ b/c/utf8filenamecheck/linux/USES @@ -0,0 +1 @@ +https://github.com/adamretter/utf8-validator-c \ No newline at end of file diff --git a/c/utf8filenamecheck/linux/bin/utf8filenamecheck b/c/utf8filenamecheck/linux/bin/utf8filenamecheck new file mode 100755 index 0000000000000000000000000000000000000000..8abae88c69c2eeabde53088583a8765b9066b536 GIT binary patch literal 16720 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 +#include +#include +#include +#include +/* + * legal utf-8 byte sequence + * http://www.unicode.org/versions/Unicode6.0.0/ch03.pdf - page 94 + * + * Code Points 1st 2s 3s 4s + * U+0000..U+007F 00..7F + * U+0080..U+07FF C2..DF 80..BF + * U+0800..U+0FFF E0 A0..BF 80..BF + * U+1000..U+CFFF E1..EC 80..BF 80..BF + * U+D000..U+D7FF ED 80..9F 80..BF + * U+E000..U+FFFF EE..EF 80..BF 80..BF + * U+10000..U+3FFFF F0 90..BF 80..BF 80..BF + * U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF + * U+100000..U+10FFFF F4 80..8F 80..BF 80..BF + * + */ + +// all byte values must be no larger than 0xF4 +static inline void checkSmallerThan0xF4(__m128i current_bytes, + __m128i *has_error) { + // unsigned, saturates to 0 below max + *has_error = _mm_or_si128(*has_error, + _mm_subs_epu8(current_bytes, _mm_set1_epi8(0xF4))); +} + +static inline __m128i continuationLengths(__m128i high_nibbles) { + return _mm_shuffle_epi8( + _mm_setr_epi8(1, 1, 1, 1, 1, 1, 1, 1, // 0xxx (ASCII) + 0, 0, 0, 0, // 10xx (continuation) + 2, 2, // 110x + 3, // 1110 + 4), // 1111, next should be 0 (not checked here) + high_nibbles); +} + +static inline __m128i carryContinuations(__m128i initial_lengths, + __m128i previous_carries) { + + __m128i right1 = + _mm_subs_epu8(_mm_alignr_epi8(initial_lengths, previous_carries, 16 - 1), + _mm_set1_epi8(1)); + __m128i sum = _mm_add_epi8(initial_lengths, right1); + + __m128i right2 = _mm_subs_epu8(_mm_alignr_epi8(sum, previous_carries, 16 - 2), + _mm_set1_epi8(2)); + return _mm_add_epi8(sum, right2); +} + +static inline void checkContinuations(__m128i initial_lengths, __m128i carries, + __m128i *has_error) { + + // overlap || underlap + // carry > length && length > 0 || !(carry > length) && !(length > 0) + // (carries > length) == (lengths > 0) + __m128i overunder = + _mm_cmpeq_epi8(_mm_cmpgt_epi8(carries, initial_lengths), + _mm_cmpgt_epi8(initial_lengths, _mm_setzero_si128())); + + *has_error = _mm_or_si128(*has_error, overunder); +} + +// when 0xED is found, next byte must be no larger than 0x9F +// when 0xF4 is found, next byte must be no larger than 0x8F +// next byte must be continuation, ie sign bit is set, so signed < is ok +static inline void checkFirstContinuationMax(__m128i current_bytes, + __m128i off1_current_bytes, + __m128i *has_error) { + __m128i maskED = _mm_cmpeq_epi8(off1_current_bytes, _mm_set1_epi8(0xED)); + __m128i maskF4 = _mm_cmpeq_epi8(off1_current_bytes, _mm_set1_epi8(0xF4)); + + __m128i badfollowED = + _mm_and_si128(_mm_cmpgt_epi8(current_bytes, _mm_set1_epi8(0x9F)), maskED); + __m128i badfollowF4 = + _mm_and_si128(_mm_cmpgt_epi8(current_bytes, _mm_set1_epi8(0x8F)), maskF4); + + *has_error = _mm_or_si128(*has_error, _mm_or_si128(badfollowED, badfollowF4)); +} + +// map off1_hibits => error condition +// hibits off1 cur +// C => < C2 && true +// E => < E1 && < A0 +// F => < F1 && < 90 +// else false && false +static inline void checkOverlong(__m128i current_bytes, + __m128i off1_current_bytes, __m128i hibits, + __m128i previous_hibits, __m128i *has_error) { + __m128i off1_hibits = _mm_alignr_epi8(hibits, previous_hibits, 16 - 1); + __m128i initial_mins = _mm_shuffle_epi8( + _mm_setr_epi8(-128, -128, -128, -128, -128, -128, -128, -128, -128, -128, + -128, -128, // 10xx => false + 0xC2, -128, // 110x + 0xE1, // 1110 + 0xF1), + off1_hibits); + + __m128i initial_under = _mm_cmpgt_epi8(initial_mins, off1_current_bytes); + + __m128i second_mins = _mm_shuffle_epi8( + _mm_setr_epi8(-128, -128, -128, -128, -128, -128, -128, -128, -128, -128, + -128, -128, // 10xx => false + 127, 127, // 110x => true + 0xA0, // 1110 + 0x90), + off1_hibits); + __m128i second_under = _mm_cmpgt_epi8(second_mins, current_bytes); + *has_error = + _mm_or_si128(*has_error, _mm_and_si128(initial_under, second_under)); +} + +struct processed_utf_bytes { + __m128i rawbytes; + __m128i high_nibbles; + __m128i carried_continuations; +}; + +static inline void count_nibbles(__m128i bytes, + struct processed_utf_bytes *answer) { + answer->rawbytes = bytes; + answer->high_nibbles = + _mm_and_si128(_mm_srli_epi16(bytes, 4), _mm_set1_epi8(0x0F)); +} + +// check whether the current bytes are valid UTF-8 +// at the end of the function, previous gets updated +static struct processed_utf_bytes +checkUTF8Bytes(__m128i current_bytes, struct processed_utf_bytes *previous, + __m128i *has_error) { + struct processed_utf_bytes pb; + count_nibbles(current_bytes, &pb); + + checkSmallerThan0xF4(current_bytes, has_error); + + __m128i initial_lengths = continuationLengths(pb.high_nibbles); + + pb.carried_continuations = + carryContinuations(initial_lengths, previous->carried_continuations); + + checkContinuations(initial_lengths, pb.carried_continuations, has_error); + + __m128i off1_current_bytes = + _mm_alignr_epi8(pb.rawbytes, previous->rawbytes, 16 - 1); + checkFirstContinuationMax(current_bytes, off1_current_bytes, has_error); + + checkOverlong(current_bytes, off1_current_bytes, pb.high_nibbles, + previous->high_nibbles, has_error); + return pb; +} + +static bool validate_utf8_fast(const char *src, size_t len) { + size_t i = 0; + __m128i has_error = _mm_setzero_si128(); + struct processed_utf_bytes previous = {.rawbytes = _mm_setzero_si128(), + .high_nibbles = _mm_setzero_si128(), + .carried_continuations = + _mm_setzero_si128()}; + if (len >= 16) { + for (; i <= len - 16; i += 16) { + __m128i current_bytes = _mm_loadu_si128((const __m128i *)(src + i)); + previous = checkUTF8Bytes(current_bytes, &previous, &has_error); + } + } + + // last part + if (i < len) { + char buffer[16]; + memset(buffer, 0, 16); + memcpy(buffer, src + i, len - i); + __m128i current_bytes = _mm_loadu_si128((const __m128i *)(buffer)); + previous = checkUTF8Bytes(current_bytes, &previous, &has_error); + } else { + has_error = + _mm_or_si128(_mm_cmpgt_epi8(previous.carried_continuations, + _mm_setr_epi8(9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 1)), + has_error); + } + + return _mm_testz_si128(has_error, has_error); +} + +#ifdef __AVX2__ + +/*****************************/ +static inline __m256i push_last_byte_of_a_to_b(__m256i a, __m256i b) { + return _mm256_alignr_epi8(b, _mm256_permute2x128_si256(a, b, 0x21), 15); +} + +static inline __m256i push_last_2bytes_of_a_to_b(__m256i a, __m256i b) { + return _mm256_alignr_epi8(b, _mm256_permute2x128_si256(a, b, 0x21), 14); +} + +// all byte values must be no larger than 0xF4 +static inline void avxcheckSmallerThan0xF4(__m256i current_bytes, + __m256i *has_error) { + // unsigned, saturates to 0 below max + *has_error = _mm256_or_si256( + *has_error, _mm256_subs_epu8(current_bytes, _mm256_set1_epi8(0xF4))); +} + +static inline __m256i avxcontinuationLengths(__m256i high_nibbles) { + return _mm256_shuffle_epi8( + _mm256_setr_epi8(1, 1, 1, 1, 1, 1, 1, 1, // 0xxx (ASCII) + 0, 0, 0, 0, // 10xx (continuation) + 2, 2, // 110x + 3, // 1110 + 4, // 1111, next should be 0 (not checked here) + 1, 1, 1, 1, 1, 1, 1, 1, // 0xxx (ASCII) + 0, 0, 0, 0, // 10xx (continuation) + 2, 2, // 110x + 3, // 1110 + 4 // 1111, next should be 0 (not checked here) + ), + high_nibbles); +} + +static inline __m256i avxcarryContinuations(__m256i initial_lengths, + __m256i previous_carries) { + + __m256i right1 = _mm256_subs_epu8( + push_last_byte_of_a_to_b(previous_carries, initial_lengths), + _mm256_set1_epi8(1)); + __m256i sum = _mm256_add_epi8(initial_lengths, right1); + + __m256i right2 = _mm256_subs_epu8( + push_last_2bytes_of_a_to_b(previous_carries, sum), _mm256_set1_epi8(2)); + return _mm256_add_epi8(sum, right2); +} + +static inline void avxcheckContinuations(__m256i initial_lengths, + __m256i carries, __m256i *has_error) { + + // overlap || underlap + // carry > length && length > 0 || !(carry > length) && !(length > 0) + // (carries > length) == (lengths > 0) + __m256i overunder = _mm256_cmpeq_epi8( + _mm256_cmpgt_epi8(carries, initial_lengths), + _mm256_cmpgt_epi8(initial_lengths, _mm256_setzero_si256())); + + *has_error = _mm256_or_si256(*has_error, overunder); +} + +// when 0xED is found, next byte must be no larger than 0x9F +// when 0xF4 is found, next byte must be no larger than 0x8F +// next byte must be continuation, ie sign bit is set, so signed < is ok +static inline void avxcheckFirstContinuationMax(__m256i current_bytes, + __m256i off1_current_bytes, + __m256i *has_error) { + __m256i maskED = + _mm256_cmpeq_epi8(off1_current_bytes, _mm256_set1_epi8(0xED)); + __m256i maskF4 = + _mm256_cmpeq_epi8(off1_current_bytes, _mm256_set1_epi8(0xF4)); + + __m256i badfollowED = _mm256_and_si256( + _mm256_cmpgt_epi8(current_bytes, _mm256_set1_epi8(0x9F)), maskED); + __m256i badfollowF4 = _mm256_and_si256( + _mm256_cmpgt_epi8(current_bytes, _mm256_set1_epi8(0x8F)), maskF4); + + *has_error = + _mm256_or_si256(*has_error, _mm256_or_si256(badfollowED, badfollowF4)); +} + +// map off1_hibits => error condition +// hibits off1 cur +// C => < C2 && true +// E => < E1 && < A0 +// F => < F1 && < 90 +// else false && false +static inline void avxcheckOverlong(__m256i current_bytes, + __m256i off1_current_bytes, __m256i hibits, + __m256i previous_hibits, + __m256i *has_error) { + __m256i off1_hibits = push_last_byte_of_a_to_b(previous_hibits, hibits); + __m256i initial_mins = _mm256_shuffle_epi8( + _mm256_setr_epi8(-128, -128, -128, -128, -128, -128, -128, -128, -128, + -128, -128, -128, // 10xx => false + 0xC2, -128, // 110x + 0xE1, // 1110 + 0xF1, -128, -128, -128, -128, -128, -128, -128, -128, + -128, -128, -128, -128, // 10xx => false + 0xC2, -128, // 110x + 0xE1, // 1110 + 0xF1), + off1_hibits); + + __m256i initial_under = _mm256_cmpgt_epi8(initial_mins, off1_current_bytes); + + __m256i second_mins = _mm256_shuffle_epi8( + _mm256_setr_epi8(-128, -128, -128, -128, -128, -128, -128, -128, -128, + -128, -128, -128, // 10xx => false + 127, 127, // 110x => true + 0xA0, // 1110 + 0x90, -128, -128, -128, -128, -128, -128, -128, -128, + -128, -128, -128, -128, // 10xx => false + 127, 127, // 110x => true + 0xA0, // 1110 + 0x90), + off1_hibits); + __m256i second_under = _mm256_cmpgt_epi8(second_mins, current_bytes); + *has_error = _mm256_or_si256(*has_error, + _mm256_and_si256(initial_under, second_under)); +} + +struct avx_processed_utf_bytes { + __m256i rawbytes; + __m256i high_nibbles; + __m256i carried_continuations; +}; + +static inline void avx_count_nibbles(__m256i bytes, + struct avx_processed_utf_bytes *answer) { + answer->rawbytes = bytes; + answer->high_nibbles = + _mm256_and_si256(_mm256_srli_epi16(bytes, 4), _mm256_set1_epi8(0x0F)); +} + +// check whether the current bytes are valid UTF-8 +// at the end of the function, previous gets updated +static struct avx_processed_utf_bytes +avxcheckUTF8Bytes(__m256i current_bytes, + struct avx_processed_utf_bytes *previous, + __m256i *has_error) { + struct avx_processed_utf_bytes pb; + avx_count_nibbles(current_bytes, &pb); + + avxcheckSmallerThan0xF4(current_bytes, has_error); + + __m256i initial_lengths = avxcontinuationLengths(pb.high_nibbles); + + pb.carried_continuations = + avxcarryContinuations(initial_lengths, previous->carried_continuations); + + avxcheckContinuations(initial_lengths, pb.carried_continuations, has_error); + + __m256i off1_current_bytes = + push_last_byte_of_a_to_b(previous->rawbytes, pb.rawbytes); + avxcheckFirstContinuationMax(current_bytes, off1_current_bytes, has_error); + + avxcheckOverlong(current_bytes, off1_current_bytes, pb.high_nibbles, + previous->high_nibbles, has_error); + return pb; +} + +// check whether the current bytes are valid UTF-8 +// at the end of the function, previous gets updated +static struct avx_processed_utf_bytes +avxcheckUTF8Bytes_asciipath(__m256i current_bytes, + struct avx_processed_utf_bytes *previous, + __m256i *has_error) { + if (_mm256_testz_si256(current_bytes, + _mm256_set1_epi8(0x80))) { // fast ascii path + *has_error = _mm256_or_si256( + _mm256_cmpgt_epi8(previous->carried_continuations, + _mm256_setr_epi8(9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 1)), + *has_error); + return *previous; + } + + struct avx_processed_utf_bytes pb; + avx_count_nibbles(current_bytes, &pb); + + avxcheckSmallerThan0xF4(current_bytes, has_error); + + __m256i initial_lengths = avxcontinuationLengths(pb.high_nibbles); + + pb.carried_continuations = + avxcarryContinuations(initial_lengths, previous->carried_continuations); + + avxcheckContinuations(initial_lengths, pb.carried_continuations, has_error); + + __m256i off1_current_bytes = + push_last_byte_of_a_to_b(previous->rawbytes, pb.rawbytes); + avxcheckFirstContinuationMax(current_bytes, off1_current_bytes, has_error); + + avxcheckOverlong(current_bytes, off1_current_bytes, pb.high_nibbles, + previous->high_nibbles, has_error); + return pb; +} + +static bool validate_utf8_fast_avx_asciipath(const char *src, size_t len) { + size_t i = 0; + __m256i has_error = _mm256_setzero_si256(); + struct avx_processed_utf_bytes previous = { + .rawbytes = _mm256_setzero_si256(), + .high_nibbles = _mm256_setzero_si256(), + .carried_continuations = _mm256_setzero_si256()}; + if (len >= 32) { + for (; i <= len - 32; i += 32) { + __m256i current_bytes = _mm256_loadu_si256((const __m256i *)(src + i)); + previous = + avxcheckUTF8Bytes_asciipath(current_bytes, &previous, &has_error); + } + } + + // last part + if (i < len) { + char buffer[32]; + memset(buffer, 0, 32); + memcpy(buffer, src + i, len - i); + __m256i current_bytes = _mm256_loadu_si256((const __m256i *)(buffer)); + previous = avxcheckUTF8Bytes(current_bytes, &previous, &has_error); + } else { + has_error = _mm256_or_si256( + _mm256_cmpgt_epi8(previous.carried_continuations, + _mm256_setr_epi8(9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 1)), + has_error); + } + + return _mm256_testz_si256(has_error, has_error); +} + +static bool validate_utf8_fast_avx(const char *src, size_t len) { + size_t i = 0; + __m256i has_error = _mm256_setzero_si256(); + struct avx_processed_utf_bytes previous = { + .rawbytes = _mm256_setzero_si256(), + .high_nibbles = _mm256_setzero_si256(), + .carried_continuations = _mm256_setzero_si256()}; + if (len >= 32) { + for (; i <= len - 32; i += 32) { + __m256i current_bytes = _mm256_loadu_si256((const __m256i *)(src + i)); + previous = avxcheckUTF8Bytes(current_bytes, &previous, &has_error); + } + } + + // last part + if (i < len) { + char buffer[32]; + memset(buffer, 0, 32); + memcpy(buffer, src + i, len - i); + __m256i current_bytes = _mm256_loadu_si256((const __m256i *)(buffer)); + previous = avxcheckUTF8Bytes(current_bytes, &previous, &has_error); + } else { + has_error = _mm256_or_si256( + _mm256_cmpgt_epi8(previous.carried_continuations, + _mm256_setr_epi8(9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 1)), + has_error); + } + + return _mm256_testz_si256(has_error, has_error); +} + +#endif // __AVX2__ +#endif diff --git a/c/utf8filenamecheck/linux/utf8filenamecheck.c b/c/utf8filenamecheck/linux/utf8filenamecheck.c new file mode 100644 index 0000000..1a98014 --- /dev/null +++ b/c/utf8filenamecheck/linux/utf8filenamecheck.c @@ -0,0 +1,148 @@ +/** + * utf8filenamecheck Check if all the filenames in a fiven folder are UTF-8 + * Copyright (C) 2023 Johannes 'Banana' Keßler + * + * 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 3 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, see . + */ + +/** + * 2023 Small linux C tool to check if paths in a folder are utf-8 formatted + * Linux version + */ +// https://linux.die.net/man/3/nftw +#define _XOPEN_SOURCE 500 +#include +#include +#include +#include +#include + +// https://github.com/simdutf/simdutf +#include + +/** + * Commandline arguments + * see: https://www.gnu.org/software/libc/manual/html_node/Argp-Example-3.html#Argp-Example-3 + */ +const char *argp_program_version = "1.0"; +const char *argp_program_bug_address = "https://www.bananas-playground.net/"; +static char doc[] = "utf8filenamecheck. Small linux C tool to check if paths in a folder are utf-8 formatted."; +static char args_doc[] = "folder"; + +/* The options we understand. */ +static struct argp_option options[] = { + {"verbose",'v', 0, 0, "Produce verbose output" }, + {"quiet",'q', 0, 0, "Produce verbose output" }, + { 0 } +}; + +struct cmdArguments { + char *args[1]; + int verbose, quiet; +}; + +/* Parse a single option. */ +static error_t +parse_opt (int key, char *arg, struct argp_state *state) { + struct cmdArguments *arguments = state->input; + + switch (key) { + case 'v': + arguments->verbose = 1; + break; + case 'q': + arguments->quiet = 1; + break; + + case ARGP_KEY_ARG: + if (state->arg_num >= 1) + // Too many arguments. + argp_usage (state); + + arguments->args[state->arg_num] = arg; + break; + + case ARGP_KEY_END: + if (state->arg_num < 1) + /* Not enough arguments. */ + argp_usage (state); + break; + + default: + return ARGP_ERR_UNKNOWN; + } + + return 0; +} + +static struct argp argp = { options, parse_opt, args_doc, doc }; +struct cmdArguments arguments; + +/** + * the callback function for nftw + * https://linux.die.net/man/3/nftw + */ +static int nftw_callback(const char *fpath, + const struct stat *sb, + int tflag, + struct FTW *ftwbuf) { + if (strcmp(fpath, ".") == 0 || strcmp(fpath, "..") == 0) { + return 0; + } + + if(tflag == FTW_DNR) { + if(!arguments.quiet) printf("Can not read %s", fpath); + } + + bool result = validate_utf8_fast(fpath, strlen(fpath)); + if(result) { + if(!arguments.quiet) printf("%s OK \n", fpath); + } else { + printf("%s FAILED \n", fpath); + } + + // continue + return 0; +} + +/** + * main routine + */ +int main(int argc, char *argv[]) { + + /** + * command line argument parsing and default values + */ + arguments.verbose = 0; + arguments.quiet = 0; + + argp_parse (&argp, argc, argv, 0, 0, &arguments); + + if(arguments.verbose) { + printf ("Folder = %s\n" + "Verbose = %s\n" + "Quiet = %s\n", + arguments.args[0], + arguments.verbose ? "yes" : "no", + arguments.quiet ? "yes" : "no" + ); + } + + if (nftw(arguments.args[0], nftw_callback, 15, FTW_PHYS)== -1) { + perror("Reading dir failed"); + exit(EXIT_FAILURE); + } + + exit(EXIT_SUCCESS); +} \ No newline at end of file diff --git a/c/utf8filenamecheck/windows/COPYING b/c/utf8filenamecheck/windows/COPYING new file mode 100644 index 0000000..80e659d --- /dev/null +++ b/c/utf8filenamecheck/windows/COPYING @@ -0,0 +1,674 @@ +GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 3 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, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. \ No newline at end of file diff --git a/c/utf8filenamecheck/windows/README b/c/utf8filenamecheck/windows/README new file mode 100644 index 0000000..39abb8d --- /dev/null +++ b/c/utf8filenamecheck/windows/README @@ -0,0 +1,35 @@ +# Klimbim Software collection, A bag full of things +# Copyright (C) 2011-2023 Johannes 'Banana' Keßler +# +# 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 3 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, see . + +# utf8filenamecheck +Small windows C tool to check if paths in a folder are utf-8 formatted + +# Uses +- https://www.argtable.org : Argument parsing (argtable-3.1.5-amalgamation) +- https://github.com/adamretter/utf8-validator-c : Check if a string is utf-8 + +# WARNING +This is a very simple, with limited experience written, windows C program. +Use at own risk and feel free to improve. + +# How to build +- gcc from https://jmeubank.github.io/tdm-gcc/ (build with tdm64-gcc-9.2.0) +Run the makefile.bat in a cmd terminal. +Resulting utf8filenamecheck.exe is in bin/ directory. + +# How to use +Run in a terminal `utf8filenamecheck.exe c:\some\dir` +Run utf8filenamecheck.exe --help to see its options. \ No newline at end of file diff --git a/c/utf8filenamecheck/windows/USES b/c/utf8filenamecheck/windows/USES new file mode 100644 index 0000000..84ddd54 --- /dev/null +++ b/c/utf8filenamecheck/windows/USES @@ -0,0 +1,2 @@ +https://www.argtable.org +https://github.com/adamretter/utf8-validator-c \ No newline at end of file diff --git a/c/utf8filenamecheck/windows/argtable/LICENSE b/c/utf8filenamecheck/windows/argtable/LICENSE new file mode 100644 index 0000000..b7853f1 --- /dev/null +++ b/c/utf8filenamecheck/windows/argtable/LICENSE @@ -0,0 +1,175 @@ +Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of STEWART HEITMANN nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +NetBSD getopt library +===================== + +Copyright (c) 2000 The NetBSD Foundation, Inc. +All rights reserved. + +This code is derived from software contributed to The NetBSD Foundation +by Dieter Baron and Thomas Klausner. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. All advertising materials mentioning features or use of this software + must display the following acknowledgement: + This product includes software developed by the NetBSD + Foundation, Inc. and its contributors. +4. Neither the name of The NetBSD Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + + +Tcl library +=========== + +This software is copyrighted by the Regents of the University of +California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState +Corporation and other parties. The following terms apply to all files +associated with the software unless explicitly disclaimed in +individual files. + +The authors hereby grant permission to use, copy, modify, distribute, +and license this software and its documentation for any purpose, provided +that existing copyright notices are retained in all copies and that this +notice is included verbatim in any distributions. No written agreement, +license, or royalty fee is required for any of the authorized uses. +Modifications to this software may be copyrighted by their authors +and need not follow the licensing terms described here, provided that +the new terms are clearly indicated on the first page of each file where +they apply. + +IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY +FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES +ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY +DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE +IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE +NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR +MODIFICATIONS. + +GOVERNMENT USE: If you are acquiring this software on behalf of the +U.S. government, the Government shall have only "Restricted Rights" +in the software and related documentation as defined in the Federal +Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you +are acquiring the software on behalf of the Department of Defense, the +software shall be classified as "Commercial Computer Software" and the +Government shall have only "Restricted Rights" as defined in Clause +252.227-7014 (b) (3) of DFARs. Notwithstanding the foregoing, the +authors grant the U.S. Government and others acting in its behalf +permission to use and distribute the software in accordance with the +terms specified in this license. + + +C Hash Table library +==================== + +Copyright (c) 2002, Christopher Clark +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +* Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +* Neither the name of the original author; nor the names of any contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +The Better String library +========================= + +Copyright (c) 2014, Paul Hsieh +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of bstrlib nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/c/utf8filenamecheck/windows/argtable/README.md b/c/utf8filenamecheck/windows/argtable/README.md new file mode 100644 index 0000000..8a71ba8 --- /dev/null +++ b/c/utf8filenamecheck/windows/argtable/README.md @@ -0,0 +1,203 @@ +[![Build Status](https://travis-ci.org/argtable/argtable3.svg?branch=master)](https://travis-ci.org/argtable/argtable3) + + +Introduction of Argtable3 +========================= + +**Argtable3** is an open source ANSI C library that parses GNU-style +command-line options. It simplifies command-line parsing by defining a +declarative-style API that you can use to specify what your command-line syntax +looks like. Argtable3 will automatically generate consistent error handling +logic and textual descriptions of the command line syntax, which are essential +but tedious to implement for a robust CLI program. + + +Quick Start +----------- + +> We no longer provide the amalgamation source code (`argtable3.c` and +> `argtable3.h`) in the source code repository. You can get the amalgamation +> distribution either from the release page (`argtable-3.x.x-amalgamation.zip`), +> or generate the distribution yourself by using the generator under the `tools` +> directory: +> +> 1. Navigate to the `tools` directory. +> 2. Run `./build dist`, which will generate the distribution under the `/dist` +> directory. + + +Argtable3 is a single-file ANSI-C library. All you have to do is adding +`argtable3.c` to your projects, and including `argtable3.h` in your source code. + +To build the library, examples, and unit tests, use CMake to generate +out-of-source build: + +* If you use GCC (Linux, MacOSX, MinGW, Cygwin), run: + + ``` + $ mkdir build + $ cd build + $ cmake -DCMAKE_BUILD_TYPE=Debug .. + $ make + $ make test + ``` + + Makefile-based generators in CMake only support one configuration at a time, + so you need to specify `CMAKE_BUILD_TYPE` to `Debug`, `Release`, `MinSizeRel`, + or `RelWithDebInfo`. To build multiple configurations, you need to create a + build directory for each configuraiton. + + To cleanup, run `make clean` or remove the build directory: + + ``` + $ rm -rf build + ``` + +* If you use Microsoft Visual C++ compiler, run: + + ``` + $ mkdir build + $ cd build + $ cmake -G "Visual Studio 15 2017 Win64" .. + $ cmake --build . --config Debug + $ ctest -C Debug + ``` + + You can also use Visual Studio 2017 IDE to open the generated solution. To + cleanup, just remove the `build` directory. + + +To build a tagged version, go to the project root directory, and use the +`Makefile` in the project root folder to check out the specified version: + + ``` + $ make taglist + Available TAGs: + v3.1.1.432a160 + $ make co TAG=v3.1.1.432a160 + $ cd .tags/v3.1.1.432a160 + $ mkdir build + $ cd build + $ cmake .. + $ make + $ make test + ``` + +You will find the shared library (or Windows DLL), static library, and the +amalgamation distribution under the build directory. + + +Documentation and Examples +-------------------------- + +To learn how to use the Argtable3 API, you can see the documentation on the web +site, or examples in the `examples` folder. + + +Unit Tests +---------- + +Argtable3 is a BSD-licensed open source library, so you can modify the library +anyway you want. However, before committing your code to your own repository or +the Argtable3 official repository, please make sure your changes won't cause any +compiler warning and can pass the unit tests included in the distribution. + +To build and test each configuration (`Debug`, `Release`, `MinSizeRel`, +`RelWithDebInfo`), you can run CMake and CTest on all supported platforms: + +``` +$ mkdir build_debug && cd build_debug +$ cmake -DCMAKE_BUILD_TYPE=Debug .. +$ cmake --build . --config Debug +$ ctest -C Debug + +$ cd .. && mkdir build_release && cd build_release +$ cmake -DCMAKE_BUILD_TYPE=Release .. +$ cmake --build . --config Release +$ ctest -C Release + +$ cd .. && mkdir build_minsizerel && cd build_minsizerel +$ cmake -DCMAKE_BUILD_TYPE=MinSizeRel .. +$ cmake --build . --config MinSizeRel +$ ctest -C MinSizeRel + +$ cd .. && mkdir build_relwithdebinfo && cd build_relwithdebinfo +$ cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo .. +$ cmake --build . --config RelWithDebInfo +$ ctest -C RelWithDebInfo +``` + + +Authors +------- + +Argtable is Copyright (C) 1998-2001,2003-2011 Stewart Heitmann. +Parts are Copyright (C) 1989-1994, 1996-1999, 2001, 2003 + Free Software Foundation, Inc. + +Argtable was written by Stewart Heitmann + +Argtable is now maintained by Tom G. Huang +The project homepage of argtable 3.x is http://www.argtable.org +The project homepage of argtable 2.x is http://argtable.sourceforge.net/ + +Here is a list of contributors who have helped to improve argtable: + +- **Nina Clemson**: Editing the original argtable-1.0 documentation. +- **Livio Bertacco**: For bug fixes and the argtable-2.x Visual C++ Makefiles. +- **Justin Dearing**: For bug fixes and Windows DLL support, plus code support for the Open Watcom compiler and help with the Mac OS X configuration. +- **Asa Packer**: Contributing bug fixes and upgrades to the Visual C++ Makefiles. +- **Danilo Cicerone**: For the Italian translation of "Introduction to Argtable-2x" on http://www.digitazero.org. +- **Uli Fouquet**: For configuration patches and documentation related to cross-compiling argtable from Unix to Windows, as well as providing the arg_print_glossary_gnu function. +- **Shachar Shemesh**: For Debian package integration and kick-starting the migration to automake/autoconf. +- **Jasper Lievisse Adriaanse**: Maintaining the argtable package in OpenBSD ports. +- **Ulrich Mohr**: For bug fixes relating to Texas Instrument DSP platforms. +- **John Vickers**: For bug fixes relating to Solaris/Motorola platforms. +- **Steve O'Neil**: For bug fixes relating to Solaris/Motorola platforms. +- **Lori A. Pritchett-Sheats**: Fixing a makefile bug relating to "make dist". +- **Paolo Bormida**: For instructions on building argtable with date and regex support on Windows. +- **Michel Valin**: For bug fixes relating to the configure scripts on IBM AIX platforms and instructions on compiling the example code under AIX. +- **Steve Christensen**: Providing prebuilt packages for SPARC/Solaris and x86/Solaris platforms on www.sunfreeware.com. +- **Jess Portnoy**: Reworking the rpm package and integrating argtable into Fedora Linux. +- **Michael Brown**: Incorporating support for pkg-config into the autoconf scripts. +- **Alexander Lindert**: For extensions to the parser to support hex, octal and binary integer formats as well as KB/MB/GB suffixes. +- **Rob Zaborowski**: Providing build configuration files for CMake. +- **Moczik Gabor**: For bug fixes relating to the parsing of filepaths and filename extensions. + +Argtable 2.x uses `getopt` from GNU, which is LGPL licensed. In order to switch to BSD, we replaced GNU `getopt` with NetBSD `getopt`. We really appreciate this high quality library that lays the foundation of Argtable 3.x and here is its copyright notice: + +``` +Copyright (c) 2000 The NetBSD Foundation, Inc. +All rights reserved. + +This code is derived from software contributed to The NetBSD Foundation +by Dieter Baron and Thomas Klausner. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. All advertising materials mentioning features or use of this software + must display the following acknowledgement: + This product includes software developed by the NetBSD + Foundation, Inc. and its contributors. +4. Neither the name of The NetBSD Foundation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS +``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS +BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. +``` diff --git a/c/utf8filenamecheck/windows/argtable/argtable3.c b/c/utf8filenamecheck/windows/argtable/argtable3.c new file mode 100644 index 0000000..e0ab1c5 --- /dev/null +++ b/c/utf8filenamecheck/windows/argtable/argtable3.c @@ -0,0 +1,5860 @@ +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include "argtable3.h" + +#define ARG_AMALGAMATION + +/******************************************************************************* + * argtable3_private: Declares private types, constants, and interfaces + * + * This file is part of the argtable3 library. + * + * Copyright (C) 2013-2019 Tom G. Huang + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#ifndef ARG_UTILS_H +#define ARG_UTILS_H + +#include + +#define ARG_ENABLE_TRACE 0 +#define ARG_ENABLE_LOG 1 + +#ifdef __cplusplus +extern "C" { +#endif + +enum { ARG_ERR_MINCOUNT = 1, ARG_ERR_MAXCOUNT, ARG_ERR_BADINT, ARG_ERR_OVERFLOW, ARG_ERR_BADDOUBLE, ARG_ERR_BADDATE, ARG_ERR_REGNOMATCH }; + +typedef void(arg_panicfn)(const char* fmt, ...); + +#if defined(_MSC_VER) +#define ARG_TRACE(x) \ + __pragma(warning(push)) __pragma(warning(disable : 4127)) do { \ + if (ARG_ENABLE_TRACE) \ + dbg_printf x; \ + } \ + while (0) \ + __pragma(warning(pop)) + +#define ARG_LOG(x) \ + __pragma(warning(push)) __pragma(warning(disable : 4127)) do { \ + if (ARG_ENABLE_LOG) \ + dbg_printf x; \ + } \ + while (0) \ + __pragma(warning(pop)) +#else +#define ARG_TRACE(x) \ + do { \ + if (ARG_ENABLE_TRACE) \ + dbg_printf x; \ + } while (0) + +#define ARG_LOG(x) \ + do { \ + if (ARG_ENABLE_LOG) \ + dbg_printf x; \ + } while (0) +#endif + +extern void dbg_printf(const char* fmt, ...); +extern void arg_set_panic(arg_panicfn* proc); +extern void* xmalloc(size_t size); +extern void* xcalloc(size_t count, size_t size); +extern void* xrealloc(void* ptr, size_t size); +extern void xfree(void* ptr); + +struct arg_hashtable_entry { + void *k, *v; + unsigned int h; + struct arg_hashtable_entry* next; +}; + +typedef struct arg_hashtable { + unsigned int tablelength; + struct arg_hashtable_entry** table; + unsigned int entrycount; + unsigned int loadlimit; + unsigned int primeindex; + unsigned int (*hashfn)(const void* k); + int (*eqfn)(const void* k1, const void* k2); +} arg_hashtable_t; + +/** + * @brief Create a hash table. + * + * @param minsize minimum initial size of hash table + * @param hashfn function for hashing keys + * @param eqfn function for determining key equality + * @return newly created hash table or NULL on failure + */ +arg_hashtable_t* arg_hashtable_create(unsigned int minsize, unsigned int (*hashfn)(const void*), int (*eqfn)(const void*, const void*)); + +/** + * @brief This function will cause the table to expand if the insertion would take + * the ratio of entries to table size over the maximum load factor. + * + * This function does not check for repeated insertions with a duplicate key. + * The value returned when using a duplicate key is undefined -- when + * the hash table changes size, the order of retrieval of duplicate key + * entries is reversed. + * If in doubt, remove before insert. + * + * @param h the hash table to insert into + * @param k the key - hash table claims ownership and will free on removal + * @param v the value - does not claim ownership + * @return non-zero for successful insertion + */ +void arg_hashtable_insert(arg_hashtable_t* h, void* k, void* v); + +#define ARG_DEFINE_HASHTABLE_INSERT(fnname, keytype, valuetype) \ + int fnname(arg_hashtable_t* h, keytype* k, valuetype* v) { return arg_hashtable_insert(h, k, v); } + +/** + * @brief Search the specified key in the hash table. + * + * @param h the hash table to search + * @param k the key to search for - does not claim ownership + * @return the value associated with the key, or NULL if none found + */ +void* arg_hashtable_search(arg_hashtable_t* h, const void* k); + +#define ARG_DEFINE_HASHTABLE_SEARCH(fnname, keytype, valuetype) \ + valuetype* fnname(arg_hashtable_t* h, keytype* k) { return (valuetype*)(arg_hashtable_search(h, k)); } + +/** + * @brief Remove the specified key from the hash table. + * + * @param h the hash table to remove the item from + * @param k the key to search for - does not claim ownership + */ +void arg_hashtable_remove(arg_hashtable_t* h, const void* k); + +#define ARG_DEFINE_HASHTABLE_REMOVE(fnname, keytype, valuetype) \ + valuetype* fnname(arg_hashtable_t* h, keytype* k) { return (valuetype*)(arg_hashtable_remove(h, k)); } + +/** + * @brief Return the number of keys in the hash table. + * + * @param h the hash table + * @return the number of items stored in the hash table + */ +unsigned int arg_hashtable_count(arg_hashtable_t* h); + +/** + * @brief Change the value associated with the key. + * + * function to change the value associated with a key, where there already + * exists a value bound to the key in the hash table. + * Source due to Holger Schemel. + * + * @name hashtable_change + * @param h the hash table + * @param key + * @param value + */ +int arg_hashtable_change(arg_hashtable_t* h, void* k, void* v); + +/** + * @brief Free the hash table and the memory allocated for each key-value pair. + * + * @param h the hash table + * @param free_values whether to call 'free' on the remaining values + */ +void arg_hashtable_destroy(arg_hashtable_t* h, int free_values); + +typedef struct arg_hashtable_itr { + arg_hashtable_t* h; + struct arg_hashtable_entry* e; + struct arg_hashtable_entry* parent; + unsigned int index; +} arg_hashtable_itr_t; + +arg_hashtable_itr_t* arg_hashtable_itr_create(arg_hashtable_t* h); + +void arg_hashtable_itr_destroy(arg_hashtable_itr_t* itr); + +/** + * @brief Return the value of the (key,value) pair at the current position. + */ +extern void* arg_hashtable_itr_key(arg_hashtable_itr_t* i); + +/** + * @brief Return the value of the (key,value) pair at the current position. + */ +extern void* arg_hashtable_itr_value(arg_hashtable_itr_t* i); + +/** + * @brief Advance the iterator to the next element. Returns zero if advanced to end of table. + */ +int arg_hashtable_itr_advance(arg_hashtable_itr_t* itr); + +/** + * @brief Remove current element and advance the iterator to the next element. + */ +int arg_hashtable_itr_remove(arg_hashtable_itr_t* itr); + +/** + * @brief Search and overwrite the supplied iterator, to point to the entry matching the supplied key. + * + * @return Zero if not found. + */ +int arg_hashtable_itr_search(arg_hashtable_itr_t* itr, arg_hashtable_t* h, void* k); + +#define ARG_DEFINE_HASHTABLE_ITERATOR_SEARCH(fnname, keytype) \ + int fnname(arg_hashtable_itr_t* i, arg_hashtable_t* h, keytype* k) { return (arg_hashtable_iterator_search(i, h, k)); } + +#ifdef __cplusplus +} +#endif + +#endif +/******************************************************************************* + * arg_utils: Implements memory, panic, and other utility functions + * + * This file is part of the argtable3 library. + * + * Copyright (C) 2013-2019 Tom G. Huang + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include "argtable3.h" + +#ifndef ARG_AMALGAMATION +#include "argtable3_private.h" +#endif + +#include +#include +#include +#include + +static void panic(const char* fmt, ...); +static arg_panicfn* s_panic = panic; + +void dbg_printf(const char* fmt, ...) { + va_list args; + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); +} + +static void panic(const char* fmt, ...) { + va_list args; + char* s; + + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4996) +#endif + s = getenv("EF_DUMPCORE"); +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + + if (s != NULL && *s != '\0') { + abort(); + } else { + exit(EXIT_FAILURE); + } +} + +void arg_set_panic(arg_panicfn* proc) { + s_panic = proc; +} + +void* xmalloc(size_t size) { + void* ret = malloc(size); + if (!ret) { + s_panic("Out of memory!\n"); + } + return ret; +} + +void* xcalloc(size_t count, size_t size) { + size_t allocated_count = count && size ? count : 1; + size_t allocated_size = count && size ? size : 1; + void* ret = calloc(allocated_count, allocated_size); + if (!ret) { + s_panic("Out of memory!\n"); + } + return ret; +} + +void* xrealloc(void* ptr, size_t size) { + size_t allocated_size = size ? size : 1; + void* ret = realloc(ptr, allocated_size); + if (!ret) { + s_panic("Out of memory!\n"); + } + return ret; +} + +void xfree(void* ptr) { + free(ptr); +} + +static void merge(void* data, int esize, int i, int j, int k, arg_comparefn* comparefn) { + char* a = (char*)data; + char* m; + int ipos, jpos, mpos; + + /* Initialize the counters used in merging. */ + ipos = i; + jpos = j + 1; + mpos = 0; + + /* Allocate storage for the merged elements. */ + m = (char*)xmalloc(esize * ((k - i) + 1)); + + /* Continue while either division has elements to merge. */ + while (ipos <= j || jpos <= k) { + if (ipos > j) { + /* The left division has no more elements to merge. */ + while (jpos <= k) { + memcpy(&m[mpos * esize], &a[jpos * esize], esize); + jpos++; + mpos++; + } + + continue; + } else if (jpos > k) { + /* The right division has no more elements to merge. */ + while (ipos <= j) { + memcpy(&m[mpos * esize], &a[ipos * esize], esize); + ipos++; + mpos++; + } + + continue; + } + + /* Append the next ordered element to the merged elements. */ + if (comparefn(&a[ipos * esize], &a[jpos * esize]) < 0) { + memcpy(&m[mpos * esize], &a[ipos * esize], esize); + ipos++; + mpos++; + } else { + memcpy(&m[mpos * esize], &a[jpos * esize], esize); + jpos++; + mpos++; + } + } + + /* Prepare to pass back the merged data. */ + memcpy(&a[i * esize], m, esize * ((k - i) + 1)); + xfree(m); +} + +void arg_mgsort(void* data, int size, int esize, int i, int k, arg_comparefn* comparefn) { + int j; + + /* Stop the recursion when no more divisions can be made. */ + if (i < k) { + /* Determine where to divide the elements. */ + j = (int)(((i + k - 1)) / 2); + + /* Recursively sort the two divisions. */ + arg_mgsort(data, size, esize, i, j, comparefn); + arg_mgsort(data, size, esize, j + 1, k, comparefn); + merge(data, esize, i, j, k, comparefn); + } +} +/******************************************************************************* + * arg_hashtable: Implements the hash table utilities + * + * This file is part of the argtable3 library. + * + * Copyright (C) 2013-2019 Tom G. Huang + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#ifndef ARG_AMALGAMATION +#include "argtable3_private.h" +#endif + +#include +#include +#include +#include + +/* + * This hash table module is adapted from the C hash table implementation by + * Christopher Clark. Here is the copyright notice from the library: + * + * Copyright (c) 2002, Christopher Clark + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Credit for primes table: Aaron Krowne + * http://br.endernet.org/~akrowne/ + * http://planetmath.org/encyclopedia/GoodHashTablePrimes.html + */ +static const unsigned int primes[] = {53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, + 24593, 49157, 98317, 196613, 393241, 786433, 1572869, 3145739, 6291469, + 12582917, 25165843, 50331653, 100663319, 201326611, 402653189, 805306457, 1610612741}; +const unsigned int prime_table_length = sizeof(primes) / sizeof(primes[0]); +const float max_load_factor = (float)0.65; + +static unsigned int enhanced_hash(arg_hashtable_t* h, const void* k) { + /* + * Aim to protect against poor hash functions by adding logic here. + * The logic is taken from Java 1.4 hash table source. + */ + unsigned int i = h->hashfn(k); + i += ~(i << 9); + i ^= ((i >> 14) | (i << 18)); /* >>> */ + i += (i << 4); + i ^= ((i >> 10) | (i << 22)); /* >>> */ + return i; +} + +static unsigned int index_for(unsigned int tablelength, unsigned int hashvalue) { + return (hashvalue % tablelength); +} + +arg_hashtable_t* arg_hashtable_create(unsigned int minsize, unsigned int (*hashfn)(const void*), int (*eqfn)(const void*, const void*)) { + arg_hashtable_t* h; + unsigned int pindex; + unsigned int size = primes[0]; + + /* Check requested hash table isn't too large */ + if (minsize > (1u << 30)) + return NULL; + + /* + * Enforce size as prime. The reason is to avoid clustering of values + * into a small number of buckets (yes, distribution). A more even + * distributed hash table will perform more consistently. + */ + for (pindex = 0; pindex < prime_table_length; pindex++) { + if (primes[pindex] > minsize) { + size = primes[pindex]; + break; + } + } + + h = (arg_hashtable_t*)xmalloc(sizeof(arg_hashtable_t)); + h->table = (struct arg_hashtable_entry**)xmalloc(sizeof(struct arg_hashtable_entry*) * size); + memset(h->table, 0, size * sizeof(struct arg_hashtable_entry*)); + h->tablelength = size; + h->primeindex = pindex; + h->entrycount = 0; + h->hashfn = hashfn; + h->eqfn = eqfn; + h->loadlimit = (unsigned int)ceil(size * max_load_factor); + return h; +} + +static int arg_hashtable_expand(arg_hashtable_t* h) { + /* Double the size of the table to accommodate more entries */ + struct arg_hashtable_entry** newtable; + struct arg_hashtable_entry* e; + unsigned int newsize; + unsigned int i; + unsigned int index; + + /* Check we're not hitting max capacity */ + if (h->primeindex == (prime_table_length - 1)) + return 0; + newsize = primes[++(h->primeindex)]; + + newtable = (struct arg_hashtable_entry**)xmalloc(sizeof(struct arg_hashtable_entry*) * newsize); + memset(newtable, 0, newsize * sizeof(struct arg_hashtable_entry*)); + /* + * This algorithm is not 'stable': it reverses the list + * when it transfers entries between the tables + */ + for (i = 0; i < h->tablelength; i++) { + while (NULL != (e = h->table[i])) { + h->table[i] = e->next; + index = index_for(newsize, e->h); + e->next = newtable[index]; + newtable[index] = e; + } + } + + xfree(h->table); + h->table = newtable; + h->tablelength = newsize; + h->loadlimit = (unsigned int)ceil(newsize * max_load_factor); + return -1; +} + +unsigned int arg_hashtable_count(arg_hashtable_t* h) { + return h->entrycount; +} + +void arg_hashtable_insert(arg_hashtable_t* h, void* k, void* v) { + /* This method allows duplicate keys - but they shouldn't be used */ + unsigned int index; + struct arg_hashtable_entry* e; + if ((h->entrycount + 1) > h->loadlimit) { + /* + * Ignore the return value. If expand fails, we should + * still try cramming just this value into the existing table + * -- we may not have memory for a larger table, but one more + * element may be ok. Next time we insert, we'll try expanding again. + */ + arg_hashtable_expand(h); + } + e = (struct arg_hashtable_entry*)xmalloc(sizeof(struct arg_hashtable_entry)); + e->h = enhanced_hash(h, k); + index = index_for(h->tablelength, e->h); + e->k = k; + e->v = v; + e->next = h->table[index]; + h->table[index] = e; + h->entrycount++; +} + +void* arg_hashtable_search(arg_hashtable_t* h, const void* k) { + struct arg_hashtable_entry* e; + unsigned int hashvalue; + unsigned int index; + + hashvalue = enhanced_hash(h, k); + index = index_for(h->tablelength, hashvalue); + e = h->table[index]; + while (e != NULL) { + /* Check hash value to short circuit heavier comparison */ + if ((hashvalue == e->h) && (h->eqfn(k, e->k))) + return e->v; + e = e->next; + } + return NULL; +} + +void arg_hashtable_remove(arg_hashtable_t* h, const void* k) { + /* + * TODO: consider compacting the table when the load factor drops enough, + * or provide a 'compact' method. + */ + + struct arg_hashtable_entry* e; + struct arg_hashtable_entry** pE; + unsigned int hashvalue; + unsigned int index; + + hashvalue = enhanced_hash(h, k); + index = index_for(h->tablelength, hashvalue); + pE = &(h->table[index]); + e = *pE; + while (NULL != e) { + /* Check hash value to short circuit heavier comparison */ + if ((hashvalue == e->h) && (h->eqfn(k, e->k))) { + *pE = e->next; + h->entrycount--; + xfree(e->k); + xfree(e->v); + xfree(e); + return; + } + pE = &(e->next); + e = e->next; + } +} + +void arg_hashtable_destroy(arg_hashtable_t* h, int free_values) { + unsigned int i; + struct arg_hashtable_entry *e, *f; + struct arg_hashtable_entry** table = h->table; + if (free_values) { + for (i = 0; i < h->tablelength; i++) { + e = table[i]; + while (NULL != e) { + f = e; + e = e->next; + xfree(f->k); + xfree(f->v); + xfree(f); + } + } + } else { + for (i = 0; i < h->tablelength; i++) { + e = table[i]; + while (NULL != e) { + f = e; + e = e->next; + xfree(f->k); + xfree(f); + } + } + } + xfree(h->table); + xfree(h); +} + +arg_hashtable_itr_t* arg_hashtable_itr_create(arg_hashtable_t* h) { + unsigned int i; + unsigned int tablelength; + + arg_hashtable_itr_t* itr = (arg_hashtable_itr_t*)xmalloc(sizeof(arg_hashtable_itr_t)); + itr->h = h; + itr->e = NULL; + itr->parent = NULL; + tablelength = h->tablelength; + itr->index = tablelength; + if (0 == h->entrycount) + return itr; + + for (i = 0; i < tablelength; i++) { + if (h->table[i] != NULL) { + itr->e = h->table[i]; + itr->index = i; + break; + } + } + return itr; +} + +void arg_hashtable_itr_destroy(arg_hashtable_itr_t* itr) { + xfree(itr); +} + +void* arg_hashtable_itr_key(arg_hashtable_itr_t* i) { + return i->e->k; +} + +void* arg_hashtable_itr_value(arg_hashtable_itr_t* i) { + return i->e->v; +} + +int arg_hashtable_itr_advance(arg_hashtable_itr_t* itr) { + unsigned int j; + unsigned int tablelength; + struct arg_hashtable_entry** table; + struct arg_hashtable_entry* next; + + if (itr->e == NULL) + return 0; /* stupidity check */ + + next = itr->e->next; + if (NULL != next) { + itr->parent = itr->e; + itr->e = next; + return -1; + } + + tablelength = itr->h->tablelength; + itr->parent = NULL; + if (tablelength <= (j = ++(itr->index))) { + itr->e = NULL; + return 0; + } + + table = itr->h->table; + while (NULL == (next = table[j])) { + if (++j >= tablelength) { + itr->index = tablelength; + itr->e = NULL; + return 0; + } + } + + itr->index = j; + itr->e = next; + return -1; +} + +int arg_hashtable_itr_remove(arg_hashtable_itr_t* itr) { + struct arg_hashtable_entry* remember_e; + struct arg_hashtable_entry* remember_parent; + int ret; + + /* Do the removal */ + if ((itr->parent) == NULL) { + /* element is head of a chain */ + itr->h->table[itr->index] = itr->e->next; + } else { + /* element is mid-chain */ + itr->parent->next = itr->e->next; + } + /* itr->e is now outside the hashtable */ + remember_e = itr->e; + itr->h->entrycount--; + xfree(remember_e->k); + xfree(remember_e->v); + + /* Advance the iterator, correcting the parent */ + remember_parent = itr->parent; + ret = arg_hashtable_itr_advance(itr); + if (itr->parent == remember_e) { + itr->parent = remember_parent; + } + xfree(remember_e); + return ret; +} + +int arg_hashtable_itr_search(arg_hashtable_itr_t* itr, arg_hashtable_t* h, void* k) { + struct arg_hashtable_entry* e; + struct arg_hashtable_entry* parent; + unsigned int hashvalue; + unsigned int index; + + hashvalue = enhanced_hash(h, k); + index = index_for(h->tablelength, hashvalue); + + e = h->table[index]; + parent = NULL; + while (e != NULL) { + /* Check hash value to short circuit heavier comparison */ + if ((hashvalue == e->h) && (h->eqfn(k, e->k))) { + itr->index = index; + itr->e = e; + itr->parent = parent; + itr->h = h; + return -1; + } + parent = e; + e = e->next; + } + return 0; +} + +int arg_hashtable_change(arg_hashtable_t* h, void* k, void* v) { + struct arg_hashtable_entry* e; + unsigned int hashvalue; + unsigned int index; + + hashvalue = enhanced_hash(h, k); + index = index_for(h->tablelength, hashvalue); + e = h->table[index]; + while (e != NULL) { + /* Check hash value to short circuit heavier comparison */ + if ((hashvalue == e->h) && (h->eqfn(k, e->k))) { + xfree(e->v); + e->v = v; + return -1; + } + e = e->next; + } + return 0; +} +/******************************************************************************* + * arg_dstr: Implements the dynamic string utilities + * + * This file is part of the argtable3 library. + * + * Copyright (C) 2013-2019 Tom G. Huang + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include "argtable3.h" + +#ifndef ARG_AMALGAMATION +#include "argtable3_private.h" +#endif + +#include +#include +#include + +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4996) +#endif + +#define START_VSNBUFF 16 + +/* + * This dynamic string module is adapted from TclResult.c in the Tcl library. + * Here is the copyright notice from the library: + * + * This software is copyrighted by the Regents of the University of + * California, Sun Microsystems, Inc., Scriptics Corporation, ActiveState + * Corporation and other parties. The following terms apply to all files + * associated with the software unless explicitly disclaimed in + * individual files. + * + * The authors hereby grant permission to use, copy, modify, distribute, + * and license this software and its documentation for any purpose, provided + * that existing copyright notices are retained in all copies and that this + * notice is included verbatim in any distributions. No written agreement, + * license, or royalty fee is required for any of the authorized uses. + * Modifications to this software may be copyrighted by their authors + * and need not follow the licensing terms described here, provided that + * the new terms are clearly indicated on the first page of each file where + * they apply. + * + * IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY + * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES + * ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY + * DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE + * IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE + * NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR + * MODIFICATIONS. + * + * GOVERNMENT USE: If you are acquiring this software on behalf of the + * U.S. government, the Government shall have only "Restricted Rights" + * in the software and related documentation as defined in the Federal + * Acquisition Regulations (FARs) in Clause 52.227.19 (c) (2). If you + * are acquiring the software on behalf of the Department of Defense, the + * software shall be classified as "Commercial Computer Software" and the + * Government shall have only "Restricted Rights" as defined in Clause + * 252.227-7014 (b) (3) of DFARs. Notwithstanding the foregoing, the + * authors grant the U.S. Government and others acting in its behalf + * permission to use and distribute the software in accordance with the + * terms specified in this license. + */ + +typedef struct _internal_arg_dstr { + char* data; + arg_dstr_freefn* free_proc; + char sbuf[ARG_DSTR_SIZE + 1]; + char* append_data; + int append_data_size; + int append_used; +} _internal_arg_dstr_t; + +static void setup_append_buf(arg_dstr_t res, int newSpace); + +arg_dstr_t arg_dstr_create(void) { + _internal_arg_dstr_t* h = (_internal_arg_dstr_t*)xmalloc(sizeof(_internal_arg_dstr_t)); + memset(h, 0, sizeof(_internal_arg_dstr_t)); + h->sbuf[0] = 0; + h->data = h->sbuf; + h->free_proc = ARG_DSTR_STATIC; + return h; +} + +void arg_dstr_destroy(arg_dstr_t ds) { + if (ds == NULL) + return; + + arg_dstr_reset(ds); + xfree(ds); + return; +} + +void arg_dstr_set(arg_dstr_t ds, char* str, arg_dstr_freefn* free_proc) { + int length; + register arg_dstr_freefn* old_free_proc = ds->free_proc; + char* old_result = ds->data; + + if (str == NULL) { + ds->sbuf[0] = 0; + ds->data = ds->sbuf; + ds->free_proc = ARG_DSTR_STATIC; + } else if (free_proc == ARG_DSTR_VOLATILE) { + length = (int)strlen(str); + if (length > ARG_DSTR_SIZE) { + ds->data = (char*)xmalloc((unsigned)length + 1); + ds->free_proc = ARG_DSTR_DYNAMIC; + } else { + ds->data = ds->sbuf; + ds->free_proc = ARG_DSTR_STATIC; + } + strcpy(ds->data, str); + } else { + ds->data = str; + ds->free_proc = free_proc; + } + + /* + * If the old result was dynamically-allocated, free it up. Do it here, + * rather than at the beginning, in case the new result value was part of + * the old result value. + */ + + if ((old_free_proc != 0) && (old_result != ds->data)) { + if (old_free_proc == ARG_DSTR_DYNAMIC) { + xfree(old_result); + } else { + (*old_free_proc)(old_result); + } + } + + if ((ds->append_data != NULL) && (ds->append_data_size > 0)) { + xfree(ds->append_data); + ds->append_data = NULL; + ds->append_data_size = 0; + } +} + +char* arg_dstr_cstr(arg_dstr_t ds) /* Interpreter whose result to return. */ +{ + return ds->data; +} + +void arg_dstr_cat(arg_dstr_t ds, const char* str) { + setup_append_buf(ds, (int)strlen(str) + 1); + memcpy(ds->data + strlen(ds->data), str, strlen(str)); +} + +void arg_dstr_catc(arg_dstr_t ds, char c) { + setup_append_buf(ds, 2); + memcpy(ds->data + strlen(ds->data), &c, 1); +} + +/* + * The logic of the `arg_dstr_catf` function is adapted from the `bformat` + * function in The Better String Library by Paul Hsieh. Here is the copyright + * notice from the library: + * + * Copyright (c) 2014, Paul Hsieh + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of bstrlib nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +void arg_dstr_catf(arg_dstr_t ds, const char* fmt, ...) { + va_list arglist; + char* buff; + int n, r; + size_t slen; + + if (fmt == NULL) + return; + + /* Since the length is not determinable beforehand, a search is + performed using the truncating "vsnprintf" call (to avoid buffer + overflows) on increasing potential sizes for the output result. */ + + if ((n = (int)(2 * strlen(fmt))) < START_VSNBUFF) + n = START_VSNBUFF; + + buff = (char*)xmalloc(n + 2); + memset(buff, 0, n + 2); + + for (;;) { + va_start(arglist, fmt); + r = vsnprintf(buff, n + 1, fmt, arglist); + va_end(arglist); + + slen = strlen(buff); + if (slen < (size_t)n) + break; + + if (r > n) + n = r; + else + n += n; + + xfree(buff); + buff = (char*)xmalloc(n + 2); + memset(buff, 0, n + 2); + } + + arg_dstr_cat(ds, buff); + xfree(buff); +} + +static void setup_append_buf(arg_dstr_t ds, int new_space) { + int total_space; + + /* + * Make the append buffer larger, if that's necessary, then copy the + * data into the append buffer and make the append buffer the official + * data. + */ + if (ds->data != ds->append_data) { + /* + * If the buffer is too big, then free it up so we go back to a + * smaller buffer. This avoids tying up memory forever after a large + * operation. + */ + if (ds->append_data_size > 500) { + xfree(ds->append_data); + ds->append_data = NULL; + ds->append_data_size = 0; + } + ds->append_used = (int)strlen(ds->data); + } else if (ds->data[ds->append_used] != 0) { + /* + * Most likely someone has modified a result created by + * arg_dstr_cat et al. so that it has a different size. Just + * recompute the size. + */ + ds->append_used = (int)strlen(ds->data); + } + + total_space = new_space + ds->append_used; + if (total_space >= ds->append_data_size) { + char* newbuf; + + if (total_space < 100) { + total_space = 200; + } else { + total_space *= 2; + } + newbuf = (char*)xmalloc((unsigned)total_space); + memset(newbuf, 0, total_space); + strcpy(newbuf, ds->data); + if (ds->append_data != NULL) { + xfree(ds->append_data); + } + ds->append_data = newbuf; + ds->append_data_size = total_space; + } else if (ds->data != ds->append_data) { + strcpy(ds->append_data, ds->data); + } + + arg_dstr_free(ds); + ds->data = ds->append_data; +} + +void arg_dstr_free(arg_dstr_t ds) { + if (ds->free_proc != NULL) { + if (ds->free_proc == ARG_DSTR_DYNAMIC) { + xfree(ds->data); + } else { + (*ds->free_proc)(ds->data); + } + ds->free_proc = NULL; + } +} + +void arg_dstr_reset(arg_dstr_t ds) { + arg_dstr_free(ds); + if ((ds->append_data != NULL) && (ds->append_data_size > 0)) { + xfree(ds->append_data); + ds->append_data = NULL; + ds->append_data_size = 0; + } + + ds->data = ds->sbuf; + ds->sbuf[0] = 0; +} + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif +/* $Id: getopt.h,v 1.1 2009/10/16 19:50:28 rodney Exp rodney $ */ +/* $OpenBSD: getopt.h,v 1.1 2002/12/03 20:24:29 millert Exp $ */ +/* $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $ */ + +/* + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Dieter Baron and Thomas Klausner. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgment: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#if ARG_REPLACE_GETOPT == 1 + +#ifndef _GETOPT_H_ +#define _GETOPT_H_ + +/* + * GNU-like getopt_long() and 4.4BSD getsubopt()/optreset extensions + */ +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +struct option { + /* name of long option */ + const char* name; + /* + * one of no_argument, required_argument, and optional_argument: + * whether option takes an argument + */ + int has_arg; + /* if not NULL, set *flag to val when option found */ + int* flag; + /* if flag not NULL, value to set *flag to; else return value */ + int val; +}; + +#ifdef __cplusplus +extern "C" { +#endif + +int getopt_long(int, char* const*, const char*, const struct option*, int*); +int getopt_long_only(int, char* const*, const char*, const struct option*, int*); +#ifndef _GETOPT_DEFINED +#define _GETOPT_DEFINED +int getopt(int, char* const*, const char*); +int getsubopt(char**, char* const*, char**); + +extern char* optarg; /* getopt(3) external variables */ +extern int opterr; +extern int optind; +extern int optopt; +extern int optreset; +extern char* suboptarg; /* getsubopt(3) external variable */ +#endif /* _GETOPT_DEFINED */ + +#ifdef __cplusplus +} +#endif +#endif /* !_GETOPT_H_ */ + +#else +#include +#endif /* ARG_REPLACE_GETOPT */ +/* $Id: getopt_long.c,v 1.1 2009/10/16 19:50:28 rodney Exp rodney $ */ +/* $OpenBSD: getopt_long.c,v 1.23 2007/10/31 12:34:57 chl Exp $ */ +/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ + +/* + * Copyright (c) 2002 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F39502-99-1-0512. + */ + +/* + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Dieter Baron and Thomas Klausner. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "argtable3.h" + +#ifndef ARG_AMALGAMATION +#include "getopt.h" +#endif + +#include +#include +#include + +#if ARG_REPLACE_GETOPT == 1 +int opterr = 1; /* if error message should be printed */ +int optind = 1; /* index into parent argv vector */ +int optopt = '?'; /* character checked for validity */ +int optreset; /* reset getopt */ +char* optarg; /* argument associated with option */ +#endif /* ARG_REPLACE_GETOPT */ + +#define PRINT_ERROR ((opterr) && (*options != ':')) + +#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ +#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ +#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ + +/* return values */ +#define BADCH (int)'?' +#define BADARG ((*options == ':') ? (int)':' : (int)'?') +#define INORDER (int)1 + +#define EMSG "" + +#if ARG_REPLACE_GETOPT == 1 +static int getopt_internal(int, char* const*, const char*, const struct option*, int*, int); +#endif /* ARG_REPLACE_GETOPT */ +static int parse_long_options(char* const*, const char*, const struct option*, int*, int); +static int gcd(int, int); +static void permute_args(int, int, int, char* const*); + +static char* place = EMSG; /* option letter processing */ + +/* XXX: set optreset to 1 rather than these two */ +static int nonopt_start = -1; /* first non option argument (for permute) */ +static int nonopt_end = -1; /* first option after non options (for permute) */ + +/* Error messages */ +static const char recargchar[] = "option requires an argument -- %c"; +static const char recargstring[] = "option requires an argument -- %s"; +static const char ambig[] = "ambiguous option -- %.*s"; +static const char noarg[] = "option doesn't take an argument -- %.*s"; +static const char illoptchar[] = "unknown option -- %c"; +static const char illoptstring[] = "unknown option -- %s"; + +#ifdef _WIN32 + +/* + * Windows needs warnx(). We change the definition though: + * 1. (another) global is defined, opterrmsg, which holds the error message + * 2. errors are always printed out on stderr w/o the program name + * Note that opterrmsg always gets set no matter what opterr is set to. The + * error message will not be printed if opterr is 0 as usual. + */ + +#include +#include + +#define MAX_OPTERRMSG_SIZE 128 + +extern char opterrmsg[MAX_OPTERRMSG_SIZE]; +char opterrmsg[MAX_OPTERRMSG_SIZE]; /* buffer for the last error message */ + +static void warnx(const char* fmt, ...) { + va_list ap; + va_start(ap, fmt); + + /* + * Make sure opterrmsg is always zero-terminated despite the _vsnprintf() + * implementation specifics and manually suppress the warning. + */ + memset(opterrmsg, 0, sizeof(opterrmsg)); + if (fmt != NULL) +#if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__)) + _vsnprintf_s(opterrmsg, sizeof(opterrmsg), sizeof(opterrmsg) - 1, fmt, ap); +#else + _vsnprintf(opterrmsg, sizeof(opterrmsg) - 1, fmt, ap); +#endif + + va_end(ap); + +#ifdef _MSC_VER +#pragma warning(suppress : 6053) +#endif + fprintf(stderr, "%s\n", opterrmsg); +} + +#else +#include +#endif /*_WIN32*/ + +/* + * Compute the greatest common divisor of a and b. + */ +static int gcd(int a, int b) { + int c; + + c = a % b; + while (c != 0) { + a = b; + b = c; + c = a % b; + } + + return (b); +} + +/* + * Exchange the block from nonopt_start to nonopt_end with the block + * from nonopt_end to opt_end (keeping the same order of arguments + * in each block). + */ +static void permute_args(int panonopt_start, int panonopt_end, int opt_end, char* const* nargv) { + int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; + char* swap; + + /* + * compute lengths of blocks and number and size of cycles + */ + nnonopts = panonopt_end - panonopt_start; + nopts = opt_end - panonopt_end; + ncycle = gcd(nnonopts, nopts); + cyclelen = (opt_end - panonopt_start) / ncycle; + + for (i = 0; i < ncycle; i++) { + cstart = panonopt_end + i; + pos = cstart; + for (j = 0; j < cyclelen; j++) { + if (pos >= panonopt_end) + pos -= nnonopts; + else + pos += nopts; + swap = nargv[pos]; + /* LINTED const cast */ + ((char**)nargv)[pos] = nargv[cstart]; + /* LINTED const cast */ + ((char**)nargv)[cstart] = swap; + } + } +} + +/* + * parse_long_options -- + * Parse long options in argc/argv argument vector. + * Returns -1 if short_too is set and the option does not match long_options. + */ +static int parse_long_options(char* const* nargv, const char* options, const struct option* long_options, int* idx, int short_too) { + char *current_argv, *has_equal; + size_t current_argv_len; + int i, match; + + current_argv = place; + match = -1; + + optind++; + + if ((has_equal = strchr(current_argv, '=')) != NULL) { + /* argument found (--option=arg) */ + current_argv_len = has_equal - current_argv; + has_equal++; + } else + current_argv_len = strlen(current_argv); + + for (i = 0; long_options[i].name; i++) { + /* find matching long option */ + if (strncmp(current_argv, long_options[i].name, current_argv_len)) + continue; + + if (strlen(long_options[i].name) == current_argv_len) { + /* exact match */ + match = i; + break; + } + /* + * If this is a known short option, don't allow + * a partial match of a single character. + */ + if (short_too && current_argv_len == 1) + continue; + + if (match == -1) /* partial match */ + match = i; + else { + /* ambiguous abbreviation */ + if (PRINT_ERROR) + warnx(ambig, (int)current_argv_len, current_argv); + optopt = 0; + return (BADCH); + } + } + if (match != -1) { /* option found */ + if (long_options[match].has_arg == no_argument && has_equal) { + if (PRINT_ERROR) + warnx(noarg, (int)current_argv_len, current_argv); + /* + * XXX: GNU sets optopt to val regardless of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + return (BADARG); + } + if (long_options[match].has_arg == required_argument || long_options[match].has_arg == optional_argument) { + if (has_equal) + optarg = has_equal; + else if (long_options[match].has_arg == required_argument) { + /* + * optional argument doesn't use next nargv + */ + optarg = nargv[optind++]; + } + } + if ((long_options[match].has_arg == required_argument) && (optarg == NULL)) { + /* + * Missing argument; leading ':' indicates no error + * should be generated. + */ + if (PRINT_ERROR) + warnx(recargstring, current_argv); + /* + * XXX: GNU sets optopt to val regardless of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + --optind; + return (BADARG); + } + } else { /* unknown option */ + if (short_too) { + --optind; + return (-1); + } + if (PRINT_ERROR) + warnx(illoptstring, current_argv); + optopt = 0; + return (BADCH); + } + if (idx) + *idx = match; + if (long_options[match].flag) { + *long_options[match].flag = long_options[match].val; + return (0); + } else + return (long_options[match].val); +} + +#if ARG_REPLACE_GETOPT == 1 +/* + * getopt_internal -- + * Parse argc/argv argument vector. Called by user level routines. + */ +static int getopt_internal(int nargc, char* const* nargv, const char* options, const struct option* long_options, int* idx, int flags) { + char* oli; /* option letter list index */ + int optchar, short_too; + static int posixly_correct = -1; + + if (options == NULL) + return (-1); + + /* + * Disable GNU extensions if POSIXLY_CORRECT is set or options + * string begins with a '+'. + */ + if (posixly_correct == -1) +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4996) +#endif + posixly_correct = (getenv("POSIXLY_CORRECT") != NULL); +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + if (posixly_correct || *options == '+') + flags &= ~FLAG_PERMUTE; + else if (*options == '-') + flags |= FLAG_ALLARGS; + if (*options == '+' || *options == '-') + options++; + + /* + * XXX Some GNU programs (like cvs) set optind to 0 instead of + * XXX using optreset. Work around this braindamage. + */ + if (optind == 0) + optind = optreset = 1; + + optarg = NULL; + if (optreset) + nonopt_start = nonopt_end = -1; +start: + if (optreset || !*place) { /* update scanning pointer */ + optreset = 0; + if (optind >= nargc) { /* end of argument vector */ + place = EMSG; + if (nonopt_end != -1) { + /* do permutation, if we have to */ + permute_args(nonopt_start, nonopt_end, optind, nargv); + optind -= nonopt_end - nonopt_start; + } else if (nonopt_start != -1) { + /* + * If we skipped non-options, set optind + * to the first of them. + */ + optind = nonopt_start; + } + nonopt_start = nonopt_end = -1; + return (-1); + } + if (*(place = nargv[optind]) != '-' || (place[1] == '\0' && strchr(options, '-') == NULL)) { + place = EMSG; /* found non-option */ + if (flags & FLAG_ALLARGS) { + /* + * GNU extension: + * return non-option as argument to option 1 + */ + optarg = nargv[optind++]; + return (INORDER); + } + if (!(flags & FLAG_PERMUTE)) { + /* + * If no permutation wanted, stop parsing + * at first non-option. + */ + return (-1); + } + /* do permutation */ + if (nonopt_start == -1) + nonopt_start = optind; + else if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, optind, nargv); + nonopt_start = optind - (nonopt_end - nonopt_start); + nonopt_end = -1; + } + optind++; + /* process next argument */ + goto start; + } + if (nonopt_start != -1 && nonopt_end == -1) + nonopt_end = optind; + + /* + * If we have "-" do nothing, if "--" we are done. + */ + if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { + optind++; + place = EMSG; + /* + * We found an option (--), so if we skipped + * non-options, we have to permute. + */ + if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, optind, nargv); + optind -= nonopt_end - nonopt_start; + } + nonopt_start = nonopt_end = -1; + return (-1); + } + } + + /* + * Check long options if: + * 1) we were passed some + * 2) the arg is not just "-" + * 3) either the arg starts with -- we are getopt_long_only() + */ + if (long_options != NULL && place != nargv[optind] && (*place == '-' || (flags & FLAG_LONGONLY))) { + short_too = 0; + if (*place == '-') + place++; /* --foo long option */ + else if (*place != ':' && strchr(options, *place) != NULL) + short_too = 1; /* could be short option too */ + + optchar = parse_long_options(nargv, options, long_options, idx, short_too); + if (optchar != -1) { + place = EMSG; + return (optchar); + } + } + + if ((optchar = (int)*place++) == (int)':' || (optchar == (int)'-' && *place != '\0') || (oli = strchr(options, optchar)) == NULL) { + /* + * If the user specified "-" and '-' isn't listed in + * options, return -1 (non-option) as per POSIX. + * Otherwise, it is an unknown option character (or ':'). + */ + if (optchar == (int)'-' && *place == '\0') + return (-1); + if (!*place) + ++optind; + if (PRINT_ERROR) + warnx(illoptchar, optchar); + optopt = optchar; + return (BADCH); + } + if (long_options != NULL && optchar == 'W' && oli[1] == ';') { + /* -W long-option */ + if (*place) /* no space */ + /* NOTHING */; + else if (++optind >= nargc) { /* no arg */ + place = EMSG; + if (PRINT_ERROR) + warnx(recargchar, optchar); + optopt = optchar; + return (BADARG); + } else /* white space */ + place = nargv[optind]; + optchar = parse_long_options(nargv, options, long_options, idx, 0); + place = EMSG; + return (optchar); + } + if (*++oli != ':') { /* doesn't take argument */ + if (!*place) + ++optind; + } else { /* takes (optional) argument */ + optarg = NULL; + if (*place) /* no white space */ + optarg = place; + else if (oli[1] != ':') { /* arg not optional */ + if (++optind >= nargc) { /* no arg */ + place = EMSG; + if (PRINT_ERROR) + warnx(recargchar, optchar); + optopt = optchar; + return (BADARG); + } else + optarg = nargv[optind]; + } + place = EMSG; + ++optind; + } + /* dump back option letter */ + return (optchar); +} + +/* + * getopt -- + * Parse argc/argv argument vector. + * + * [eventually this will replace the BSD getopt] + */ +int getopt(int nargc, char* const* nargv, const char* options) { + /* + * We don't pass FLAG_PERMUTE to getopt_internal() since + * the BSD getopt(3) (unlike GNU) has never done this. + * + * Furthermore, since many privileged programs call getopt() + * before dropping privileges it makes sense to keep things + * as simple (and bug-free) as possible. + */ + return (getopt_internal(nargc, nargv, options, NULL, NULL, 0)); +} +#endif /* ARG_REPLACE_GETOPT */ + +/* + * getopt_long -- + * Parse argc/argv argument vector. + */ +int getopt_long(int nargc, char* const* nargv, const char* options, const struct option* long_options, int* idx) { + return (getopt_internal(nargc, nargv, options, long_options, idx, FLAG_PERMUTE)); +} + +/* + * getopt_long_only -- + * Parse argc/argv argument vector. + */ +int getopt_long_only(int nargc, char* const* nargv, const char* options, const struct option* long_options, int* idx) { + return (getopt_internal(nargc, nargv, options, long_options, idx, FLAG_PERMUTE | FLAG_LONGONLY)); +} +/******************************************************************************* + * arg_date: Implements the date command-line option + * + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include "argtable3.h" + +#ifndef ARG_AMALGAMATION +#include "argtable3_private.h" +#endif + +#include +#include + +char* arg_strptime(const char* buf, const char* fmt, struct tm* tm); + +static void arg_date_resetfn(struct arg_date* parent) { + ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent)); + parent->count = 0; +} + +static int arg_date_scanfn(struct arg_date* parent, const char* argval) { + int errorcode = 0; + + if (parent->count == parent->hdr.maxcount) { + errorcode = ARG_ERR_MAXCOUNT; + } else if (!argval) { + /* no argument value was given, leave parent->tmval[] unaltered but still count it */ + parent->count++; + } else { + const char* pend; + struct tm tm = parent->tmval[parent->count]; + + /* parse the given argument value, store result in parent->tmval[] */ + pend = arg_strptime(argval, parent->format, &tm); + if (pend && pend[0] == '\0') + parent->tmval[parent->count++] = tm; + else + errorcode = ARG_ERR_BADDATE; + } + + ARG_TRACE(("%s:scanfn(%p) returns %d\n", __FILE__, parent, errorcode)); + return errorcode; +} + +static int arg_date_checkfn(struct arg_date* parent) { + int errorcode = (parent->count < parent->hdr.mincount) ? ARG_ERR_MINCOUNT : 0; + + ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode)); + return errorcode; +} + +static void arg_date_errorfn(struct arg_date* parent, arg_dstr_t ds, int errorcode, const char* argval, const char* progname) { + const char* shortopts = parent->hdr.shortopts; + const char* longopts = parent->hdr.longopts; + const char* datatype = parent->hdr.datatype; + + /* make argval NULL safe */ + argval = argval ? argval : ""; + + arg_dstr_catf(ds, "%s: ", progname); + switch (errorcode) { + case ARG_ERR_MINCOUNT: + arg_dstr_cat(ds, "missing option "); + arg_print_option_ds(ds, shortopts, longopts, datatype, "\n"); + break; + + case ARG_ERR_MAXCOUNT: + arg_dstr_cat(ds, "excess option "); + arg_print_option_ds(ds, shortopts, longopts, argval, "\n"); + break; + + case ARG_ERR_BADDATE: { + struct tm tm; + char buff[200]; + + arg_dstr_catf(ds, "illegal timestamp format \"%s\"\n", argval); + memset(&tm, 0, sizeof(tm)); + arg_strptime("1999-12-31 23:59:59", "%F %H:%M:%S", &tm); + strftime(buff, sizeof(buff), parent->format, &tm); + arg_dstr_catf(ds, "correct format is \"%s\"\n", buff); + break; + } + } +} + +struct arg_date* arg_date0(const char* shortopts, const char* longopts, const char* format, const char* datatype, const char* glossary) { + return arg_daten(shortopts, longopts, format, datatype, 0, 1, glossary); +} + +struct arg_date* arg_date1(const char* shortopts, const char* longopts, const char* format, const char* datatype, const char* glossary) { + return arg_daten(shortopts, longopts, format, datatype, 1, 1, glossary); +} + +struct arg_date* +arg_daten(const char* shortopts, const char* longopts, const char* format, const char* datatype, int mincount, int maxcount, const char* glossary) { + size_t nbytes; + struct arg_date* result; + + /* foolproof things by ensuring maxcount is not less than mincount */ + maxcount = (maxcount < mincount) ? mincount : maxcount; + + /* default time format is the national date format for the locale */ + if (!format) + format = "%x"; + + nbytes = sizeof(struct arg_date) /* storage for struct arg_date */ + + maxcount * sizeof(struct tm); /* storage for tmval[maxcount] array */ + + /* allocate storage for the arg_date struct + tmval[] array. */ + /* we use calloc because we want the tmval[] array zero filled. */ + result = (struct arg_date*)xcalloc(1, nbytes); + + /* init the arg_hdr struct */ + result->hdr.flag = ARG_HASVALUE; + result->hdr.shortopts = shortopts; + result->hdr.longopts = longopts; + result->hdr.datatype = datatype ? datatype : format; + result->hdr.glossary = glossary; + result->hdr.mincount = mincount; + result->hdr.maxcount = maxcount; + result->hdr.parent = result; + result->hdr.resetfn = (arg_resetfn*)arg_date_resetfn; + result->hdr.scanfn = (arg_scanfn*)arg_date_scanfn; + result->hdr.checkfn = (arg_checkfn*)arg_date_checkfn; + result->hdr.errorfn = (arg_errorfn*)arg_date_errorfn; + + /* store the tmval[maxcount] array immediately after the arg_date struct */ + result->tmval = (struct tm*)(result + 1); + + /* init the remaining arg_date member variables */ + result->count = 0; + result->format = format; + + ARG_TRACE(("arg_daten() returns %p\n", result)); + return result; +} + +/*- + * Copyright (c) 1997, 1998, 2005, 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code was contributed to The NetBSD Foundation by Klaus Klein. + * Heavily optimised by David Laight + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +/* + * We do not implement alternate representations. However, we always + * check whether a given modifier is allowed for a certain conversion. + */ +#define ALT_E 0x01 +#define ALT_O 0x02 +#define LEGAL_ALT(x) \ + { \ + if (alt_format & ~(x)) \ + return (0); \ + } +#define TM_YEAR_BASE (1900) + +static int conv_num(const char**, int*, int, int); + +static const char* day[7] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; + +static const char* abday[7] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; + +static const char* mon[12] = {"January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December"}; + +static const char* abmon[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; + +static const char* am_pm[2] = {"AM", "PM"}; + +static int arg_strcasecmp(const char* s1, const char* s2) { + const unsigned char* us1 = (const unsigned char*)s1; + const unsigned char* us2 = (const unsigned char*)s2; + while (tolower(*us1) == tolower(*us2++)) + if (*us1++ == '\0') + return 0; + + return tolower(*us1) - tolower(*--us2); +} + +static int arg_strncasecmp(const char* s1, const char* s2, size_t n) { + if (n != 0) { + const unsigned char* us1 = (const unsigned char*)s1; + const unsigned char* us2 = (const unsigned char*)s2; + do { + if (tolower(*us1) != tolower(*us2++)) + return tolower(*us1) - tolower(*--us2); + + if (*us1++ == '\0') + break; + } while (--n != 0); + } + + return 0; +} + +char* arg_strptime(const char* buf, const char* fmt, struct tm* tm) { + char c; + const char* bp; + size_t len = 0; + int alt_format, i, split_year = 0; + + bp = buf; + + while ((c = *fmt) != '\0') { + /* Clear `alternate' modifier prior to new conversion. */ + alt_format = 0; + + /* Eat up white-space. */ + if (isspace(c)) { + while (isspace(*bp)) + bp++; + + fmt++; + continue; + } + + if ((c = *fmt++) != '%') + goto literal; + + again: + switch (c = *fmt++) { + case '%': /* "%%" is converted to "%". */ + literal: + if (c != *bp++) + return (0); + break; + + /* + * "Alternative" modifiers. Just set the appropriate flag + * and start over again. + */ + case 'E': /* "%E?" alternative conversion modifier. */ + LEGAL_ALT(0); + alt_format |= ALT_E; + goto again; + + case 'O': /* "%O?" alternative conversion modifier. */ + LEGAL_ALT(0); + alt_format |= ALT_O; + goto again; + + /* + * "Complex" conversion rules, implemented through recursion. + */ + case 'c': /* Date and time, using the locale's format. */ + LEGAL_ALT(ALT_E); + bp = arg_strptime(bp, "%x %X", tm); + if (!bp) + return (0); + break; + + case 'D': /* The date as "%m/%d/%y". */ + LEGAL_ALT(0); + bp = arg_strptime(bp, "%m/%d/%y", tm); + if (!bp) + return (0); + break; + + case 'R': /* The time as "%H:%M". */ + LEGAL_ALT(0); + bp = arg_strptime(bp, "%H:%M", tm); + if (!bp) + return (0); + break; + + case 'r': /* The time in 12-hour clock representation. */ + LEGAL_ALT(0); + bp = arg_strptime(bp, "%I:%M:%S %p", tm); + if (!bp) + return (0); + break; + + case 'T': /* The time as "%H:%M:%S". */ + LEGAL_ALT(0); + bp = arg_strptime(bp, "%H:%M:%S", tm); + if (!bp) + return (0); + break; + + case 'X': /* The time, using the locale's format. */ + LEGAL_ALT(ALT_E); + bp = arg_strptime(bp, "%H:%M:%S", tm); + if (!bp) + return (0); + break; + + case 'x': /* The date, using the locale's format. */ + LEGAL_ALT(ALT_E); + bp = arg_strptime(bp, "%m/%d/%y", tm); + if (!bp) + return (0); + break; + + /* + * "Elementary" conversion rules. + */ + case 'A': /* The day of week, using the locale's form. */ + case 'a': + LEGAL_ALT(0); + for (i = 0; i < 7; i++) { + /* Full name. */ + len = strlen(day[i]); + if (arg_strncasecmp(day[i], bp, len) == 0) + break; + + /* Abbreviated name. */ + len = strlen(abday[i]); + if (arg_strncasecmp(abday[i], bp, len) == 0) + break; + } + + /* Nothing matched. */ + if (i == 7) + return (0); + + tm->tm_wday = i; + bp += len; + break; + + case 'B': /* The month, using the locale's form. */ + case 'b': + case 'h': + LEGAL_ALT(0); + for (i = 0; i < 12; i++) { + /* Full name. */ + len = strlen(mon[i]); + if (arg_strncasecmp(mon[i], bp, len) == 0) + break; + + /* Abbreviated name. */ + len = strlen(abmon[i]); + if (arg_strncasecmp(abmon[i], bp, len) == 0) + break; + } + + /* Nothing matched. */ + if (i == 12) + return (0); + + tm->tm_mon = i; + bp += len; + break; + + case 'C': /* The century number. */ + LEGAL_ALT(ALT_E); + if (!(conv_num(&bp, &i, 0, 99))) + return (0); + + if (split_year) { + tm->tm_year = (tm->tm_year % 100) + (i * 100); + } else { + tm->tm_year = i * 100; + split_year = 1; + } + break; + + case 'd': /* The day of month. */ + case 'e': + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_mday, 1, 31))) + return (0); + break; + + case 'k': /* The hour (24-hour clock representation). */ + LEGAL_ALT(0); + /* FALLTHROUGH */ + case 'H': + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_hour, 0, 23))) + return (0); + break; + + case 'l': /* The hour (12-hour clock representation). */ + LEGAL_ALT(0); + /* FALLTHROUGH */ + case 'I': + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_hour, 1, 12))) + return (0); + if (tm->tm_hour == 12) + tm->tm_hour = 0; + break; + + case 'j': /* The day of year. */ + LEGAL_ALT(0); + if (!(conv_num(&bp, &i, 1, 366))) + return (0); + tm->tm_yday = i - 1; + break; + + case 'M': /* The minute. */ + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_min, 0, 59))) + return (0); + break; + + case 'm': /* The month. */ + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &i, 1, 12))) + return (0); + tm->tm_mon = i - 1; + break; + + case 'p': /* The locale's equivalent of AM/PM. */ + LEGAL_ALT(0); + /* AM? */ + if (arg_strcasecmp(am_pm[0], bp) == 0) { + if (tm->tm_hour > 11) + return (0); + + bp += strlen(am_pm[0]); + break; + } + /* PM? */ + else if (arg_strcasecmp(am_pm[1], bp) == 0) { + if (tm->tm_hour > 11) + return (0); + + tm->tm_hour += 12; + bp += strlen(am_pm[1]); + break; + } + + /* Nothing matched. */ + return (0); + + case 'S': /* The seconds. */ + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_sec, 0, 61))) + return (0); + break; + + case 'U': /* The week of year, beginning on sunday. */ + case 'W': /* The week of year, beginning on monday. */ + LEGAL_ALT(ALT_O); + /* + * XXX This is bogus, as we can not assume any valid + * information present in the tm structure at this + * point to calculate a real value, so just check the + * range for now. + */ + if (!(conv_num(&bp, &i, 0, 53))) + return (0); + break; + + case 'w': /* The day of week, beginning on sunday. */ + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_wday, 0, 6))) + return (0); + break; + + case 'Y': /* The year. */ + LEGAL_ALT(ALT_E); + if (!(conv_num(&bp, &i, 0, 9999))) + return (0); + + tm->tm_year = i - TM_YEAR_BASE; + break; + + case 'y': /* The year within 100 years of the epoch. */ + LEGAL_ALT(ALT_E | ALT_O); + if (!(conv_num(&bp, &i, 0, 99))) + return (0); + + if (split_year) { + tm->tm_year = ((tm->tm_year / 100) * 100) + i; + break; + } + split_year = 1; + if (i <= 68) + tm->tm_year = i + 2000 - TM_YEAR_BASE; + else + tm->tm_year = i + 1900 - TM_YEAR_BASE; + break; + + /* + * Miscellaneous conversions. + */ + case 'n': /* Any kind of white-space. */ + case 't': + LEGAL_ALT(0); + while (isspace(*bp)) + bp++; + break; + + default: /* Unknown/unsupported conversion. */ + return (0); + } + } + + /* LINTED functional specification */ + return ((char*)bp); +} + +static int conv_num(const char** buf, int* dest, int llim, int ulim) { + int result = 0; + + /* The limit also determines the number of valid digits. */ + int rulim = ulim; + + if (**buf < '0' || **buf > '9') + return (0); + + do { + result *= 10; + result += *(*buf)++ - '0'; + rulim /= 10; + } while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9'); + + if (result < llim || result > ulim) + return (0); + + *dest = result; + return (1); +} +/******************************************************************************* + * arg_dbl: Implements the double command-line option + * + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include "argtable3.h" + +#ifndef ARG_AMALGAMATION +#include "argtable3_private.h" +#endif + +#include + +static void arg_dbl_resetfn(struct arg_dbl* parent) { + ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent)); + parent->count = 0; +} + +static int arg_dbl_scanfn(struct arg_dbl* parent, const char* argval) { + int errorcode = 0; + + if (parent->count == parent->hdr.maxcount) { + /* maximum number of arguments exceeded */ + errorcode = ARG_ERR_MAXCOUNT; + } else if (!argval) { + /* a valid argument with no argument value was given. */ + /* This happens when an optional argument value was invoked. */ + /* leave parent argument value unaltered but still count the argument. */ + parent->count++; + } else { + double val; + char* end; + + /* extract double from argval into val */ + val = strtod(argval, &end); + + /* if success then store result in parent->dval[] array otherwise return error*/ + if (*end == 0) + parent->dval[parent->count++] = val; + else + errorcode = ARG_ERR_BADDOUBLE; + } + + ARG_TRACE(("%s:scanfn(%p) returns %d\n", __FILE__, parent, errorcode)); + return errorcode; +} + +static int arg_dbl_checkfn(struct arg_dbl* parent) { + int errorcode = (parent->count < parent->hdr.mincount) ? ARG_ERR_MINCOUNT : 0; + + ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode)); + return errorcode; +} + +static void arg_dbl_errorfn(struct arg_dbl* parent, arg_dstr_t ds, int errorcode, const char* argval, const char* progname) { + const char* shortopts = parent->hdr.shortopts; + const char* longopts = parent->hdr.longopts; + const char* datatype = parent->hdr.datatype; + + /* make argval NULL safe */ + argval = argval ? argval : ""; + + arg_dstr_catf(ds, "%s: ", progname); + switch (errorcode) { + case ARG_ERR_MINCOUNT: + arg_dstr_cat(ds, "missing option "); + arg_print_option_ds(ds, shortopts, longopts, datatype, "\n"); + break; + + case ARG_ERR_MAXCOUNT: + arg_dstr_cat(ds, "excess option "); + arg_print_option_ds(ds, shortopts, longopts, argval, "\n"); + break; + + case ARG_ERR_BADDOUBLE: + arg_dstr_catf(ds, "invalid argument \"%s\" to option ", argval); + arg_print_option_ds(ds, shortopts, longopts, datatype, "\n"); + break; + } +} + +struct arg_dbl* arg_dbl0(const char* shortopts, const char* longopts, const char* datatype, const char* glossary) { + return arg_dbln(shortopts, longopts, datatype, 0, 1, glossary); +} + +struct arg_dbl* arg_dbl1(const char* shortopts, const char* longopts, const char* datatype, const char* glossary) { + return arg_dbln(shortopts, longopts, datatype, 1, 1, glossary); +} + +struct arg_dbl* arg_dbln(const char* shortopts, const char* longopts, const char* datatype, int mincount, int maxcount, const char* glossary) { + size_t nbytes; + struct arg_dbl* result; + size_t addr; + size_t rem; + + /* foolproof things by ensuring maxcount is not less than mincount */ + maxcount = (maxcount < mincount) ? mincount : maxcount; + + nbytes = sizeof(struct arg_dbl) /* storage for struct arg_dbl */ + + (maxcount + 1) * sizeof(double); /* storage for dval[maxcount] array plus one extra for padding to memory boundary */ + + result = (struct arg_dbl*)xmalloc(nbytes); + + /* init the arg_hdr struct */ + result->hdr.flag = ARG_HASVALUE; + result->hdr.shortopts = shortopts; + result->hdr.longopts = longopts; + result->hdr.datatype = datatype ? datatype : ""; + result->hdr.glossary = glossary; + result->hdr.mincount = mincount; + result->hdr.maxcount = maxcount; + result->hdr.parent = result; + result->hdr.resetfn = (arg_resetfn*)arg_dbl_resetfn; + result->hdr.scanfn = (arg_scanfn*)arg_dbl_scanfn; + result->hdr.checkfn = (arg_checkfn*)arg_dbl_checkfn; + result->hdr.errorfn = (arg_errorfn*)arg_dbl_errorfn; + + /* Store the dval[maxcount] array on the first double boundary that + * immediately follows the arg_dbl struct. We do the memory alignment + * purely for SPARC and Motorola systems. They require floats and + * doubles to be aligned on natural boundaries. + */ + addr = (size_t)(result + 1); + rem = addr % sizeof(double); + result->dval = (double*)(addr + sizeof(double) - rem); + ARG_TRACE(("addr=%p, dval=%p, sizeof(double)=%d rem=%d\n", addr, result->dval, (int)sizeof(double), (int)rem)); + + result->count = 0; + + ARG_TRACE(("arg_dbln() returns %p\n", result)); + return result; +} +/******************************************************************************* + * arg_end: Implements the error handling utilities + * + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include "argtable3.h" + +#ifndef ARG_AMALGAMATION +#include "argtable3_private.h" +#endif + +#include + +static void arg_end_resetfn(struct arg_end* parent) { + ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent)); + parent->count = 0; +} + +static void arg_end_errorfn(void* parent, arg_dstr_t ds, int error, const char* argval, const char* progname) { + /* suppress unreferenced formal parameter warning */ + (void)parent; + + progname = progname ? progname : ""; + argval = argval ? argval : ""; + + arg_dstr_catf(ds, "%s: ", progname); + switch (error) { + case ARG_ELIMIT: + arg_dstr_cat(ds, "too many errors to display"); + break; + case ARG_EMALLOC: + arg_dstr_cat(ds, "insufficient memory"); + break; + case ARG_ENOMATCH: + arg_dstr_catf(ds, "unexpected argument \"%s\"", argval); + break; + case ARG_EMISSARG: + arg_dstr_catf(ds, "option \"%s\" requires an argument", argval); + break; + case ARG_ELONGOPT: + arg_dstr_catf(ds, "invalid option \"%s\"", argval); + break; + default: + arg_dstr_catf(ds, "invalid option \"-%c\"", error); + break; + } + + arg_dstr_cat(ds, "\n"); +} + +struct arg_end* arg_end(int maxcount) { + size_t nbytes; + struct arg_end* result; + + nbytes = sizeof(struct arg_end) + maxcount * sizeof(int) /* storage for int error[maxcount] array*/ + + maxcount * sizeof(void*) /* storage for void* parent[maxcount] array */ + + maxcount * sizeof(char*); /* storage for char* argval[maxcount] array */ + + result = (struct arg_end*)xmalloc(nbytes); + + /* init the arg_hdr struct */ + result->hdr.flag = ARG_TERMINATOR; + result->hdr.shortopts = NULL; + result->hdr.longopts = NULL; + result->hdr.datatype = NULL; + result->hdr.glossary = NULL; + result->hdr.mincount = 1; + result->hdr.maxcount = maxcount; + result->hdr.parent = result; + result->hdr.resetfn = (arg_resetfn*)arg_end_resetfn; + result->hdr.scanfn = NULL; + result->hdr.checkfn = NULL; + result->hdr.errorfn = (arg_errorfn*)arg_end_errorfn; + + /* store error[maxcount] array immediately after struct arg_end */ + result->error = (int*)(result + 1); + + /* store parent[maxcount] array immediately after error[] array */ + result->parent = (void**)(result->error + maxcount); + + /* store argval[maxcount] array immediately after parent[] array */ + result->argval = (const char**)(result->parent + maxcount); + + ARG_TRACE(("arg_end(%d) returns %p\n", maxcount, result)); + return result; +} + +void arg_print_errors_ds(arg_dstr_t ds, struct arg_end* end, const char* progname) { + int i; + ARG_TRACE(("arg_errors()\n")); + for (i = 0; i < end->count; i++) { + struct arg_hdr* errorparent = (struct arg_hdr*)(end->parent[i]); + if (errorparent->errorfn) + errorparent->errorfn(end->parent[i], ds, end->error[i], end->argval[i], progname); + } +} + +void arg_print_errors(FILE* fp, struct arg_end* end, const char* progname) { + arg_dstr_t ds = arg_dstr_create(); + arg_print_errors_ds(ds, end, progname); + fputs(arg_dstr_cstr(ds), fp); + arg_dstr_destroy(ds); +} +/******************************************************************************* + * arg_file: Implements the file command-line option + * + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include "argtable3.h" + +#ifndef ARG_AMALGAMATION +#include "argtable3_private.h" +#endif + +#include +#include + +#ifdef WIN32 +#define FILESEPARATOR1 '\\' +#define FILESEPARATOR2 '/' +#else +#define FILESEPARATOR1 '/' +#define FILESEPARATOR2 '/' +#endif + +static void arg_file_resetfn(struct arg_file* parent) { + ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent)); + parent->count = 0; +} + +/* Returns ptr to the base filename within *filename */ +static const char* arg_basename(const char* filename) { + const char *result = NULL, *result1, *result2; + + /* Find the last occurrence of eother file separator character. */ + /* Two alternative file separator chars are supported as legal */ + /* file separators but not both together in the same filename. */ + result1 = (filename ? strrchr(filename, FILESEPARATOR1) : NULL); + result2 = (filename ? strrchr(filename, FILESEPARATOR2) : NULL); + + if (result2) + result = result2 + 1; /* using FILESEPARATOR2 (the alternative file separator) */ + + if (result1) + result = result1 + 1; /* using FILESEPARATOR1 (the preferred file separator) */ + + if (!result) + result = filename; /* neither file separator was found so basename is the whole filename */ + + /* special cases of "." and ".." are not considered basenames */ + if (result && (strcmp(".", result) == 0 || strcmp("..", result) == 0)) + result = filename + strlen(filename); + + return result; +} + +/* Returns ptr to the file extension within *basename */ +static const char* arg_extension(const char* basename) { + /* find the last occurrence of '.' in basename */ + const char* result = (basename ? strrchr(basename, '.') : NULL); + + /* if no '.' was found then return pointer to end of basename */ + if (basename && !result) + result = basename + strlen(basename); + + /* special case: basenames with a single leading dot (eg ".foo") are not considered as true extensions */ + if (basename && result == basename) + result = basename + strlen(basename); + + /* special case: empty extensions (eg "foo.","foo..") are not considered as true extensions */ + if (basename && result && result[1] == '\0') + result = basename + strlen(basename); + + return result; +} + +static int arg_file_scanfn(struct arg_file* parent, const char* argval) { + int errorcode = 0; + + if (parent->count == parent->hdr.maxcount) { + /* maximum number of arguments exceeded */ + errorcode = ARG_ERR_MAXCOUNT; + } else if (!argval) { + /* a valid argument with no argument value was given. */ + /* This happens when an optional argument value was invoked. */ + /* leave parent arguiment value unaltered but still count the argument. */ + parent->count++; + } else { + parent->filename[parent->count] = argval; + parent->basename[parent->count] = arg_basename(argval); + parent->extension[parent->count] = + arg_extension(parent->basename[parent->count]); /* only seek extensions within the basename (not the file path)*/ + parent->count++; + } + + ARG_TRACE(("%s4:scanfn(%p) returns %d\n", __FILE__, parent, errorcode)); + return errorcode; +} + +static int arg_file_checkfn(struct arg_file* parent) { + int errorcode = (parent->count < parent->hdr.mincount) ? ARG_ERR_MINCOUNT : 0; + + ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode)); + return errorcode; +} + +static void arg_file_errorfn(struct arg_file* parent, arg_dstr_t ds, int errorcode, const char* argval, const char* progname) { + const char* shortopts = parent->hdr.shortopts; + const char* longopts = parent->hdr.longopts; + const char* datatype = parent->hdr.datatype; + + /* make argval NULL safe */ + argval = argval ? argval : ""; + + arg_dstr_catf(ds, "%s: ", progname); + switch (errorcode) { + case ARG_ERR_MINCOUNT: + arg_dstr_cat(ds, "missing option "); + arg_print_option_ds(ds, shortopts, longopts, datatype, "\n"); + break; + + case ARG_ERR_MAXCOUNT: + arg_dstr_cat(ds, "excess option "); + arg_print_option_ds(ds, shortopts, longopts, argval, "\n"); + break; + + default: + arg_dstr_catf(ds, "unknown error at \"%s\"\n", argval); + } +} + +struct arg_file* arg_file0(const char* shortopts, const char* longopts, const char* datatype, const char* glossary) { + return arg_filen(shortopts, longopts, datatype, 0, 1, glossary); +} + +struct arg_file* arg_file1(const char* shortopts, const char* longopts, const char* datatype, const char* glossary) { + return arg_filen(shortopts, longopts, datatype, 1, 1, glossary); +} + +struct arg_file* arg_filen(const char* shortopts, const char* longopts, const char* datatype, int mincount, int maxcount, const char* glossary) { + size_t nbytes; + struct arg_file* result; + int i; + + /* foolproof things by ensuring maxcount is not less than mincount */ + maxcount = (maxcount < mincount) ? mincount : maxcount; + + nbytes = sizeof(struct arg_file) /* storage for struct arg_file */ + + sizeof(char*) * maxcount /* storage for filename[maxcount] array */ + + sizeof(char*) * maxcount /* storage for basename[maxcount] array */ + + sizeof(char*) * maxcount; /* storage for extension[maxcount] array */ + + result = (struct arg_file*)xmalloc(nbytes); + + /* init the arg_hdr struct */ + result->hdr.flag = ARG_HASVALUE; + result->hdr.shortopts = shortopts; + result->hdr.longopts = longopts; + result->hdr.glossary = glossary; + result->hdr.datatype = datatype ? datatype : ""; + result->hdr.mincount = mincount; + result->hdr.maxcount = maxcount; + result->hdr.parent = result; + result->hdr.resetfn = (arg_resetfn*)arg_file_resetfn; + result->hdr.scanfn = (arg_scanfn*)arg_file_scanfn; + result->hdr.checkfn = (arg_checkfn*)arg_file_checkfn; + result->hdr.errorfn = (arg_errorfn*)arg_file_errorfn; + + /* store the filename,basename,extension arrays immediately after the arg_file struct */ + result->filename = (const char**)(result + 1); + result->basename = result->filename + maxcount; + result->extension = result->basename + maxcount; + result->count = 0; + + /* foolproof the string pointers by initialising them with empty strings */ + for (i = 0; i < maxcount; i++) { + result->filename[i] = ""; + result->basename[i] = ""; + result->extension[i] = ""; + } + + ARG_TRACE(("arg_filen() returns %p\n", result)); + return result; +} +/******************************************************************************* + * arg_int: Implements the int command-line option + * + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include "argtable3.h" + +#ifndef ARG_AMALGAMATION +#include "argtable3_private.h" +#endif + +#include +#include +#include + +static void arg_int_resetfn(struct arg_int* parent) { + ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent)); + parent->count = 0; +} + +/* strtol0x() is like strtol() except that the numeric string is */ +/* expected to be prefixed by "0X" where X is a user supplied char. */ +/* The string may optionally be prefixed by white space and + or - */ +/* as in +0X123 or -0X123. */ +/* Once the prefix has been scanned, the remainder of the numeric */ +/* string is converted using strtol() with the given base. */ +/* eg: to parse hex str="-0X12324", specify X='X' and base=16. */ +/* eg: to parse oct str="+0o12324", specify X='O' and base=8. */ +/* eg: to parse bin str="-0B01010", specify X='B' and base=2. */ +/* Failure of conversion is indicated by result where *endptr==str. */ +static long int strtol0X(const char* str, const char** endptr, char X, int base) { + long int val; /* stores result */ + int s = 1; /* sign is +1 or -1 */ + const char* ptr = str; /* ptr to current position in str */ + + /* skip leading whitespace */ + while (isspace(*ptr)) + ptr++; + /* printf("1) %s\n",ptr); */ + + /* scan optional sign character */ + switch (*ptr) { + case '+': + ptr++; + s = 1; + break; + case '-': + ptr++; + s = -1; + break; + default: + s = 1; + break; + } + /* printf("2) %s\n",ptr); */ + + /* '0X' prefix */ + if ((*ptr++) != '0') { + /* printf("failed to detect '0'\n"); */ + *endptr = str; + return 0; + } + /* printf("3) %s\n",ptr); */ + if (toupper(*ptr++) != toupper(X)) { + /* printf("failed to detect '%c'\n",X); */ + *endptr = str; + return 0; + } + /* printf("4) %s\n",ptr); */ + + /* attempt conversion on remainder of string using strtol() */ + val = strtol(ptr, (char**)endptr, base); + if (*endptr == ptr) { + /* conversion failed */ + *endptr = str; + return 0; + } + + /* success */ + return s * val; +} + +/* Returns 1 if str matches suffix (case insensitive). */ +/* Str may contain trailing whitespace, but nothing else. */ +static int detectsuffix(const char* str, const char* suffix) { + /* scan pairwise through strings until mismatch detected */ + while (toupper(*str) == toupper(*suffix)) { + /* printf("'%c' '%c'\n", *str, *suffix); */ + + /* return 1 (success) if match persists until the string terminator */ + if (*str == '\0') + return 1; + + /* next chars */ + str++; + suffix++; + } + /* printf("'%c' '%c' mismatch\n", *str, *suffix); */ + + /* return 0 (fail) if the matching did not consume the entire suffix */ + if (*suffix != 0) + return 0; /* failed to consume entire suffix */ + + /* skip any remaining whitespace in str */ + while (isspace(*str)) + str++; + + /* return 1 (success) if we have reached end of str else return 0 (fail) */ + return (*str == '\0') ? 1 : 0; +} + +static int arg_int_scanfn(struct arg_int* parent, const char* argval) { + int errorcode = 0; + + if (parent->count == parent->hdr.maxcount) { + /* maximum number of arguments exceeded */ + errorcode = ARG_ERR_MAXCOUNT; + } else if (!argval) { + /* a valid argument with no argument value was given. */ + /* This happens when an optional argument value was invoked. */ + /* leave parent arguiment value unaltered but still count the argument. */ + parent->count++; + } else { + long int val; + const char* end; + + /* attempt to extract hex integer (eg: +0x123) from argval into val conversion */ + val = strtol0X(argval, &end, 'X', 16); + if (end == argval) { + /* hex failed, attempt octal conversion (eg +0o123) */ + val = strtol0X(argval, &end, 'O', 8); + if (end == argval) { + /* octal failed, attempt binary conversion (eg +0B101) */ + val = strtol0X(argval, &end, 'B', 2); + if (end == argval) { + /* binary failed, attempt decimal conversion with no prefix (eg 1234) */ + val = strtol(argval, (char**)&end, 10); + if (end == argval) { + /* all supported number formats failed */ + return ARG_ERR_BADINT; + } + } + } + } + + /* Safety check for integer overflow. WARNING: this check */ + /* achieves nothing on machines where size(int)==size(long). */ + if (val > INT_MAX || val < INT_MIN) + errorcode = ARG_ERR_OVERFLOW; + + /* Detect any suffixes (KB,MB,GB) and multiply argument value appropriately. */ + /* We need to be mindful of integer overflows when using such big numbers. */ + if (detectsuffix(end, "KB")) /* kilobytes */ + { + if (val > (INT_MAX / 1024) || val < (INT_MIN / 1024)) + errorcode = ARG_ERR_OVERFLOW; /* Overflow would occur if we proceed */ + else + val *= 1024; /* 1KB = 1024 */ + } else if (detectsuffix(end, "MB")) /* megabytes */ + { + if (val > (INT_MAX / 1048576) || val < (INT_MIN / 1048576)) + errorcode = ARG_ERR_OVERFLOW; /* Overflow would occur if we proceed */ + else + val *= 1048576; /* 1MB = 1024*1024 */ + } else if (detectsuffix(end, "GB")) /* gigabytes */ + { + if (val > (INT_MAX / 1073741824) || val < (INT_MIN / 1073741824)) + errorcode = ARG_ERR_OVERFLOW; /* Overflow would occur if we proceed */ + else + val *= 1073741824; /* 1GB = 1024*1024*1024 */ + } else if (!detectsuffix(end, "")) + errorcode = ARG_ERR_BADINT; /* invalid suffix detected */ + + /* if success then store result in parent->ival[] array */ + if (errorcode == 0) + parent->ival[parent->count++] = (int)val; + } + + /* printf("%s:scanfn(%p,%p) returns %d\n",__FILE__,parent,argval,errorcode); */ + return errorcode; +} + +static int arg_int_checkfn(struct arg_int* parent) { + int errorcode = (parent->count < parent->hdr.mincount) ? ARG_ERR_MINCOUNT : 0; + /*printf("%s:checkfn(%p) returns %d\n",__FILE__,parent,errorcode);*/ + return errorcode; +} + +static void arg_int_errorfn(struct arg_int* parent, arg_dstr_t ds, int errorcode, const char* argval, const char* progname) { + const char* shortopts = parent->hdr.shortopts; + const char* longopts = parent->hdr.longopts; + const char* datatype = parent->hdr.datatype; + + /* make argval NULL safe */ + argval = argval ? argval : ""; + + arg_dstr_catf(ds, "%s: ", progname); + switch (errorcode) { + case ARG_ERR_MINCOUNT: + arg_dstr_cat(ds, "missing option "); + arg_print_option_ds(ds, shortopts, longopts, datatype, "\n"); + break; + + case ARG_ERR_MAXCOUNT: + arg_dstr_cat(ds, "excess option "); + arg_print_option_ds(ds, shortopts, longopts, argval, "\n"); + break; + + case ARG_ERR_BADINT: + arg_dstr_catf(ds, "invalid argument \"%s\" to option ", argval); + arg_print_option_ds(ds, shortopts, longopts, datatype, "\n"); + break; + + case ARG_ERR_OVERFLOW: + arg_dstr_cat(ds, "integer overflow at option "); + arg_print_option_ds(ds, shortopts, longopts, datatype, " "); + arg_dstr_catf(ds, "(%s is too large)\n", argval); + break; + } +} + +struct arg_int* arg_int0(const char* shortopts, const char* longopts, const char* datatype, const char* glossary) { + return arg_intn(shortopts, longopts, datatype, 0, 1, glossary); +} + +struct arg_int* arg_int1(const char* shortopts, const char* longopts, const char* datatype, const char* glossary) { + return arg_intn(shortopts, longopts, datatype, 1, 1, glossary); +} + +struct arg_int* arg_intn(const char* shortopts, const char* longopts, const char* datatype, int mincount, int maxcount, const char* glossary) { + size_t nbytes; + struct arg_int* result; + + /* foolproof things by ensuring maxcount is not less than mincount */ + maxcount = (maxcount < mincount) ? mincount : maxcount; + + nbytes = sizeof(struct arg_int) /* storage for struct arg_int */ + + maxcount * sizeof(int); /* storage for ival[maxcount] array */ + + result = (struct arg_int*)xmalloc(nbytes); + + /* init the arg_hdr struct */ + result->hdr.flag = ARG_HASVALUE; + result->hdr.shortopts = shortopts; + result->hdr.longopts = longopts; + result->hdr.datatype = datatype ? datatype : ""; + result->hdr.glossary = glossary; + result->hdr.mincount = mincount; + result->hdr.maxcount = maxcount; + result->hdr.parent = result; + result->hdr.resetfn = (arg_resetfn*)arg_int_resetfn; + result->hdr.scanfn = (arg_scanfn*)arg_int_scanfn; + result->hdr.checkfn = (arg_checkfn*)arg_int_checkfn; + result->hdr.errorfn = (arg_errorfn*)arg_int_errorfn; + + /* store the ival[maxcount] array immediately after the arg_int struct */ + result->ival = (int*)(result + 1); + result->count = 0; + + ARG_TRACE(("arg_intn() returns %p\n", result)); + return result; +} +/******************************************************************************* + * arg_lit: Implements the literature command-line option + * + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include "argtable3.h" + +#ifndef ARG_AMALGAMATION +#include "argtable3_private.h" +#endif + +#include + +static void arg_lit_resetfn(struct arg_lit* parent) { + ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent)); + parent->count = 0; +} + +static int arg_lit_scanfn(struct arg_lit* parent, const char* argval) { + int errorcode = 0; + if (parent->count < parent->hdr.maxcount) + parent->count++; + else + errorcode = ARG_ERR_MAXCOUNT; + + ARG_TRACE(("%s:scanfn(%p,%s) returns %d\n", __FILE__, parent, argval, errorcode)); + return errorcode; +} + +static int arg_lit_checkfn(struct arg_lit* parent) { + int errorcode = (parent->count < parent->hdr.mincount) ? ARG_ERR_MINCOUNT : 0; + ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode)); + return errorcode; +} + +static void arg_lit_errorfn(struct arg_lit* parent, arg_dstr_t ds, int errorcode, const char* argval, const char* progname) { + const char* shortopts = parent->hdr.shortopts; + const char* longopts = parent->hdr.longopts; + const char* datatype = parent->hdr.datatype; + + switch (errorcode) { + case ARG_ERR_MINCOUNT: + arg_dstr_catf(ds, "%s: missing option ", progname); + arg_print_option_ds(ds, shortopts, longopts, datatype, "\n"); + arg_dstr_cat(ds, "\n"); + break; + + case ARG_ERR_MAXCOUNT: + arg_dstr_catf(ds, "%s: extraneous option ", progname); + arg_print_option_ds(ds, shortopts, longopts, datatype, "\n"); + break; + } + + ARG_TRACE(("%s:errorfn(%p, %p, %d, %s, %s)\n", __FILE__, parent, ds, errorcode, argval, progname)); +} + +struct arg_lit* arg_lit0(const char* shortopts, const char* longopts, const char* glossary) { + return arg_litn(shortopts, longopts, 0, 1, glossary); +} + +struct arg_lit* arg_lit1(const char* shortopts, const char* longopts, const char* glossary) { + return arg_litn(shortopts, longopts, 1, 1, glossary); +} + +struct arg_lit* arg_litn(const char* shortopts, const char* longopts, int mincount, int maxcount, const char* glossary) { + struct arg_lit* result; + + /* foolproof things by ensuring maxcount is not less than mincount */ + maxcount = (maxcount < mincount) ? mincount : maxcount; + + result = (struct arg_lit*)xmalloc(sizeof(struct arg_lit)); + + /* init the arg_hdr struct */ + result->hdr.flag = 0; + result->hdr.shortopts = shortopts; + result->hdr.longopts = longopts; + result->hdr.datatype = NULL; + result->hdr.glossary = glossary; + result->hdr.mincount = mincount; + result->hdr.maxcount = maxcount; + result->hdr.parent = result; + result->hdr.resetfn = (arg_resetfn*)arg_lit_resetfn; + result->hdr.scanfn = (arg_scanfn*)arg_lit_scanfn; + result->hdr.checkfn = (arg_checkfn*)arg_lit_checkfn; + result->hdr.errorfn = (arg_errorfn*)arg_lit_errorfn; + + /* init local variables */ + result->count = 0; + + ARG_TRACE(("arg_litn() returns %p\n", result)); + return result; +} +/******************************************************************************* + * arg_rem: Implements the rem command-line option + * + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include "argtable3.h" + +#ifndef ARG_AMALGAMATION +#include "argtable3_private.h" +#endif + +#include + +struct arg_rem* arg_rem(const char* datatype, const char* glossary) { + struct arg_rem* result = (struct arg_rem*)xmalloc(sizeof(struct arg_rem)); + + result->hdr.flag = 0; + result->hdr.shortopts = NULL; + result->hdr.longopts = NULL; + result->hdr.datatype = datatype; + result->hdr.glossary = glossary; + result->hdr.mincount = 1; + result->hdr.maxcount = 1; + result->hdr.parent = result; + result->hdr.resetfn = NULL; + result->hdr.scanfn = NULL; + result->hdr.checkfn = NULL; + result->hdr.errorfn = NULL; + + ARG_TRACE(("arg_rem() returns %p\n", result)); + return result; +} +/******************************************************************************* + * arg_rex: Implements the regex command-line option + * + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include "argtable3.h" + +#ifndef ARG_AMALGAMATION +#include "argtable3_private.h" +#endif + +#include +#include + +#ifndef _TREX_H_ +#define _TREX_H_ + +/* + * This module uses the T-Rex regular expression library to implement the regex + * logic. Here is the copyright notice of the library: + * + * Copyright (C) 2003-2006 Alberto Demichelis + * + * This software is provided 'as-is', without any express + * or implied warranty. In no event will the authors be held + * liable for any damages arising from the use of this software. + * + * Permission is granted to anyone to use this software for + * any purpose, including commercial applications, and to alter + * it and redistribute it freely, subject to the following restrictions: + * + * 1. The origin of this software must not be misrepresented; + * you must not claim that you wrote the original software. + * If you use this software in a product, an acknowledgment + * in the product documentation would be appreciated but + * is not required. + * + * 2. Altered source versions must be plainly marked as such, + * and must not be misrepresented as being the original software. + * + * 3. This notice may not be removed or altered from any + * source distribution. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define TRexChar char +#define MAX_CHAR 0xFF +#define _TREXC(c) (c) +#define trex_strlen strlen +#define trex_printf printf + +#ifndef TREX_API +#define TREX_API extern +#endif + +#define TRex_True 1 +#define TRex_False 0 + +#define TREX_ICASE ARG_REX_ICASE + +typedef unsigned int TRexBool; +typedef struct TRex TRex; + +typedef struct { + const TRexChar* begin; + int len; +} TRexMatch; + +TREX_API TRex* trex_compile(const TRexChar* pattern, const TRexChar** error, int flags); +TREX_API void trex_free(TRex* exp); +TREX_API TRexBool trex_match(TRex* exp, const TRexChar* text); +TREX_API TRexBool trex_search(TRex* exp, const TRexChar* text, const TRexChar** out_begin, const TRexChar** out_end); +TREX_API TRexBool +trex_searchrange(TRex* exp, const TRexChar* text_begin, const TRexChar* text_end, const TRexChar** out_begin, const TRexChar** out_end); +TREX_API int trex_getsubexpcount(TRex* exp); +TREX_API TRexBool trex_getsubexp(TRex* exp, int n, TRexMatch* subexp); + +#ifdef __cplusplus +} +#endif + +#endif + +struct privhdr { + const char* pattern; + int flags; +}; + +static void arg_rex_resetfn(struct arg_rex* parent) { + ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent)); + parent->count = 0; +} + +static int arg_rex_scanfn(struct arg_rex* parent, const char* argval) { + int errorcode = 0; + const TRexChar* error = NULL; + TRex* rex = NULL; + TRexBool is_match = TRex_False; + + if (parent->count == parent->hdr.maxcount) { + /* maximum number of arguments exceeded */ + errorcode = ARG_ERR_MAXCOUNT; + } else if (!argval) { + /* a valid argument with no argument value was given. */ + /* This happens when an optional argument value was invoked. */ + /* leave parent argument value unaltered but still count the argument. */ + parent->count++; + } else { + struct privhdr* priv = (struct privhdr*)parent->hdr.priv; + + /* test the current argument value for a match with the regular expression */ + /* if a match is detected, record the argument value in the arg_rex struct */ + + rex = trex_compile(priv->pattern, &error, priv->flags); + is_match = trex_match(rex, argval); + if (!is_match) + errorcode = ARG_ERR_REGNOMATCH; + else + parent->sval[parent->count++] = argval; + + trex_free(rex); + } + + ARG_TRACE(("%s:scanfn(%p) returns %d\n", __FILE__, parent, errorcode)); + return errorcode; +} + +static int arg_rex_checkfn(struct arg_rex* parent) { + int errorcode = (parent->count < parent->hdr.mincount) ? ARG_ERR_MINCOUNT : 0; +#if 0 + struct privhdr *priv = (struct privhdr*)parent->hdr.priv; + + /* free the regex "program" we constructed in resetfn */ + regfree(&(priv->regex)); + + /*printf("%s:checkfn(%p) returns %d\n",__FILE__,parent,errorcode);*/ +#endif + return errorcode; +} + +static void arg_rex_errorfn(struct arg_rex* parent, arg_dstr_t ds, int errorcode, const char* argval, const char* progname) { + const char* shortopts = parent->hdr.shortopts; + const char* longopts = parent->hdr.longopts; + const char* datatype = parent->hdr.datatype; + + /* make argval NULL safe */ + argval = argval ? argval : ""; + + arg_dstr_catf(ds, "%s: ", progname); + switch (errorcode) { + case ARG_ERR_MINCOUNT: + arg_dstr_cat(ds, "missing option "); + arg_print_option_ds(ds, shortopts, longopts, datatype, "\n"); + break; + + case ARG_ERR_MAXCOUNT: + arg_dstr_cat(ds, "excess option "); + arg_print_option_ds(ds, shortopts, longopts, argval, "\n"); + break; + + case ARG_ERR_REGNOMATCH: + arg_dstr_cat(ds, "illegal value "); + arg_print_option_ds(ds, shortopts, longopts, argval, "\n"); + break; + + default: { + #if 0 + char errbuff[256]; + regerror(errorcode, NULL, errbuff, sizeof(errbuff)); + printf("%s\n", errbuff); + #endif + } break; + } +} + +struct arg_rex* arg_rex0(const char* shortopts, const char* longopts, const char* pattern, const char* datatype, int flags, const char* glossary) { + return arg_rexn(shortopts, longopts, pattern, datatype, 0, 1, flags, glossary); +} + +struct arg_rex* arg_rex1(const char* shortopts, const char* longopts, const char* pattern, const char* datatype, int flags, const char* glossary) { + return arg_rexn(shortopts, longopts, pattern, datatype, 1, 1, flags, glossary); +} + +struct arg_rex* arg_rexn(const char* shortopts, + const char* longopts, + const char* pattern, + const char* datatype, + int mincount, + int maxcount, + int flags, + const char* glossary) { + size_t nbytes; + struct arg_rex* result; + struct privhdr* priv; + int i; + const TRexChar* error = NULL; + TRex* rex = NULL; + + if (!pattern) { + printf("argtable: ERROR - illegal regular expression pattern \"(NULL)\"\n"); + printf("argtable: Bad argument table.\n"); + return NULL; + } + + /* foolproof things by ensuring maxcount is not less than mincount */ + maxcount = (maxcount < mincount) ? mincount : maxcount; + + nbytes = sizeof(struct arg_rex) /* storage for struct arg_rex */ + + sizeof(struct privhdr) /* storage for private arg_rex data */ + + maxcount * sizeof(char*); /* storage for sval[maxcount] array */ + + /* init the arg_hdr struct */ + result = (struct arg_rex*)xmalloc(nbytes); + result->hdr.flag = ARG_HASVALUE; + result->hdr.shortopts = shortopts; + result->hdr.longopts = longopts; + result->hdr.datatype = datatype ? datatype : pattern; + result->hdr.glossary = glossary; + result->hdr.mincount = mincount; + result->hdr.maxcount = maxcount; + result->hdr.parent = result; + result->hdr.resetfn = (arg_resetfn*)arg_rex_resetfn; + result->hdr.scanfn = (arg_scanfn*)arg_rex_scanfn; + result->hdr.checkfn = (arg_checkfn*)arg_rex_checkfn; + result->hdr.errorfn = (arg_errorfn*)arg_rex_errorfn; + + /* store the arg_rex_priv struct immediately after the arg_rex struct */ + result->hdr.priv = result + 1; + priv = (struct privhdr*)(result->hdr.priv); + priv->pattern = pattern; + priv->flags = flags; + + /* store the sval[maxcount] array immediately after the arg_rex_priv struct */ + result->sval = (const char**)(priv + 1); + result->count = 0; + + /* foolproof the string pointers by initializing them to reference empty strings */ + for (i = 0; i < maxcount; i++) + result->sval[i] = ""; + + /* here we construct and destroy a regex representation of the regular + * expression for no other reason than to force any regex errors to be + * trapped now rather than later. If we don't, then errors may go undetected + * until an argument is actually parsed. + */ + + rex = trex_compile(priv->pattern, &error, priv->flags); + if (rex == NULL) { + ARG_LOG(("argtable: %s \"%s\"\n", error ? error : _TREXC("undefined"), priv->pattern)); + ARG_LOG(("argtable: Bad argument table.\n")); + } + + trex_free(rex); + + ARG_TRACE(("arg_rexn() returns %p\n", result)); + return result; +} + +/* see copyright notice in trex.h */ +#include +#include +#include +#include + +#ifdef _UINCODE +#define scisprint iswprint +#define scstrlen wcslen +#define scprintf wprintf +#define _SC(x) L(x) +#else +#define scisprint isprint +#define scstrlen strlen +#define scprintf printf +#define _SC(x) (x) +#endif + +#ifdef _DEBUG +#include + +static const TRexChar* g_nnames[] = {_SC("NONE"), _SC("OP_GREEDY"), _SC("OP_OR"), _SC("OP_EXPR"), _SC("OP_NOCAPEXPR"), + _SC("OP_DOT"), _SC("OP_CLASS"), _SC("OP_CCLASS"), _SC("OP_NCLASS"), _SC("OP_RANGE"), + _SC("OP_CHAR"), _SC("OP_EOL"), _SC("OP_BOL"), _SC("OP_WB")}; + +#endif +#define OP_GREEDY (MAX_CHAR + 1) /* * + ? {n} */ +#define OP_OR (MAX_CHAR + 2) +#define OP_EXPR (MAX_CHAR + 3) /* parentesis () */ +#define OP_NOCAPEXPR (MAX_CHAR + 4) /* parentesis (?:) */ +#define OP_DOT (MAX_CHAR + 5) +#define OP_CLASS (MAX_CHAR + 6) +#define OP_CCLASS (MAX_CHAR + 7) +#define OP_NCLASS (MAX_CHAR + 8) /* negates class the [^ */ +#define OP_RANGE (MAX_CHAR + 9) +#define OP_CHAR (MAX_CHAR + 10) +#define OP_EOL (MAX_CHAR + 11) +#define OP_BOL (MAX_CHAR + 12) +#define OP_WB (MAX_CHAR + 13) + +#define TREX_SYMBOL_ANY_CHAR ('.') +#define TREX_SYMBOL_GREEDY_ONE_OR_MORE ('+') +#define TREX_SYMBOL_GREEDY_ZERO_OR_MORE ('*') +#define TREX_SYMBOL_GREEDY_ZERO_OR_ONE ('?') +#define TREX_SYMBOL_BRANCH ('|') +#define TREX_SYMBOL_END_OF_STRING ('$') +#define TREX_SYMBOL_BEGINNING_OF_STRING ('^') +#define TREX_SYMBOL_ESCAPE_CHAR ('\\') + +typedef int TRexNodeType; + +typedef struct tagTRexNode { + TRexNodeType type; + int left; + int right; + int next; +} TRexNode; + +struct TRex { + const TRexChar* _eol; + const TRexChar* _bol; + const TRexChar* _p; + int _first; + int _op; + TRexNode* _nodes; + int _nallocated; + int _nsize; + int _nsubexpr; + TRexMatch* _matches; + int _currsubexp; + void* _jmpbuf; + const TRexChar** _error; + int _flags; +}; + +static int trex_list(TRex* exp); + +static int trex_newnode(TRex* exp, TRexNodeType type) { + TRexNode n; + int newid; + n.type = type; + n.next = n.right = n.left = -1; + if (type == OP_EXPR) + n.right = exp->_nsubexpr++; + if (exp->_nallocated < (exp->_nsize + 1)) { + exp->_nallocated *= 2; + exp->_nodes = (TRexNode*)xrealloc(exp->_nodes, exp->_nallocated * sizeof(TRexNode)); + } + exp->_nodes[exp->_nsize++] = n; + newid = exp->_nsize - 1; + return (int)newid; +} + +static void trex_error(TRex* exp, const TRexChar* error) { + if (exp->_error) + *exp->_error = error; + longjmp(*((jmp_buf*)exp->_jmpbuf), -1); +} + +static void trex_expect(TRex* exp, int n) { + if ((*exp->_p) != n) + trex_error(exp, _SC("expected paren")); + exp->_p++; +} + +static TRexChar trex_escapechar(TRex* exp) { + if (*exp->_p == TREX_SYMBOL_ESCAPE_CHAR) { + exp->_p++; + switch (*exp->_p) { + case 'v': + exp->_p++; + return '\v'; + case 'n': + exp->_p++; + return '\n'; + case 't': + exp->_p++; + return '\t'; + case 'r': + exp->_p++; + return '\r'; + case 'f': + exp->_p++; + return '\f'; + default: + return (*exp->_p++); + } + } else if (!scisprint(*exp->_p)) + trex_error(exp, _SC("letter expected")); + return (*exp->_p++); +} + +static int trex_charclass(TRex* exp, int classid) { + int n = trex_newnode(exp, OP_CCLASS); + exp->_nodes[n].left = classid; + return n; +} + +static int trex_charnode(TRex* exp, TRexBool isclass) { + TRexChar t; + if (*exp->_p == TREX_SYMBOL_ESCAPE_CHAR) { + exp->_p++; + switch (*exp->_p) { + case 'n': + exp->_p++; + return trex_newnode(exp, '\n'); + case 't': + exp->_p++; + return trex_newnode(exp, '\t'); + case 'r': + exp->_p++; + return trex_newnode(exp, '\r'); + case 'f': + exp->_p++; + return trex_newnode(exp, '\f'); + case 'v': + exp->_p++; + return trex_newnode(exp, '\v'); + case 'a': + case 'A': + case 'w': + case 'W': + case 's': + case 'S': + case 'd': + case 'D': + case 'x': + case 'X': + case 'c': + case 'C': + case 'p': + case 'P': + case 'l': + case 'u': { + t = *exp->_p; + exp->_p++; + return trex_charclass(exp, t); + } + case 'b': + case 'B': + if (!isclass) { + int node = trex_newnode(exp, OP_WB); + exp->_nodes[node].left = *exp->_p; + exp->_p++; + return node; + } + /* fall through */ + default: + t = *exp->_p; + exp->_p++; + return trex_newnode(exp, t); + } + } else if (!scisprint(*exp->_p)) { + trex_error(exp, _SC("letter expected")); + } + t = *exp->_p; + exp->_p++; + return trex_newnode(exp, t); +} +static int trex_class(TRex* exp) { + int ret = -1; + int first = -1, chain; + if (*exp->_p == TREX_SYMBOL_BEGINNING_OF_STRING) { + ret = trex_newnode(exp, OP_NCLASS); + exp->_p++; + } else + ret = trex_newnode(exp, OP_CLASS); + + if (*exp->_p == ']') + trex_error(exp, _SC("empty class")); + chain = ret; + while (*exp->_p != ']' && exp->_p != exp->_eol) { + if (*exp->_p == '-' && first != -1) { + int r, t; + if (*exp->_p++ == ']') + trex_error(exp, _SC("unfinished range")); + r = trex_newnode(exp, OP_RANGE); + if (first > *exp->_p) + trex_error(exp, _SC("invalid range")); + if (exp->_nodes[first].type == OP_CCLASS) + trex_error(exp, _SC("cannot use character classes in ranges")); + exp->_nodes[r].left = exp->_nodes[first].type; + t = trex_escapechar(exp); + exp->_nodes[r].right = t; + exp->_nodes[chain].next = r; + chain = r; + first = -1; + } else { + if (first != -1) { + int c = first; + exp->_nodes[chain].next = c; + chain = c; + first = trex_charnode(exp, TRex_True); + } else { + first = trex_charnode(exp, TRex_True); + } + } + } + if (first != -1) { + int c = first; + exp->_nodes[chain].next = c; + chain = c; + first = -1; + } + /* hack? */ + exp->_nodes[ret].left = exp->_nodes[ret].next; + exp->_nodes[ret].next = -1; + return ret; +} + +static int trex_parsenumber(TRex* exp) { + int ret = *exp->_p - '0'; + int positions = 10; + exp->_p++; + while (isdigit(*exp->_p)) { + ret = ret * 10 + (*exp->_p++ - '0'); + if (positions == 1000000000) + trex_error(exp, _SC("overflow in numeric constant")); + positions *= 10; + }; + return ret; +} + +static int trex_element(TRex* exp) { + int ret = -1; + switch (*exp->_p) { + case '(': { + int expr, newn; + exp->_p++; + + if (*exp->_p == '?') { + exp->_p++; + trex_expect(exp, ':'); + expr = trex_newnode(exp, OP_NOCAPEXPR); + } else + expr = trex_newnode(exp, OP_EXPR); + newn = trex_list(exp); + exp->_nodes[expr].left = newn; + ret = expr; + trex_expect(exp, ')'); + } break; + case '[': + exp->_p++; + ret = trex_class(exp); + trex_expect(exp, ']'); + break; + case TREX_SYMBOL_END_OF_STRING: + exp->_p++; + ret = trex_newnode(exp, OP_EOL); + break; + case TREX_SYMBOL_ANY_CHAR: + exp->_p++; + ret = trex_newnode(exp, OP_DOT); + break; + default: + ret = trex_charnode(exp, TRex_False); + break; + } + + { + TRexBool isgreedy = TRex_False; + unsigned short p0 = 0, p1 = 0; + switch (*exp->_p) { + case TREX_SYMBOL_GREEDY_ZERO_OR_MORE: + p0 = 0; + p1 = 0xFFFF; + exp->_p++; + isgreedy = TRex_True; + break; + case TREX_SYMBOL_GREEDY_ONE_OR_MORE: + p0 = 1; + p1 = 0xFFFF; + exp->_p++; + isgreedy = TRex_True; + break; + case TREX_SYMBOL_GREEDY_ZERO_OR_ONE: + p0 = 0; + p1 = 1; + exp->_p++; + isgreedy = TRex_True; + break; + case '{': + exp->_p++; + if (!isdigit(*exp->_p)) + trex_error(exp, _SC("number expected")); + p0 = (unsigned short)trex_parsenumber(exp); + /*******************************/ + switch (*exp->_p) { + case '}': + p1 = p0; + exp->_p++; + break; + case ',': + exp->_p++; + p1 = 0xFFFF; + if (isdigit(*exp->_p)) { + p1 = (unsigned short)trex_parsenumber(exp); + } + trex_expect(exp, '}'); + break; + default: + trex_error(exp, _SC(", or } expected")); + } + /*******************************/ + isgreedy = TRex_True; + break; + } + if (isgreedy) { + int nnode = trex_newnode(exp, OP_GREEDY); + exp->_nodes[nnode].left = ret; + exp->_nodes[nnode].right = ((p0) << 16) | p1; + ret = nnode; + } + } + if ((*exp->_p != TREX_SYMBOL_BRANCH) && (*exp->_p != ')') && (*exp->_p != TREX_SYMBOL_GREEDY_ZERO_OR_MORE) && + (*exp->_p != TREX_SYMBOL_GREEDY_ONE_OR_MORE) && (*exp->_p != '\0')) { + int nnode = trex_element(exp); + exp->_nodes[ret].next = nnode; + } + + return ret; +} + +static int trex_list(TRex* exp) { + int ret = -1, e; + if (*exp->_p == TREX_SYMBOL_BEGINNING_OF_STRING) { + exp->_p++; + ret = trex_newnode(exp, OP_BOL); + } + e = trex_element(exp); + if (ret != -1) { + exp->_nodes[ret].next = e; + } else + ret = e; + + if (*exp->_p == TREX_SYMBOL_BRANCH) { + int temp, tright; + exp->_p++; + temp = trex_newnode(exp, OP_OR); + exp->_nodes[temp].left = ret; + tright = trex_list(exp); + exp->_nodes[temp].right = tright; + ret = temp; + } + return ret; +} + +static TRexBool trex_matchcclass(int cclass, TRexChar c) { + switch (cclass) { + case 'a': + return isalpha(c) ? TRex_True : TRex_False; + case 'A': + return !isalpha(c) ? TRex_True : TRex_False; + case 'w': + return (isalnum(c) || c == '_') ? TRex_True : TRex_False; + case 'W': + return (!isalnum(c) && c != '_') ? TRex_True : TRex_False; + case 's': + return isspace(c) ? TRex_True : TRex_False; + case 'S': + return !isspace(c) ? TRex_True : TRex_False; + case 'd': + return isdigit(c) ? TRex_True : TRex_False; + case 'D': + return !isdigit(c) ? TRex_True : TRex_False; + case 'x': + return isxdigit(c) ? TRex_True : TRex_False; + case 'X': + return !isxdigit(c) ? TRex_True : TRex_False; + case 'c': + return iscntrl(c) ? TRex_True : TRex_False; + case 'C': + return !iscntrl(c) ? TRex_True : TRex_False; + case 'p': + return ispunct(c) ? TRex_True : TRex_False; + case 'P': + return !ispunct(c) ? TRex_True : TRex_False; + case 'l': + return islower(c) ? TRex_True : TRex_False; + case 'u': + return isupper(c) ? TRex_True : TRex_False; + } + return TRex_False; /*cannot happen*/ +} + +static TRexBool trex_matchclass(TRex* exp, TRexNode* node, TRexChar c) { + do { + switch (node->type) { + case OP_RANGE: + if (exp->_flags & TREX_ICASE) { + if (c >= toupper(node->left) && c <= toupper(node->right)) + return TRex_True; + if (c >= tolower(node->left) && c <= tolower(node->right)) + return TRex_True; + } else { + if (c >= node->left && c <= node->right) + return TRex_True; + } + break; + case OP_CCLASS: + if (trex_matchcclass(node->left, c)) + return TRex_True; + break; + default: + if (exp->_flags & TREX_ICASE) { + if (c == tolower(node->type) || c == toupper(node->type)) + return TRex_True; + } else { + if (c == node->type) + return TRex_True; + } + } + } while ((node->next != -1) && ((node = &exp->_nodes[node->next]) != NULL)); + return TRex_False; +} + +static const TRexChar* trex_matchnode(TRex* exp, TRexNode* node, const TRexChar* str, TRexNode* next) { + TRexNodeType type = node->type; + switch (type) { + case OP_GREEDY: { + /* TRexNode *greedystop = (node->next != -1) ? &exp->_nodes[node->next] : NULL; */ + TRexNode* greedystop = NULL; + int p0 = (node->right >> 16) & 0x0000FFFF, p1 = node->right & 0x0000FFFF, nmaches = 0; + const TRexChar *s = str, *good = str; + + if (node->next != -1) { + greedystop = &exp->_nodes[node->next]; + } else { + greedystop = next; + } + + while ((nmaches == 0xFFFF || nmaches < p1)) { + const TRexChar* stop; + if ((s = trex_matchnode(exp, &exp->_nodes[node->left], s, greedystop)) == NULL) + break; + nmaches++; + good = s; + if (greedystop) { + /* checks that 0 matches satisfy the expression(if so skips) */ + /* if not would always stop(for instance if is a '?') */ + if (greedystop->type != OP_GREEDY || (greedystop->type == OP_GREEDY && ((greedystop->right >> 16) & 0x0000FFFF) != 0)) { + TRexNode* gnext = NULL; + if (greedystop->next != -1) { + gnext = &exp->_nodes[greedystop->next]; + } else if (next && next->next != -1) { + gnext = &exp->_nodes[next->next]; + } + stop = trex_matchnode(exp, greedystop, s, gnext); + if (stop) { + /* if satisfied stop it */ + if (p0 == p1 && p0 == nmaches) + break; + else if (nmaches >= p0 && p1 == 0xFFFF) + break; + else if (nmaches >= p0 && nmaches <= p1) + break; + } + } + } + + if (s >= exp->_eol) + break; + } + if (p0 == p1 && p0 == nmaches) + return good; + else if (nmaches >= p0 && p1 == 0xFFFF) + return good; + else if (nmaches >= p0 && nmaches <= p1) + return good; + return NULL; + } + case OP_OR: { + const TRexChar* asd = str; + TRexNode* temp = &exp->_nodes[node->left]; + while ((asd = trex_matchnode(exp, temp, asd, NULL)) != NULL) { + if (temp->next != -1) + temp = &exp->_nodes[temp->next]; + else + return asd; + } + asd = str; + temp = &exp->_nodes[node->right]; + while ((asd = trex_matchnode(exp, temp, asd, NULL)) != NULL) { + if (temp->next != -1) + temp = &exp->_nodes[temp->next]; + else + return asd; + } + return NULL; + break; + } + case OP_EXPR: + case OP_NOCAPEXPR: { + TRexNode* n = &exp->_nodes[node->left]; + const TRexChar* cur = str; + int capture = -1; + if (node->type != OP_NOCAPEXPR && node->right == exp->_currsubexp) { + capture = exp->_currsubexp; + exp->_matches[capture].begin = cur; + exp->_currsubexp++; + } + + do { + TRexNode* subnext = NULL; + if (n->next != -1) { + subnext = &exp->_nodes[n->next]; + } else { + subnext = next; + } + if ((cur = trex_matchnode(exp, n, cur, subnext)) == NULL) { + if (capture != -1) { + exp->_matches[capture].begin = 0; + exp->_matches[capture].len = 0; + } + return NULL; + } + } while ((n->next != -1) && ((n = &exp->_nodes[n->next]) != NULL)); + + if (capture != -1) + exp->_matches[capture].len = (int)(cur - exp->_matches[capture].begin); + return cur; + } + case OP_WB: + if ((str == exp->_bol && !isspace(*str)) || (str == exp->_eol && !isspace(*(str - 1))) || (!isspace(*str) && isspace(*(str + 1))) || + (isspace(*str) && !isspace(*(str + 1)))) { + return (node->left == 'b') ? str : NULL; + } + return (node->left == 'b') ? NULL : str; + case OP_BOL: + if (str == exp->_bol) + return str; + return NULL; + case OP_EOL: + if (str == exp->_eol) + return str; + return NULL; + case OP_DOT: { + str++; + } + return str; + case OP_NCLASS: + case OP_CLASS: + if (trex_matchclass(exp, &exp->_nodes[node->left], *str) ? (type == OP_CLASS ? TRex_True : TRex_False) + : (type == OP_NCLASS ? TRex_True : TRex_False)) { + str++; + return str; + } + return NULL; + case OP_CCLASS: + if (trex_matchcclass(node->left, *str)) { + str++; + return str; + } + return NULL; + default: /* char */ + if (exp->_flags & TREX_ICASE) { + if (*str != tolower(node->type) && *str != toupper(node->type)) + return NULL; + } else { + if (*str != node->type) + return NULL; + } + str++; + return str; + } +} + +/* public api */ +TRex* trex_compile(const TRexChar* pattern, const TRexChar** error, int flags) { + TRex* exp = (TRex*)xmalloc(sizeof(TRex)); + exp->_eol = exp->_bol = NULL; + exp->_p = pattern; + exp->_nallocated = (int)scstrlen(pattern) * sizeof(TRexChar); + exp->_nodes = (TRexNode*)xmalloc(exp->_nallocated * sizeof(TRexNode)); + exp->_nsize = 0; + exp->_matches = 0; + exp->_nsubexpr = 0; + exp->_first = trex_newnode(exp, OP_EXPR); + exp->_error = error; + exp->_jmpbuf = xmalloc(sizeof(jmp_buf)); + exp->_flags = flags; + if (setjmp(*((jmp_buf*)exp->_jmpbuf)) == 0) { + int res = trex_list(exp); + exp->_nodes[exp->_first].left = res; + if (*exp->_p != '\0') + trex_error(exp, _SC("unexpected character")); +#ifdef _DEBUG + { + int nsize, i; + TRexNode* t; + nsize = exp->_nsize; + t = &exp->_nodes[0]; + scprintf(_SC("\n")); + for (i = 0; i < nsize; i++) { + if (exp->_nodes[i].type > MAX_CHAR) + scprintf(_SC("[%02d] %10s "), i, g_nnames[exp->_nodes[i].type - MAX_CHAR]); + else + scprintf(_SC("[%02d] %10c "), i, exp->_nodes[i].type); + scprintf(_SC("left %02d right %02d next %02d\n"), exp->_nodes[i].left, exp->_nodes[i].right, exp->_nodes[i].next); + } + scprintf(_SC("\n")); + } +#endif + exp->_matches = (TRexMatch*)xmalloc(exp->_nsubexpr * sizeof(TRexMatch)); + memset(exp->_matches, 0, exp->_nsubexpr * sizeof(TRexMatch)); + } else { + trex_free(exp); + return NULL; + } + return exp; +} + +void trex_free(TRex* exp) { + if (exp) { + xfree(exp->_nodes); + xfree(exp->_jmpbuf); + xfree(exp->_matches); + xfree(exp); + } +} + +TRexBool trex_match(TRex* exp, const TRexChar* text) { + const TRexChar* res = NULL; + exp->_bol = text; + exp->_eol = text + scstrlen(text); + exp->_currsubexp = 0; + res = trex_matchnode(exp, exp->_nodes, text, NULL); + if (res == NULL || res != exp->_eol) + return TRex_False; + return TRex_True; +} + +TRexBool trex_searchrange(TRex* exp, const TRexChar* text_begin, const TRexChar* text_end, const TRexChar** out_begin, const TRexChar** out_end) { + const TRexChar* cur = NULL; + int node = exp->_first; + if (text_begin >= text_end) + return TRex_False; + exp->_bol = text_begin; + exp->_eol = text_end; + do { + cur = text_begin; + while (node != -1) { + exp->_currsubexp = 0; + cur = trex_matchnode(exp, &exp->_nodes[node], cur, NULL); + if (!cur) + break; + node = exp->_nodes[node].next; + } + text_begin++; + } while (cur == NULL && text_begin != text_end); + + if (cur == NULL) + return TRex_False; + + --text_begin; + + if (out_begin) + *out_begin = text_begin; + if (out_end) + *out_end = cur; + return TRex_True; +} + +TRexBool trex_search(TRex* exp, const TRexChar* text, const TRexChar** out_begin, const TRexChar** out_end) { + return trex_searchrange(exp, text, text + scstrlen(text), out_begin, out_end); +} + +int trex_getsubexpcount(TRex* exp) { + return exp->_nsubexpr; +} + +TRexBool trex_getsubexp(TRex* exp, int n, TRexMatch* subexp) { + if (n < 0 || n >= exp->_nsubexpr) + return TRex_False; + *subexp = exp->_matches[n]; + return TRex_True; +} +/******************************************************************************* + * arg_str: Implements the str command-line option + * + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include "argtable3.h" + +#ifndef ARG_AMALGAMATION +#include "argtable3_private.h" +#endif + +#include + +static void arg_str_resetfn(struct arg_str* parent) { + int i; + + ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent)); + for (i = 0; i < parent->count; i++) { + parent->sval[i] = ""; + } + parent->count = 0; +} + +static int arg_str_scanfn(struct arg_str* parent, const char* argval) { + int errorcode = 0; + + if (parent->count == parent->hdr.maxcount) { + /* maximum number of arguments exceeded */ + errorcode = ARG_ERR_MAXCOUNT; + } else if (!argval) { + /* a valid argument with no argument value was given. */ + /* This happens when an optional argument value was invoked. */ + /* leave parent argument value unaltered but still count the argument. */ + parent->count++; + } else { + parent->sval[parent->count++] = argval; + } + + ARG_TRACE(("%s:scanfn(%p) returns %d\n", __FILE__, parent, errorcode)); + return errorcode; +} + +static int arg_str_checkfn(struct arg_str* parent) { + int errorcode = (parent->count < parent->hdr.mincount) ? ARG_ERR_MINCOUNT : 0; + + ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode)); + return errorcode; +} + +static void arg_str_errorfn(struct arg_str* parent, arg_dstr_t ds, int errorcode, const char* argval, const char* progname) { + const char* shortopts = parent->hdr.shortopts; + const char* longopts = parent->hdr.longopts; + const char* datatype = parent->hdr.datatype; + + /* make argval NULL safe */ + argval = argval ? argval : ""; + + arg_dstr_catf(ds, "%s: ", progname); + switch (errorcode) { + case ARG_ERR_MINCOUNT: + arg_dstr_cat(ds, "missing option "); + arg_print_option_ds(ds, shortopts, longopts, datatype, "\n"); + break; + + case ARG_ERR_MAXCOUNT: + arg_dstr_cat(ds, "excess option "); + arg_print_option_ds(ds, shortopts, longopts, argval, "\n"); + break; + } +} + +struct arg_str* arg_str0(const char* shortopts, const char* longopts, const char* datatype, const char* glossary) { + return arg_strn(shortopts, longopts, datatype, 0, 1, glossary); +} + +struct arg_str* arg_str1(const char* shortopts, const char* longopts, const char* datatype, const char* glossary) { + return arg_strn(shortopts, longopts, datatype, 1, 1, glossary); +} + +struct arg_str* arg_strn(const char* shortopts, const char* longopts, const char* datatype, int mincount, int maxcount, const char* glossary) { + size_t nbytes; + struct arg_str* result; + int i; + + /* should not allow this stupid error */ + /* we should return an error code warning this logic error */ + /* foolproof things by ensuring maxcount is not less than mincount */ + maxcount = (maxcount < mincount) ? mincount : maxcount; + + nbytes = sizeof(struct arg_str) /* storage for struct arg_str */ + + maxcount * sizeof(char*); /* storage for sval[maxcount] array */ + + result = (struct arg_str*)xmalloc(nbytes); + + /* init the arg_hdr struct */ + result->hdr.flag = ARG_HASVALUE; + result->hdr.shortopts = shortopts; + result->hdr.longopts = longopts; + result->hdr.datatype = datatype ? datatype : ""; + result->hdr.glossary = glossary; + result->hdr.mincount = mincount; + result->hdr.maxcount = maxcount; + result->hdr.parent = result; + result->hdr.resetfn = (arg_resetfn*)arg_str_resetfn; + result->hdr.scanfn = (arg_scanfn*)arg_str_scanfn; + result->hdr.checkfn = (arg_checkfn*)arg_str_checkfn; + result->hdr.errorfn = (arg_errorfn*)arg_str_errorfn; + + /* store the sval[maxcount] array immediately after the arg_str struct */ + result->sval = (const char**)(result + 1); + result->count = 0; + + /* foolproof the string pointers by initializing them to reference empty strings */ + for (i = 0; i < maxcount; i++) + result->sval[i] = ""; + + ARG_TRACE(("arg_strn() returns %p\n", result)); + return result; +} +/******************************************************************************* + * arg_cmd: Provides the sub-command mechanism + * + * This file is part of the argtable3 library. + * + * Copyright (C) 2013-2019 Tom G. Huang + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include "argtable3.h" + +#ifndef ARG_AMALGAMATION +#include "argtable3_private.h" +#endif + +#include +#include +#include + +#define MAX_MODULE_VERSION_SIZE 128 + +static arg_hashtable_t* s_hashtable = NULL; +static char* s_module_name = NULL; +static int s_mod_ver_major = 0; +static int s_mod_ver_minor = 0; +static int s_mod_ver_patch = 0; +static char* s_mod_ver_tag = NULL; +static char* s_mod_ver = NULL; + +void arg_set_module_name(const char* name) { + size_t slen; + + xfree(s_module_name); + slen = strlen(name); + s_module_name = (char*)xmalloc(slen + 1); + memset(s_module_name, 0, slen + 1); + +#if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__)) + strncpy_s(s_module_name, slen + 1, name, slen); +#else + memcpy(s_module_name, name, slen); +#endif +} + +void arg_set_module_version(int major, int minor, int patch, const char* tag) { + size_t slen_tag, slen_ds; + arg_dstr_t ds; + + s_mod_ver_major = major; + s_mod_ver_minor = minor; + s_mod_ver_patch = patch; + + xfree(s_mod_ver_tag); + slen_tag = strlen(tag); + s_mod_ver_tag = (char*)xmalloc(slen_tag + 1); + memset(s_mod_ver_tag, 0, slen_tag + 1); + +#if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__)) + strncpy_s(s_mod_ver_tag, slen_tag + 1, tag, slen_tag); +#else + memcpy(s_mod_ver_tag, tag, slen_tag); +#endif + + ds = arg_dstr_create(); + arg_dstr_catf(ds, "%d.", s_mod_ver_major); + arg_dstr_catf(ds, "%d.", s_mod_ver_minor); + arg_dstr_catf(ds, "%d.", s_mod_ver_patch); + arg_dstr_cat(ds, s_mod_ver_tag); + + xfree(s_mod_ver); + slen_ds = strlen(arg_dstr_cstr(ds)); + s_mod_ver = (char*)xmalloc(slen_ds + 1); + memset(s_mod_ver, 0, slen_ds + 1); + +#if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__)) + strncpy_s(s_mod_ver, slen_ds + 1, arg_dstr_cstr(ds), slen_ds); +#else + memcpy(s_mod_ver, arg_dstr_cstr(ds), slen_ds); +#endif + + arg_dstr_destroy(ds); +} + +static unsigned int hash_key(const void* key) { + const char* str = (const char*)key; + int c; + unsigned int hash = 5381; + + while ((c = *str++) != 0) + hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ + + return hash; +} + +static int equal_keys(const void* key1, const void* key2) { + char* k1 = (char*)key1; + char* k2 = (char*)key2; + return (0 == strcmp(k1, k2)); +} + +void arg_cmd_init(void) { + s_hashtable = arg_hashtable_create(32, hash_key, equal_keys); +} + +void arg_cmd_uninit(void) { + arg_hashtable_destroy(s_hashtable, 1); +} + +void arg_cmd_register(const char* name, arg_cmdfn* proc, const char* description) { + arg_cmd_info_t* cmd_info; + size_t slen_name; + void* k; + + assert(strlen(name) < ARG_CMD_NAME_LEN); + assert(strlen(description) < ARG_CMD_DESCRIPTION_LEN); + + /* Check if the command already exists. */ + /* If the command exists, replace the existing command. */ + /* If the command doesn't exist, insert the command. */ + cmd_info = (arg_cmd_info_t*)arg_hashtable_search(s_hashtable, name); + if (cmd_info) { + arg_hashtable_remove(s_hashtable, name); + cmd_info = NULL; + } + + cmd_info = (arg_cmd_info_t*)xmalloc(sizeof(arg_cmd_info_t)); + memset(cmd_info, 0, sizeof(arg_cmd_info_t)); + +#if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__)) + strncpy_s(cmd_info->name, ARG_CMD_NAME_LEN, name, strlen(name)); + strncpy_s(cmd_info->description, ARG_CMD_DESCRIPTION_LEN, description, strlen(description)); +#else + memcpy(cmd_info->name, name, strlen(name)); + memcpy(cmd_info->description, description, strlen(description)); +#endif + + cmd_info->proc = proc; + + slen_name = strlen(name); + k = xmalloc(slen_name + 1); + memset(k, 0, slen_name + 1); + +#if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__)) + strncpy_s((char*)k, slen_name + 1, name, slen_name); +#else + memcpy((char*)k, name, slen_name); +#endif + + arg_hashtable_insert(s_hashtable, k, cmd_info); +} + +void arg_cmd_unregister(const char* name) { + arg_hashtable_remove(s_hashtable, name); +} + +int arg_cmd_dispatch(const char* name, int argc, char* argv[], arg_dstr_t res) { + arg_cmd_info_t* cmd_info = arg_cmd_info(name); + + assert(cmd_info != NULL); + assert(cmd_info->proc != NULL); + + return cmd_info->proc(argc, argv, res); +} + +arg_cmd_info_t* arg_cmd_info(const char* name) { + return (arg_cmd_info_t*)arg_hashtable_search(s_hashtable, name); +} + +unsigned int arg_cmd_count(void) { + return arg_hashtable_count(s_hashtable); +} + +arg_cmd_itr_t arg_cmd_itr_create(void) { + return (arg_cmd_itr_t)arg_hashtable_itr_create(s_hashtable); +} + +int arg_cmd_itr_advance(arg_cmd_itr_t itr) { + return arg_hashtable_itr_advance((arg_hashtable_itr_t*)itr); +} + +char* arg_cmd_itr_key(arg_cmd_itr_t itr) { + return (char*)arg_hashtable_itr_key((arg_hashtable_itr_t*)itr); +} + +arg_cmd_info_t* arg_cmd_itr_value(arg_cmd_itr_t itr) { + return (arg_cmd_info_t*)arg_hashtable_itr_value((arg_hashtable_itr_t*)itr); +} + +void arg_cmd_itr_destroy(arg_cmd_itr_t itr) { + arg_hashtable_itr_destroy((arg_hashtable_itr_t*)itr); +} + +int arg_cmd_itr_search(arg_cmd_itr_t itr, void* k) { + return arg_hashtable_itr_search((arg_hashtable_itr_t*)itr, s_hashtable, k); +} + +static const char* module_name(void) { + if (s_module_name == NULL || strlen(s_module_name) == 0) + return ""; + + return s_module_name; +} + +static const char* module_version(void) { + if (s_mod_ver == NULL || strlen(s_mod_ver) == 0) + return "0.0.0.0"; + + return s_mod_ver; +} + +void arg_make_get_help_msg(arg_dstr_t res) { + arg_dstr_catf(res, "%s v%s\n", module_name(), module_version()); + arg_dstr_catf(res, "Please type '%s help' to get more information.\n", module_name()); +} + +void arg_make_help_msg(arg_dstr_t ds, char* cmd_name, void** argtable) { + arg_cmd_info_t* cmd_info = (arg_cmd_info_t*)arg_hashtable_search(s_hashtable, cmd_name); + if (cmd_info) { + arg_dstr_catf(ds, "%s: %s\n", cmd_name, cmd_info->description); + } + + arg_dstr_cat(ds, "Usage:\n"); + arg_dstr_catf(ds, " %s", module_name()); + + arg_print_syntaxv_ds(ds, argtable, "\n \nAvailable options:\n"); + arg_print_glossary_ds(ds, argtable, " %-23s %s\n"); + + arg_dstr_cat(ds, "\n"); +} + +void arg_make_syntax_err_msg(arg_dstr_t ds, void** argtable, struct arg_end* end) { + arg_print_errors_ds(ds, end, module_name()); + arg_dstr_cat(ds, "Usage: \n"); + arg_dstr_catf(ds, " %s", module_name()); + arg_print_syntaxv_ds(ds, argtable, "\n"); + arg_dstr_cat(ds, "\n"); +} + +int arg_make_syntax_err_help_msg(arg_dstr_t ds, char* name, int help, int nerrors, void** argtable, struct arg_end* end, int* exitcode) { + /* help handling + * note: '-h|--help' takes precedence over error reporting + */ + if (help > 0) { + arg_make_help_msg(ds, name, argtable); + *exitcode = EXIT_SUCCESS; + return 1; + } + + /* syntax error handling */ + if (nerrors > 0) { + arg_make_syntax_err_msg(ds, argtable, end); + *exitcode = EXIT_FAILURE; + return 1; + } + + return 0; +} +/******************************************************************************* + * argtable3: Implements the main interfaces of the library + * + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include "argtable3.h" + +#ifndef ARG_AMALGAMATION +#include "argtable3_private.h" +#include "getopt.h" +#endif + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#undef WIN32_LEAN_AND_MEAN +#endif + +#include +#include +#include +#include +#include + +static void arg_register_error(struct arg_end* end, void* parent, int error, const char* argval) { + /* printf("arg_register_error(%p,%p,%d,%s)\n",end,parent,error,argval); */ + if (end->count < end->hdr.maxcount) { + end->error[end->count] = error; + end->parent[end->count] = parent; + end->argval[end->count] = argval; + end->count++; + } else { + end->error[end->hdr.maxcount - 1] = ARG_ELIMIT; + end->parent[end->hdr.maxcount - 1] = end; + end->argval[end->hdr.maxcount - 1] = NULL; + } +} + +/* + * Return index of first table entry with a matching short option + * or -1 if no match was found. + */ +static int find_shortoption(struct arg_hdr** table, char shortopt) { + int tabindex; + for (tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) { + if (table[tabindex]->shortopts && strchr(table[tabindex]->shortopts, shortopt)) + return tabindex; + } + return -1; +} + +struct longoptions { + int getoptval; + int noptions; + struct option* options; +}; + +#if 0 +static +void dump_longoptions(struct longoptions * longoptions) +{ + int i; + printf("getoptval = %d\n", longoptions->getoptval); + printf("noptions = %d\n", longoptions->noptions); + for (i = 0; i < longoptions->noptions; i++) + { + printf("options[%d].name = \"%s\"\n", + i, + longoptions->options[i].name); + printf("options[%d].has_arg = %d\n", i, longoptions->options[i].has_arg); + printf("options[%d].flag = %p\n", i, longoptions->options[i].flag); + printf("options[%d].val = %d\n", i, longoptions->options[i].val); + } +} +#endif + +static struct longoptions* alloc_longoptions(struct arg_hdr** table) { + struct longoptions* result; + size_t nbytes; + int noptions = 1; + size_t longoptlen = 0; + int tabindex; + int option_index = 0; + char* store; + + /* + * Determine the total number of option structs required + * by counting the number of comma separated long options + * in all table entries and return the count in noptions. + * note: noptions starts at 1 not 0 because we getoptlong + * requires a NULL option entry to terminate the option array. + * While we are at it, count the number of chars required + * to store private copies of all the longoption strings + * and return that count in logoptlen. + */ + tabindex = 0; + do { + const char* longopts = table[tabindex]->longopts; + longoptlen += (longopts ? strlen(longopts) : 0) + 1; + while (longopts) { + noptions++; + longopts = strchr(longopts + 1, ','); + } + } while (!(table[tabindex++]->flag & ARG_TERMINATOR)); + /*printf("%d long options consuming %d chars in total\n",noptions,longoptlen);*/ + + /* allocate storage for return data structure as: */ + /* (struct longoptions) + (struct options)[noptions] + char[longoptlen] */ + nbytes = sizeof(struct longoptions) + sizeof(struct option) * noptions + longoptlen; + result = (struct longoptions*)xmalloc(nbytes); + + result->getoptval = 0; + result->noptions = noptions; + result->options = (struct option*)(result + 1); + store = (char*)(result->options + noptions); + + for (tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) { + const char* longopts = table[tabindex]->longopts; + + while (longopts && *longopts) { + char* storestart = store; + + /* copy progressive longopt strings into the store */ + while (*longopts != 0 && *longopts != ',') + *store++ = *longopts++; + *store++ = 0; + if (*longopts == ',') + longopts++; + /*fprintf(stderr,"storestart=\"%s\"\n",storestart);*/ + + result->options[option_index].name = storestart; + result->options[option_index].flag = &(result->getoptval); + result->options[option_index].val = tabindex; + if (table[tabindex]->flag & ARG_HASOPTVALUE) + result->options[option_index].has_arg = 2; + else if (table[tabindex]->flag & ARG_HASVALUE) + result->options[option_index].has_arg = 1; + else + result->options[option_index].has_arg = 0; + + option_index++; + } + } + /* terminate the options array with a zero-filled entry */ + result->options[option_index].name = 0; + result->options[option_index].has_arg = 0; + result->options[option_index].flag = 0; + result->options[option_index].val = 0; + + /*dump_longoptions(result);*/ + return result; +} + +static char* alloc_shortoptions(struct arg_hdr** table) { + char* result; + size_t len = 2; + int tabindex; + char* res; + + /* determine the total number of option chars required */ + for (tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) { + struct arg_hdr* hdr = table[tabindex]; + len += 3 * (hdr->shortopts ? strlen(hdr->shortopts) : 0); + } + + result = xmalloc(len); + + res = result; + + /* add a leading ':' so getopt return codes distinguish */ + /* unrecognised option and options missing argument values */ + *res++ = ':'; + + for (tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) { + struct arg_hdr* hdr = table[tabindex]; + const char* shortopts = hdr->shortopts; + while (shortopts && *shortopts) { + *res++ = *shortopts++; + if (hdr->flag & ARG_HASVALUE) + *res++ = ':'; + if (hdr->flag & ARG_HASOPTVALUE) + *res++ = ':'; + } + } + /* null terminate the string */ + *res = 0; + + /*printf("alloc_shortoptions() returns \"%s\"\n",(result?result:"NULL"));*/ + return result; +} + +/* return index of the table terminator entry */ +static int arg_endindex(struct arg_hdr** table) { + int tabindex = 0; + while (!(table[tabindex]->flag & ARG_TERMINATOR)) + tabindex++; + return tabindex; +} + +static void arg_parse_tagged(int argc, char** argv, struct arg_hdr** table, struct arg_end* endtable) { + struct longoptions* longoptions; + char* shortoptions; + int copt; + + /*printf("arg_parse_tagged(%d,%p,%p,%p)\n",argc,argv,table,endtable);*/ + + /* allocate short and long option arrays for the given opttable[]. */ + /* if the allocs fail then put an error msg in the last table entry. */ + longoptions = alloc_longoptions(table); + shortoptions = alloc_shortoptions(table); + + /*dump_longoptions(longoptions);*/ + + /* reset getopts internal option-index to zero, and disable error reporting */ + optind = 0; + opterr = 0; + + /* fetch and process args using getopt_long */ + while ((copt = getopt_long(argc, argv, shortoptions, longoptions->options, NULL)) != -1) { + /* + printf("optarg='%s'\n",optarg); + printf("optind=%d\n",optind); + printf("copt=%c\n",(char)copt); + printf("optopt=%c (%d)\n",optopt, (int)(optopt)); + */ + switch (copt) { + case 0: { + int tabindex = longoptions->getoptval; + void* parent = table[tabindex]->parent; + /*printf("long option detected from argtable[%d]\n", tabindex);*/ + if (optarg && optarg[0] == 0 && (table[tabindex]->flag & ARG_HASVALUE)) { + /* printf(": long option %s requires an argument\n",argv[optind-1]); */ + arg_register_error(endtable, endtable, ARG_EMISSARG, argv[optind - 1]); + /* continue to scan the (empty) argument value to enforce argument count checking */ + } + if (table[tabindex]->scanfn) { + int errorcode = table[tabindex]->scanfn(parent, optarg); + if (errorcode != 0) + arg_register_error(endtable, parent, errorcode, optarg); + } + } break; + + case '?': + /* + * getopt_long() found an unrecognised short option. + * if it was a short option its value is in optopt + * if it was a long option then optopt=0 + */ + switch (optopt) { + case 0: + /*printf("?0 unrecognised long option %s\n",argv[optind-1]);*/ + arg_register_error(endtable, endtable, ARG_ELONGOPT, argv[optind - 1]); + break; + default: + /*printf("?* unrecognised short option '%c'\n",optopt);*/ + arg_register_error(endtable, endtable, optopt, NULL); + break; + } + break; + + case ':': + /* + * getopt_long() found an option with its argument missing. + */ + /*printf(": option %s requires an argument\n",argv[optind-1]); */ + arg_register_error(endtable, endtable, ARG_EMISSARG, argv[optind - 1]); + break; + + default: { + /* getopt_long() found a valid short option */ + int tabindex = find_shortoption(table, (char)copt); + /*printf("short option detected from argtable[%d]\n", tabindex);*/ + if (tabindex == -1) { + /* should never get here - but handle it just in case */ + /*printf("unrecognised short option %d\n",copt);*/ + arg_register_error(endtable, endtable, copt, NULL); + } else { + if (table[tabindex]->scanfn) { + void* parent = table[tabindex]->parent; + int errorcode = table[tabindex]->scanfn(parent, optarg); + if (errorcode != 0) + arg_register_error(endtable, parent, errorcode, optarg); + } + } + break; + } + } + } + + xfree(shortoptions); + xfree(longoptions); +} + +static void arg_parse_untagged(int argc, char** argv, struct arg_hdr** table, struct arg_end* endtable) { + int tabindex = 0; + int errorlast = 0; + const char* optarglast = NULL; + void* parentlast = NULL; + + /*printf("arg_parse_untagged(%d,%p,%p,%p)\n",argc,argv,table,endtable);*/ + while (!(table[tabindex]->flag & ARG_TERMINATOR)) { + void* parent; + int errorcode; + + /* if we have exhausted our argv[optind] entries then we have finished */ + if (optind >= argc) { + /*printf("arg_parse_untagged(): argv[] exhausted\n");*/ + return; + } + + /* skip table entries with non-null long or short options (they are not untagged entries) */ + if (table[tabindex]->longopts || table[tabindex]->shortopts) { + /*printf("arg_parse_untagged(): skipping argtable[%d] (tagged argument)\n",tabindex);*/ + tabindex++; + continue; + } + + /* skip table entries with NULL scanfn */ + if (!(table[tabindex]->scanfn)) { + /*printf("arg_parse_untagged(): skipping argtable[%d] (NULL scanfn)\n",tabindex);*/ + tabindex++; + continue; + } + + /* attempt to scan the current argv[optind] with the current */ + /* table[tabindex] entry. If it succeeds then keep it, otherwise */ + /* try again with the next table[] entry. */ + parent = table[tabindex]->parent; + errorcode = table[tabindex]->scanfn(parent, argv[optind]); + if (errorcode == 0) { + /* success, move onto next argv[optind] but stay with same table[tabindex] */ + /*printf("arg_parse_untagged(): argtable[%d] successfully matched\n",tabindex);*/ + optind++; + + /* clear the last tentative error */ + errorlast = 0; + } else { + /* failure, try same argv[optind] with next table[tabindex] entry */ + /*printf("arg_parse_untagged(): argtable[%d] failed match\n",tabindex);*/ + tabindex++; + + /* remember this as a tentative error we may wish to reinstate later */ + errorlast = errorcode; + optarglast = argv[optind]; + parentlast = parent; + } + } + + /* if a tenative error still remains at this point then register it as a proper error */ + if (errorlast) { + arg_register_error(endtable, parentlast, errorlast, optarglast); + optind++; + } + + /* only get here when not all argv[] entries were consumed */ + /* register an error for each unused argv[] entry */ + while (optind < argc) { + /*printf("arg_parse_untagged(): argv[%d]=\"%s\" not consumed\n",optind,argv[optind]);*/ + arg_register_error(endtable, endtable, ARG_ENOMATCH, argv[optind++]); + } + + return; +} + +static void arg_parse_check(struct arg_hdr** table, struct arg_end* endtable) { + int tabindex = 0; + /* printf("arg_parse_check()\n"); */ + do { + if (table[tabindex]->checkfn) { + void* parent = table[tabindex]->parent; + int errorcode = table[tabindex]->checkfn(parent); + if (errorcode != 0) + arg_register_error(endtable, parent, errorcode, NULL); + } + } while (!(table[tabindex++]->flag & ARG_TERMINATOR)); +} + +static void arg_reset(void** argtable) { + struct arg_hdr** table = (struct arg_hdr**)argtable; + int tabindex = 0; + /*printf("arg_reset(%p)\n",argtable);*/ + do { + if (table[tabindex]->resetfn) + table[tabindex]->resetfn(table[tabindex]->parent); + } while (!(table[tabindex++]->flag & ARG_TERMINATOR)); +} + +int arg_parse(int argc, char** argv, void** argtable) { + struct arg_hdr** table = (struct arg_hdr**)argtable; + struct arg_end* endtable; + int endindex; + char** argvcopy = NULL; + int i; + + /*printf("arg_parse(%d,%p,%p)\n",argc,argv,argtable);*/ + + /* reset any argtable data from previous invocations */ + arg_reset(argtable); + + /* locate the first end-of-table marker within the array */ + endindex = arg_endindex(table); + endtable = (struct arg_end*)table[endindex]; + + /* Special case of argc==0. This can occur on Texas Instruments DSP. */ + /* Failure to trap this case results in an unwanted NULL result from */ + /* the malloc for argvcopy (next code block). */ + if (argc == 0) { + /* We must still perform post-parse checks despite the absence of command line arguments */ + arg_parse_check(table, endtable); + + /* Now we are finished */ + return endtable->count; + } + + argvcopy = (char**)xmalloc(sizeof(char*) * (argc + 1)); + + /* + Fill in the local copy of argv[]. We need a local copy + because getopt rearranges argv[] which adversely affects + susbsequent parsing attempts. + */ + for (i = 0; i < argc; i++) + argvcopy[i] = argv[i]; + + argvcopy[argc] = NULL; + + /* parse the command line (local copy) for tagged options */ + arg_parse_tagged(argc, argvcopy, table, endtable); + + /* parse the command line (local copy) for untagged options */ + arg_parse_untagged(argc, argvcopy, table, endtable); + + /* if no errors so far then perform post-parse checks otherwise dont bother */ + if (endtable->count == 0) + arg_parse_check(table, endtable); + + /* release the local copt of argv[] */ + xfree(argvcopy); + + return endtable->count; +} + +/* + * Concatenate contents of src[] string onto *pdest[] string. + * The *pdest pointer is altered to point to the end of the + * target string and *pndest is decremented by the same number + * of chars. + * Does not append more than *pndest chars into *pdest[] + * so as to prevent buffer overruns. + * Its something like strncat() but more efficient for repeated + * calls on the same destination string. + * Example of use: + * char dest[30] = "good" + * size_t ndest = sizeof(dest); + * char *pdest = dest; + * arg_char(&pdest,"bye ",&ndest); + * arg_char(&pdest,"cruel ",&ndest); + * arg_char(&pdest,"world!",&ndest); + * Results in: + * dest[] == "goodbye cruel world!" + * ndest == 10 + */ +static void arg_cat(char** pdest, const char* src, size_t* pndest) { + char* dest = *pdest; + char* end = dest + *pndest; + + /*locate null terminator of dest string */ + while (dest < end && *dest != 0) + dest++; + + /* concat src string to dest string */ + while (dest < end && *src != 0) + *dest++ = *src++; + + /* null terminate dest string */ + *dest = 0; + + /* update *pdest and *pndest */ + *pndest = end - dest; + *pdest = dest; +} + +static void arg_cat_option(char* dest, size_t ndest, const char* shortopts, const char* longopts, const char* datatype, int optvalue) { + if (shortopts) { + char option[3]; + + /* note: option array[] is initialiazed dynamically here to satisfy */ + /* a deficiency in the watcom compiler wrt static array initializers. */ + option[0] = '-'; + option[1] = shortopts[0]; + option[2] = 0; + + arg_cat(&dest, option, &ndest); + if (datatype) { + arg_cat(&dest, " ", &ndest); + if (optvalue) { + arg_cat(&dest, "[", &ndest); + arg_cat(&dest, datatype, &ndest); + arg_cat(&dest, "]", &ndest); + } else + arg_cat(&dest, datatype, &ndest); + } + } else if (longopts) { + size_t ncspn; + + /* add "--" tag prefix */ + arg_cat(&dest, "--", &ndest); + + /* add comma separated option tag */ + ncspn = strcspn(longopts, ","); +#if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__)) + strncat_s(dest, ndest, longopts, (ncspn < ndest) ? ncspn : ndest); +#else + strncat(dest, longopts, (ncspn < ndest) ? ncspn : ndest); +#endif + + if (datatype) { + arg_cat(&dest, "=", &ndest); + if (optvalue) { + arg_cat(&dest, "[", &ndest); + arg_cat(&dest, datatype, &ndest); + arg_cat(&dest, "]", &ndest); + } else + arg_cat(&dest, datatype, &ndest); + } + } else if (datatype) { + if (optvalue) { + arg_cat(&dest, "[", &ndest); + arg_cat(&dest, datatype, &ndest); + arg_cat(&dest, "]", &ndest); + } else + arg_cat(&dest, datatype, &ndest); + } +} + +static void +arg_cat_optionv(char* dest, size_t ndest, const char* shortopts, const char* longopts, const char* datatype, int optvalue, const char* separator) { + separator = separator ? separator : ""; + + if (shortopts) { + const char* c = shortopts; + while (*c) { + /* "-a|-b|-c" */ + char shortopt[3]; + + /* note: shortopt array[] is initialiazed dynamically here to satisfy */ + /* a deficiency in the watcom compiler wrt static array initializers. */ + shortopt[0] = '-'; + shortopt[1] = *c; + shortopt[2] = 0; + + arg_cat(&dest, shortopt, &ndest); + if (*++c) + arg_cat(&dest, separator, &ndest); + } + } + + /* put separator between long opts and short opts */ + if (shortopts && longopts) + arg_cat(&dest, separator, &ndest); + + if (longopts) { + const char* c = longopts; + while (*c) { + size_t ncspn; + + /* add "--" tag prefix */ + arg_cat(&dest, "--", &ndest); + + /* add comma separated option tag */ + ncspn = strcspn(c, ","); +#if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__)) + strncat_s(dest, ndest, c, (ncspn < ndest) ? ncspn : ndest); +#else + strncat(dest, c, (ncspn < ndest) ? ncspn : ndest); +#endif + c += ncspn; + + /* add given separator in place of comma */ + if (*c == ',') { + arg_cat(&dest, separator, &ndest); + c++; + } + } + } + + if (datatype) { + if (longopts) + arg_cat(&dest, "=", &ndest); + else if (shortopts) + arg_cat(&dest, " ", &ndest); + + if (optvalue) { + arg_cat(&dest, "[", &ndest); + arg_cat(&dest, datatype, &ndest); + arg_cat(&dest, "]", &ndest); + } else + arg_cat(&dest, datatype, &ndest); + } +} + +void arg_print_option_ds(arg_dstr_t ds, const char* shortopts, const char* longopts, const char* datatype, const char* suffix) { + char syntax[200] = ""; + suffix = suffix ? suffix : ""; + + /* there is no way of passing the proper optvalue for optional argument values here, so we must ignore it */ + arg_cat_optionv(syntax, sizeof(syntax), shortopts, longopts, datatype, 0, "|"); + + arg_dstr_cat(ds, syntax); + arg_dstr_cat(ds, (char*)suffix); +} + +/* this function should be deprecated because it doesn't consider optional argument values (ARG_HASOPTVALUE) */ +void arg_print_option(FILE* fp, const char* shortopts, const char* longopts, const char* datatype, const char* suffix) { + arg_dstr_t ds = arg_dstr_create(); + arg_print_option_ds(ds, shortopts, longopts, datatype, suffix); + fputs(arg_dstr_cstr(ds), fp); + arg_dstr_destroy(ds); +} + +/* + * Print a GNU style [OPTION] string in which all short options that + * do not take argument values are presented in abbreviated form, as + * in: -xvfsd, or -xvf[sd], or [-xvsfd] + */ +static void arg_print_gnuswitch_ds(arg_dstr_t ds, struct arg_hdr** table) { + int tabindex; + char* format1 = " -%c"; + char* format2 = " [-%c"; + char* suffix = ""; + + /* print all mandatory switches that are without argument values */ + for (tabindex = 0; table[tabindex] && !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) { + /* skip optional options */ + if (table[tabindex]->mincount < 1) + continue; + + /* skip non-short options */ + if (table[tabindex]->shortopts == NULL) + continue; + + /* skip options that take argument values */ + if (table[tabindex]->flag & ARG_HASVALUE) + continue; + + /* print the short option (only the first short option char, ignore multiple choices)*/ + arg_dstr_catf(ds, format1, table[tabindex]->shortopts[0]); + format1 = "%c"; + format2 = "[%c"; + } + + /* print all optional switches that are without argument values */ + for (tabindex = 0; table[tabindex] && !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) { + /* skip mandatory args */ + if (table[tabindex]->mincount > 0) + continue; + + /* skip args without short options */ + if (table[tabindex]->shortopts == NULL) + continue; + + /* skip args with values */ + if (table[tabindex]->flag & ARG_HASVALUE) + continue; + + /* print first short option */ + arg_dstr_catf(ds, format2, table[tabindex]->shortopts[0]); + format2 = "%c"; + suffix = "]"; + } + + arg_dstr_catf(ds, "%s", suffix); +} + +void arg_print_syntax_ds(arg_dstr_t ds, void** argtable, const char* suffix) { + struct arg_hdr** table = (struct arg_hdr**)argtable; + int i, tabindex; + + /* print GNU style [OPTION] string */ + arg_print_gnuswitch_ds(ds, table); + + /* print remaining options in abbreviated style */ + for (tabindex = 0; table[tabindex] && !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) { + char syntax[200] = ""; + const char *shortopts, *longopts, *datatype; + + /* skip short options without arg values (they were printed by arg_print_gnu_switch) */ + if (table[tabindex]->shortopts && !(table[tabindex]->flag & ARG_HASVALUE)) + continue; + + shortopts = table[tabindex]->shortopts; + longopts = table[tabindex]->longopts; + datatype = table[tabindex]->datatype; + arg_cat_option(syntax, sizeof(syntax), shortopts, longopts, datatype, table[tabindex]->flag & ARG_HASOPTVALUE); + + if (strlen(syntax) > 0) { + /* print mandatory instances of this option */ + for (i = 0; i < table[tabindex]->mincount; i++) { + arg_dstr_cat(ds, " "); + arg_dstr_cat(ds, syntax); + } + + /* print optional instances enclosed in "[..]" */ + switch (table[tabindex]->maxcount - table[tabindex]->mincount) { + case 0: + break; + case 1: + arg_dstr_cat(ds, " ["); + arg_dstr_cat(ds, syntax); + arg_dstr_cat(ds, "]"); + break; + case 2: + arg_dstr_cat(ds, " ["); + arg_dstr_cat(ds, syntax); + arg_dstr_cat(ds, "]"); + arg_dstr_cat(ds, " ["); + arg_dstr_cat(ds, syntax); + arg_dstr_cat(ds, "]"); + break; + default: + arg_dstr_cat(ds, " ["); + arg_dstr_cat(ds, syntax); + arg_dstr_cat(ds, "]..."); + break; + } + } + } + + if (suffix) { + arg_dstr_cat(ds, (char*)suffix); + } +} + +void arg_print_syntax(FILE* fp, void** argtable, const char* suffix) { + arg_dstr_t ds = arg_dstr_create(); + arg_print_syntax_ds(ds, argtable, suffix); + fputs(arg_dstr_cstr(ds), fp); + arg_dstr_destroy(ds); +} + +void arg_print_syntaxv_ds(arg_dstr_t ds, void** argtable, const char* suffix) { + struct arg_hdr** table = (struct arg_hdr**)argtable; + int i, tabindex; + + /* print remaining options in abbreviated style */ + for (tabindex = 0; table[tabindex] && !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) { + char syntax[200] = ""; + const char *shortopts, *longopts, *datatype; + + shortopts = table[tabindex]->shortopts; + longopts = table[tabindex]->longopts; + datatype = table[tabindex]->datatype; + arg_cat_optionv(syntax, sizeof(syntax), shortopts, longopts, datatype, table[tabindex]->flag & ARG_HASOPTVALUE, "|"); + + /* print mandatory options */ + for (i = 0; i < table[tabindex]->mincount; i++) { + arg_dstr_cat(ds, " "); + arg_dstr_cat(ds, syntax); + } + + /* print optional args enclosed in "[..]" */ + switch (table[tabindex]->maxcount - table[tabindex]->mincount) { + case 0: + break; + case 1: + arg_dstr_cat(ds, " ["); + arg_dstr_cat(ds, syntax); + arg_dstr_cat(ds, "]"); + break; + case 2: + arg_dstr_cat(ds, " ["); + arg_dstr_cat(ds, syntax); + arg_dstr_cat(ds, "]"); + arg_dstr_cat(ds, " ["); + arg_dstr_cat(ds, syntax); + arg_dstr_cat(ds, "]"); + break; + default: + arg_dstr_cat(ds, " ["); + arg_dstr_cat(ds, syntax); + arg_dstr_cat(ds, "]..."); + break; + } + } + + if (suffix) { + arg_dstr_cat(ds, (char*)suffix); + } +} + +void arg_print_syntaxv(FILE* fp, void** argtable, const char* suffix) { + arg_dstr_t ds = arg_dstr_create(); + arg_print_syntaxv_ds(ds, argtable, suffix); + fputs(arg_dstr_cstr(ds), fp); + arg_dstr_destroy(ds); +} + +void arg_print_glossary_ds(arg_dstr_t ds, void** argtable, const char* format) { + struct arg_hdr** table = (struct arg_hdr**)argtable; + int tabindex; + + format = format ? format : " %-20s %s\n"; + for (tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) { + if (table[tabindex]->glossary) { + char syntax[200] = ""; + const char* shortopts = table[tabindex]->shortopts; + const char* longopts = table[tabindex]->longopts; + const char* datatype = table[tabindex]->datatype; + const char* glossary = table[tabindex]->glossary; + arg_cat_optionv(syntax, sizeof(syntax), shortopts, longopts, datatype, table[tabindex]->flag & ARG_HASOPTVALUE, ", "); + arg_dstr_catf(ds, format, syntax, glossary); + } + } +} + +void arg_print_glossary(FILE* fp, void** argtable, const char* format) { + arg_dstr_t ds = arg_dstr_create(); + arg_print_glossary_ds(ds, argtable, format); + fputs(arg_dstr_cstr(ds), fp); + arg_dstr_destroy(ds); +} + +/** + * Print a piece of text formatted, which means in a column with a + * left and a right margin. The lines are wrapped at whitspaces next + * to right margin. The function does not indent the first line, but + * only the following ones. + * + * Example: + * arg_print_formatted( fp, 0, 5, "Some text that doesn't fit." ) + * will result in the following output: + * + * Some + * text + * that + * doesn' + * t fit. + * + * Too long lines will be wrapped in the middle of a word. + * + * arg_print_formatted( fp, 2, 7, "Some text that doesn't fit." ) + * will result in the following output: + * + * Some + * text + * that + * doesn' + * t fit. + * + * As you see, the first line is not indented. This enables output of + * lines, which start in a line where output already happened. + * + * Author: Uli Fouquet + */ +static void arg_print_formatted_ds(arg_dstr_t ds, const unsigned lmargin, const unsigned rmargin, const char* text) { + const unsigned int textlen = (unsigned int)strlen(text); + unsigned int line_start = 0; + unsigned int line_end = textlen; + const unsigned int colwidth = (rmargin - lmargin) + 1; + + assert(strlen(text) < UINT_MAX); + + /* Someone doesn't like us... */ + if (line_end < line_start) { + arg_dstr_catf(ds, "%s\n", text); + } + + while (line_end > line_start) { + /* Eat leading white spaces. This is essential because while + wrapping lines, there will often be a whitespace at beginning + of line */ + while (isspace(*(text + line_start))) { + line_start++; + } + + /* Find last whitespace, that fits into line */ + if (line_end - line_start > colwidth) { + line_end = line_start + colwidth; + + while ((line_end > line_start) && !isspace(*(text + line_end))) { + line_end--; + } + + /* Consume trailing spaces */ + while ((line_end > line_start) && isspace(*(text + line_end))) { + line_end--; + } + + /* Restore the last non-space character */ + line_end++; + } + + /* Output line of text */ + while (line_start < line_end) { + char c = *(text + line_start); + arg_dstr_catc(ds, c); + line_start++; + } + arg_dstr_cat(ds, "\n"); + + /* Initialize another line */ + if (line_end < textlen) { + unsigned i; + + for (i = 0; i < lmargin; i++) { + arg_dstr_cat(ds, " "); + } + + line_end = textlen; + } + } /* lines of text */ +} + +/** + * Prints the glossary in strict GNU format. + * Differences to arg_print_glossary() are: + * - wraps lines after 80 chars + * - indents lines without shortops + * - does not accept formatstrings + * + * Contributed by Uli Fouquet + */ +void arg_print_glossary_gnu_ds(arg_dstr_t ds, void** argtable) { + struct arg_hdr** table = (struct arg_hdr**)argtable; + int tabindex; + + for (tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) { + if (table[tabindex]->glossary) { + char syntax[200] = ""; + const char* shortopts = table[tabindex]->shortopts; + const char* longopts = table[tabindex]->longopts; + const char* datatype = table[tabindex]->datatype; + const char* glossary = table[tabindex]->glossary; + + if (!shortopts && longopts) { + /* Indent trailing line by 4 spaces... */ + memset(syntax, ' ', 4); + *(syntax + 4) = '\0'; + } + + arg_cat_optionv(syntax, sizeof(syntax), shortopts, longopts, datatype, table[tabindex]->flag & ARG_HASOPTVALUE, ", "); + + /* If syntax fits not into column, print glossary in new line... */ + if (strlen(syntax) > 25) { + arg_dstr_catf(ds, " %-25s %s\n", syntax, ""); + *syntax = '\0'; + } + + arg_dstr_catf(ds, " %-25s ", syntax); + arg_print_formatted_ds(ds, 28, 79, glossary); + } + } /* for each table entry */ + + arg_dstr_cat(ds, "\n"); +} + +void arg_print_glossary_gnu(FILE* fp, void** argtable) { + arg_dstr_t ds = arg_dstr_create(); + arg_print_glossary_gnu_ds(ds, argtable); + fputs(arg_dstr_cstr(ds), fp); + arg_dstr_destroy(ds); +} + +/** + * Checks the argtable[] array for NULL entries and returns 1 + * if any are found, zero otherwise. + */ +int arg_nullcheck(void** argtable) { + struct arg_hdr** table = (struct arg_hdr**)argtable; + int tabindex; + /*printf("arg_nullcheck(%p)\n",argtable);*/ + + if (!table) + return 1; + + tabindex = 0; + do { + /*printf("argtable[%d]=%p\n",tabindex,argtable[tabindex]);*/ + if (!table[tabindex]) + return 1; + } while (!(table[tabindex++]->flag & ARG_TERMINATOR)); + + return 0; +} + +/* + * arg_free() is deprecated in favour of arg_freetable() due to a flaw in its design. + * The flaw results in memory leak in the (very rare) case that an intermediate + * entry in the argtable array failed its memory allocation while others following + * that entry were still allocated ok. Those subsequent allocations will not be + * deallocated by arg_free(). + * Despite the unlikeliness of the problem occurring, and the even unlikelier event + * that it has any deliterious effect, it is fixed regardless by replacing arg_free() + * with the newer arg_freetable() function. + * We still keep arg_free() for backwards compatibility. + */ +void arg_free(void** argtable) { + struct arg_hdr** table = (struct arg_hdr**)argtable; + int tabindex = 0; + int flag; + /*printf("arg_free(%p)\n",argtable);*/ + do { + /* + if we encounter a NULL entry then somewhat incorrectly we presume + we have come to the end of the array. It isnt strictly true because + an intermediate entry could be NULL with other non-NULL entries to follow. + The subsequent argtable entries would then not be freed as they should. + */ + if (table[tabindex] == NULL) + break; + + flag = table[tabindex]->flag; + xfree(table[tabindex]); + table[tabindex++] = NULL; + + } while (!(flag & ARG_TERMINATOR)); +} + +/* frees each non-NULL element of argtable[], where n is the size of the number of entries in the array */ +void arg_freetable(void** argtable, size_t n) { + struct arg_hdr** table = (struct arg_hdr**)argtable; + size_t tabindex = 0; + /*printf("arg_freetable(%p)\n",argtable);*/ + for (tabindex = 0; tabindex < n; tabindex++) { + if (table[tabindex] == NULL) + continue; + + xfree(table[tabindex]); + table[tabindex] = NULL; + }; +} + +#ifdef _WIN32 +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { + return TRUE; + UNREFERENCED_PARAMETER(hinstDLL); + UNREFERENCED_PARAMETER(fdwReason); + UNREFERENCED_PARAMETER(lpvReserved); +} +#endif diff --git a/c/utf8filenamecheck/windows/argtable/argtable3.h b/c/utf8filenamecheck/windows/argtable/argtable3.h new file mode 100644 index 0000000..2042538 --- /dev/null +++ b/c/utf8filenamecheck/windows/argtable/argtable3.h @@ -0,0 +1,277 @@ +/******************************************************************************* + * argtable3: Declares the main interfaces of the library + * + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#ifndef ARGTABLE3 +#define ARGTABLE3 + +#include /* FILE */ +#include /* struct tm */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define ARG_REX_ICASE 1 +#define ARG_DSTR_SIZE 200 +#define ARG_CMD_NAME_LEN 100 +#define ARG_CMD_DESCRIPTION_LEN 256 + +#ifndef ARG_REPLACE_GETOPT +#define ARG_REPLACE_GETOPT 1 /* use the embedded getopt as the system getopt(3) */ +#endif /* ARG_REPLACE_GETOPT */ + +/* bit masks for arg_hdr.flag */ +enum { ARG_TERMINATOR = 0x1, ARG_HASVALUE = 0x2, ARG_HASOPTVALUE = 0x4 }; + +#if defined(_WIN32) + #if defined(argtable3_EXPORTS) + #define ARG_EXTERN __declspec(dllexport) + #elif defined(argtable3_IMPORTS) + #define ARG_EXTERN __declspec(dllimport) + #else + #define ARG_EXTERN + #endif +#else + #define ARG_EXTERN +#endif + +typedef struct _internal_arg_dstr* arg_dstr_t; +typedef void* arg_cmd_itr_t; + +typedef void(arg_resetfn)(void* parent); +typedef int(arg_scanfn)(void* parent, const char* argval); +typedef int(arg_checkfn)(void* parent); +typedef void(arg_errorfn)(void* parent, arg_dstr_t ds, int error, const char* argval, const char* progname); +typedef void(arg_dstr_freefn)(char* buf); +typedef int(arg_cmdfn)(int argc, char* argv[], arg_dstr_t res); +typedef int(arg_comparefn)(const void* k1, const void* k2); + +/* + * The arg_hdr struct defines properties that are common to all arg_xxx structs. + * The argtable library requires each arg_xxx struct to have an arg_hdr + * struct as its first data member. + * The argtable library functions then use this data to identify the + * properties of the command line option, such as its option tags, + * datatype string, and glossary strings, and so on. + * Moreover, the arg_hdr struct contains pointers to custom functions that + * are provided by each arg_xxx struct which perform the tasks of parsing + * that particular arg_xxx arguments, performing post-parse checks, and + * reporting errors. + * These functions are private to the individual arg_xxx source code + * and are the pointer to them are initiliased by that arg_xxx struct's + * constructor function. The user could alter them after construction + * if desired, but the original intention is for them to be set by the + * constructor and left unaltered. + */ +struct arg_hdr { + char flag; /* Modifier flags: ARG_TERMINATOR, ARG_HASVALUE. */ + const char* shortopts; /* String defining the short options */ + const char* longopts; /* String defiing the long options */ + const char* datatype; /* Description of the argument data type */ + const char* glossary; /* Description of the option as shown by arg_print_glossary function */ + int mincount; /* Minimum number of occurences of this option accepted */ + int maxcount; /* Maximum number of occurences if this option accepted */ + void* parent; /* Pointer to parent arg_xxx struct */ + arg_resetfn* resetfn; /* Pointer to parent arg_xxx reset function */ + arg_scanfn* scanfn; /* Pointer to parent arg_xxx scan function */ + arg_checkfn* checkfn; /* Pointer to parent arg_xxx check function */ + arg_errorfn* errorfn; /* Pointer to parent arg_xxx error function */ + void* priv; /* Pointer to private header data for use by arg_xxx functions */ +}; + +struct arg_rem { + struct arg_hdr hdr; /* The mandatory argtable header struct */ +}; + +struct arg_lit { + struct arg_hdr hdr; /* The mandatory argtable header struct */ + int count; /* Number of matching command line args */ +}; + +struct arg_int { + struct arg_hdr hdr; /* The mandatory argtable header struct */ + int count; /* Number of matching command line args */ + int* ival; /* Array of parsed argument values */ +}; + +struct arg_dbl { + struct arg_hdr hdr; /* The mandatory argtable header struct */ + int count; /* Number of matching command line args */ + double* dval; /* Array of parsed argument values */ +}; + +struct arg_str { + struct arg_hdr hdr; /* The mandatory argtable header struct */ + int count; /* Number of matching command line args */ + const char** sval; /* Array of parsed argument values */ +}; + +struct arg_rex { + struct arg_hdr hdr; /* The mandatory argtable header struct */ + int count; /* Number of matching command line args */ + const char** sval; /* Array of parsed argument values */ +}; + +struct arg_file { + struct arg_hdr hdr; /* The mandatory argtable header struct */ + int count; /* Number of matching command line args*/ + const char** filename; /* Array of parsed filenames (eg: /home/foo.bar) */ + const char** basename; /* Array of parsed basenames (eg: foo.bar) */ + const char** extension; /* Array of parsed extensions (eg: .bar) */ +}; + +struct arg_date { + struct arg_hdr hdr; /* The mandatory argtable header struct */ + const char* format; /* strptime format string used to parse the date */ + int count; /* Number of matching command line args */ + struct tm* tmval; /* Array of parsed time values */ +}; + +enum { ARG_ELIMIT = 1, ARG_EMALLOC, ARG_ENOMATCH, ARG_ELONGOPT, ARG_EMISSARG }; +struct arg_end { + struct arg_hdr hdr; /* The mandatory argtable header struct */ + int count; /* Number of errors encountered */ + int* error; /* Array of error codes */ + void** parent; /* Array of pointers to offending arg_xxx struct */ + const char** argval; /* Array of pointers to offending argv[] string */ +}; + +typedef struct arg_cmd_info { + char name[ARG_CMD_NAME_LEN]; + char description[ARG_CMD_DESCRIPTION_LEN]; + arg_cmdfn* proc; +} arg_cmd_info_t; + +/**** arg_xxx constructor functions *********************************/ + +ARG_EXTERN struct arg_rem* arg_rem(const char* datatype, const char* glossary); + +ARG_EXTERN struct arg_lit* arg_lit0(const char* shortopts, const char* longopts, const char* glossary); +ARG_EXTERN struct arg_lit* arg_lit1(const char* shortopts, const char* longopts, const char* glossary); +ARG_EXTERN struct arg_lit* arg_litn(const char* shortopts, const char* longopts, int mincount, int maxcount, const char* glossary); + +ARG_EXTERN struct arg_key* arg_key0(const char* keyword, int flags, const char* glossary); +ARG_EXTERN struct arg_key* arg_key1(const char* keyword, int flags, const char* glossary); +ARG_EXTERN struct arg_key* arg_keyn(const char* keyword, int flags, int mincount, int maxcount, const char* glossary); + +ARG_EXTERN struct arg_int* arg_int0(const char* shortopts, const char* longopts, const char* datatype, const char* glossary); +ARG_EXTERN struct arg_int* arg_int1(const char* shortopts, const char* longopts, const char* datatype, const char* glossary); +ARG_EXTERN struct arg_int* arg_intn(const char* shortopts, const char* longopts, const char* datatype, int mincount, int maxcount, const char* glossary); + +ARG_EXTERN struct arg_dbl* arg_dbl0(const char* shortopts, const char* longopts, const char* datatype, const char* glossary); +ARG_EXTERN struct arg_dbl* arg_dbl1(const char* shortopts, const char* longopts, const char* datatype, const char* glossary); +ARG_EXTERN struct arg_dbl* arg_dbln(const char* shortopts, const char* longopts, const char* datatype, int mincount, int maxcount, const char* glossary); + +ARG_EXTERN struct arg_str* arg_str0(const char* shortopts, const char* longopts, const char* datatype, const char* glossary); +ARG_EXTERN struct arg_str* arg_str1(const char* shortopts, const char* longopts, const char* datatype, const char* glossary); +ARG_EXTERN struct arg_str* arg_strn(const char* shortopts, const char* longopts, const char* datatype, int mincount, int maxcount, const char* glossary); + +ARG_EXTERN struct arg_rex* arg_rex0(const char* shortopts, const char* longopts, const char* pattern, const char* datatype, int flags, const char* glossary); +ARG_EXTERN struct arg_rex* arg_rex1(const char* shortopts, const char* longopts, const char* pattern, const char* datatype, int flags, const char* glossary); +ARG_EXTERN struct arg_rex* arg_rexn(const char* shortopts, + const char* longopts, + const char* pattern, + const char* datatype, + int mincount, + int maxcount, + int flags, + const char* glossary); + +ARG_EXTERN struct arg_file* arg_file0(const char* shortopts, const char* longopts, const char* datatype, const char* glossary); +ARG_EXTERN struct arg_file* arg_file1(const char* shortopts, const char* longopts, const char* datatype, const char* glossary); +ARG_EXTERN struct arg_file* arg_filen(const char* shortopts, const char* longopts, const char* datatype, int mincount, int maxcount, const char* glossary); + +ARG_EXTERN struct arg_date* arg_date0(const char* shortopts, const char* longopts, const char* format, const char* datatype, const char* glossary); +ARG_EXTERN struct arg_date* arg_date1(const char* shortopts, const char* longopts, const char* format, const char* datatype, const char* glossary); +ARG_EXTERN struct arg_date* arg_daten(const char* shortopts, const char* longopts, const char* format, const char* datatype, int mincount, int maxcount, const char* glossary); + +ARG_EXTERN struct arg_end* arg_end(int maxerrors); + +#define ARG_DSTR_STATIC ((arg_dstr_freefn*)0) +#define ARG_DSTR_VOLATILE ((arg_dstr_freefn*)1) +#define ARG_DSTR_DYNAMIC ((arg_dstr_freefn*)3) + +/**** other functions *******************************************/ +ARG_EXTERN int arg_nullcheck(void** argtable); +ARG_EXTERN int arg_parse(int argc, char** argv, void** argtable); +ARG_EXTERN void arg_print_option(FILE* fp, const char* shortopts, const char* longopts, const char* datatype, const char* suffix); +ARG_EXTERN void arg_print_syntax(FILE* fp, void** argtable, const char* suffix); +ARG_EXTERN void arg_print_syntaxv(FILE* fp, void** argtable, const char* suffix); +ARG_EXTERN void arg_print_glossary(FILE* fp, void** argtable, const char* format); +ARG_EXTERN void arg_print_glossary_gnu(FILE* fp, void** argtable); +ARG_EXTERN void arg_print_errors(FILE* fp, struct arg_end* end, const char* progname); +ARG_EXTERN void arg_print_option_ds(arg_dstr_t ds, const char* shortopts, const char* longopts, const char* datatype, const char* suffix); +ARG_EXTERN void arg_print_syntax_ds(arg_dstr_t ds, void** argtable, const char* suffix); +ARG_EXTERN void arg_print_syntaxv_ds(arg_dstr_t ds, void** argtable, const char* suffix); +ARG_EXTERN void arg_print_glossary_ds(arg_dstr_t ds, void** argtable, const char* format); +ARG_EXTERN void arg_print_glossary_gnu_ds(arg_dstr_t ds, void** argtable); +ARG_EXTERN void arg_print_errors_ds(arg_dstr_t ds, struct arg_end* end, const char* progname); +ARG_EXTERN void arg_freetable(void** argtable, size_t n); + +ARG_EXTERN arg_dstr_t arg_dstr_create(void); +ARG_EXTERN void arg_dstr_destroy(arg_dstr_t ds); +ARG_EXTERN void arg_dstr_reset(arg_dstr_t ds); +ARG_EXTERN void arg_dstr_free(arg_dstr_t ds); +ARG_EXTERN void arg_dstr_set(arg_dstr_t ds, char* str, arg_dstr_freefn* free_proc); +ARG_EXTERN void arg_dstr_cat(arg_dstr_t ds, const char* str); +ARG_EXTERN void arg_dstr_catc(arg_dstr_t ds, char c); +ARG_EXTERN void arg_dstr_catf(arg_dstr_t ds, const char* fmt, ...); +ARG_EXTERN char* arg_dstr_cstr(arg_dstr_t ds); + +ARG_EXTERN void arg_cmd_init(void); +ARG_EXTERN void arg_cmd_uninit(void); +ARG_EXTERN void arg_cmd_register(const char* name, arg_cmdfn* proc, const char* description); +ARG_EXTERN void arg_cmd_unregister(const char* name); +ARG_EXTERN int arg_cmd_dispatch(const char* name, int argc, char* argv[], arg_dstr_t res); +ARG_EXTERN unsigned int arg_cmd_count(void); +ARG_EXTERN arg_cmd_info_t* arg_cmd_info(const char* name); +ARG_EXTERN arg_cmd_itr_t arg_cmd_itr_create(void); +ARG_EXTERN void arg_cmd_itr_destroy(arg_cmd_itr_t itr); +ARG_EXTERN int arg_cmd_itr_advance(arg_cmd_itr_t itr); +ARG_EXTERN char* arg_cmd_itr_key(arg_cmd_itr_t itr); +ARG_EXTERN arg_cmd_info_t* arg_cmd_itr_value(arg_cmd_itr_t itr); +ARG_EXTERN int arg_cmd_itr_search(arg_cmd_itr_t itr, void* k); +ARG_EXTERN void arg_mgsort(void* data, int size, int esize, int i, int k, arg_comparefn* comparefn); +ARG_EXTERN void arg_make_get_help_msg(arg_dstr_t res); +ARG_EXTERN void arg_make_help_msg(arg_dstr_t ds, char* cmd_name, void** argtable); +ARG_EXTERN void arg_make_syntax_err_msg(arg_dstr_t ds, void** argtable, struct arg_end* end); +ARG_EXTERN int arg_make_syntax_err_help_msg(arg_dstr_t ds, char* name, int help, int nerrors, void** argtable, struct arg_end* end, int* exitcode); +ARG_EXTERN void arg_set_module_name(const char* name); +ARG_EXTERN void arg_set_module_version(int major, int minor, int patch, const char* tag); + +/**** deprecated functions, for back-compatibility only ********/ +ARG_EXTERN void arg_free(void** argtable); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/c/utf8filenamecheck/windows/argtable/examples/CMakeLists.txt b/c/utf8filenamecheck/windows/argtable/examples/CMakeLists.txt new file mode 100644 index 0000000..9e0be34 --- /dev/null +++ b/c/utf8filenamecheck/windows/argtable/examples/CMakeLists.txt @@ -0,0 +1,46 @@ +################################################################################ +# This file is part of the argtable3 library. +# +# Copyright (C) 2016-2019 Tom G. Huang +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of STEWART HEITMANN nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, +# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +################################################################################ + +file(GLOB EXAMPLES_SOURCES RELATIVE ${PROJECT_SOURCE_DIR}/examples *.c) + +if(UNIX) + set(ARGTABLE3_EXTRA_LIBS m) +endif() + +foreach(examples_src ${EXAMPLES_SOURCES}) + string(REPLACE ".c" "" examplename ${examples_src}) + add_executable(${examplename} ${PROJECT_SOURCE_DIR}/examples/${examples_src}) + target_include_directories(${examplename} PRIVATE ${PROJECT_SOURCE_DIR}/src) + if(ARGTABLE3_BUILD_STATIC_EXAMPLES) + target_link_libraries(${examplename} argtable3_static ${ARGTABLE3_EXTRA_LIBS}) + else() + target_link_libraries(${examplename} argtable3 ${ARGTABLE3_EXTRA_LIBS}) + endif() +endforeach() diff --git a/c/utf8filenamecheck/windows/argtable/examples/echo.c b/c/utf8filenamecheck/windows/argtable/examples/echo.c new file mode 100644 index 0000000..584db02 --- /dev/null +++ b/c/utf8filenamecheck/windows/argtable/examples/echo.c @@ -0,0 +1,128 @@ +/******************************************************************************* + * Example source code for using the argtable3 library to implement: + * + * echo [-neE] [--help] [--version] [STRING]... + * + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include "argtable3.h" + +/* Here we only approximate the echo functionality */ +void mymain(int n, int e, int E, const char** strings, int nstrings) + { + int j; + + printf("option -n = %s\n", ((n)?"YES":"NO")); + printf("option -e = %s\n", ((e)?"YES":"NO")); + printf("option -E = %s\n", ((E)?"YES":"NO")); + for (j=0; js"); + struct arg_lit *help = arg_lit0(NULL,"help", "print this help and exit"); + struct arg_lit *vers = arg_lit0(NULL,"version", "print version information and exit"); + struct arg_str *strs = arg_strn(NULL,NULL,"STRING",0,argc+2,NULL); + struct arg_end *end = arg_end(20); + void* argtable[] = {n,e,E,help,vers,strs,end}; + const char* progname = "echo"; + int exitcode=0; + int nerrors; + + /* verify the argtable[] entries were allocated sucessfully */ + if (arg_nullcheck(argtable) != 0) + { + /* NULL entries were detected, some allocations must have failed */ + printf("%s: insufficient memory\n",progname); + exitcode=1; + goto exit; + } + + /* Parse the command line as defined by argtable[] */ + nerrors = arg_parse(argc,argv,argtable); + + /* special case: '--help' takes precedence over error reporting */ + if (help->count > 0) + { + printf("Usage: %s", progname); + arg_print_syntax(stdout,argtable,"\n"); + printf("Echo the STRINGs to standard output.\n\n"); + arg_print_glossary(stdout,argtable," %-10s %s\n"); + printf("\nWithout -E, the following sequences are recognized and interpolated:\n\n" + " \\NNN the character whose ASCII code is NNN (octal)\n" + " \\\\ backslash\n" + " \\a alert (BEL)\n" + " \\b backspace\n" + " \\c suppress trailing newline\n" + " \\f form feed\n" + " \\n new line\n" + " \\r carriage return\n" + " \\t horizontal tab\n" + " \\v vertical tab\n\n" + "Report bugs to .\n"); + exitcode=0; + goto exit; + } + + /* special case: '--version' takes precedence error reporting */ + if (vers->count > 0) + { + printf("'%s' example program for the \"argtable\" command line argument parser.\n",progname); + printf("September 2003, Stewart Heitmann\n"); + exitcode=0; + goto exit; + } + + /* If the parser returned any errors then display them and exit */ + if (nerrors > 0) + { + /* Display the error details contained in the arg_end struct.*/ + arg_print_errors(stdout,end,progname); + printf("Try '%s --help' for more information.\n",progname); + exitcode=1; + goto exit; + } + + /* Command line parsing is complete, do the main processing */ + mymain(n->count, e->count, E->count, strs->sval, strs->count); + + exit: + /* deallocate each non-null entry in argtable[] */ + arg_freetable(argtable,sizeof(argtable)/sizeof(argtable[0])); + + return exitcode; + } diff --git a/c/utf8filenamecheck/windows/argtable/examples/ls.c b/c/utf8filenamecheck/windows/argtable/examples/ls.c new file mode 100644 index 0000000..345eb38 --- /dev/null +++ b/c/utf8filenamecheck/windows/argtable/examples/ls.c @@ -0,0 +1,326 @@ +/******************************************************************************* + * Example source code for using the argtable3 library to implement: + * + * ls [-aAbBcCdDfFgGhHiklLmnNopqQrRsStuUvxX1] [--author] + * [--block-size=SIZE] [--color=[WHEN]] [--format=WORD] [--full-time] + * [--si] [--dereference-command-line-symlink-to-dir] [--indicator-style=WORD] + * [-I PATTERN] [--show-control-chars] [--quoting-style=WORD] [--sort=WORD] + * [--time=WORD] [--time-style=STYLE] [-T COLS] [-w COLS] [--help] + * [--version] [FILE]... + * + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include "argtable3.h" + +/* These variables hold the values parsed from the comand line by arg_parse() */ +struct arg_lit *a, *A, *author, *b, *B, *c, *C, *d, *D, *f, *F, *fulltime; +struct arg_lit *g, *G, *h, *H, *si, *deref, *i, *k, *l, *L, *m, *n, *N, *o, *p; +struct arg_lit *q, *shcont, *Q, *r, *R, *s, *S, *t, *u, *U, *v, *x, *X, *one; +struct arg_lit *help, *version; +struct arg_int *blocksize, *T, *w; +struct arg_str *color, *format, *indic, *I, *Qstyle, *sort, *Time, *timesty; +struct arg_file *files; +struct arg_end *end; + +/* Here we simply echo the command line option values as a demonstration. */ +/* In a real program, this is where we would perform the main processing. */ +int mymain(void) + { + int j; + + if (a->count > 0) + printf("a=YES\n"); + if (A->count > 0) + printf("A=YES\n"); + if (author->count > 0) + printf("author=YES\n"); + if (b->count > 0) + printf("b=YES\n"); + if (blocksize->count > 0) + printf("blocksize=%d\n",blocksize->count); + if (B->count > 0) + printf("B=YES\n"); + if (c->count > 0) + printf("c=YES\n"); + if (C->count > 0) + printf("C=YES\n"); + if (color->count > 0) + printf("color=%s\n",color->sval[0]); + if (d->count > 0) + printf("d=YES\n"); + if (D->count > 0) + printf("D=YES\n"); + if (f->count > 0) + printf("f=YES\n"); + if (F->count > 0) + printf("F=YES\n"); + if (format->count > 0) + printf("format=%s\n",format->sval[0]); + if (fulltime->count > 0) + printf("fulltime=YES\n"); + if (g->count > 0) + printf("g=YES\n"); + if (G->count > 0) + printf("G=YES\n"); + if (h->count > 0) + printf("h=YES\n"); + if (si->count > 0) + printf("si=YES\n"); + if (H->count > 0) + printf("H=YES\n"); + if (deref->count > 0) + printf("deref=YES\n"); + if (indic->count > 0) + printf("indic=%s\n",indic->sval[0]); + if (i->count > 0) + printf("i=YES\n"); + if (I->count > 0) + printf("I=%s\n",I->sval[0]); + if (k->count > 0) + printf("k=YES\n"); + if (l->count > 0) + printf("l=YES\n"); + if (L->count > 0) + printf("L=YES\n"); + if (m->count > 0) + printf("m=YES\n"); + if (n->count > 0) + printf("n=YES\n"); + if (N->count > 0) + printf("N=YES\n"); + if (o->count > 0) + printf("o=YES\n"); + if (p->count > 0) + printf("p=YES\n"); + if (q->count > 0) + printf("q=YES\n"); + if (shcont->count > 0) + printf("shcont=YES\n"); + if (Q->count > 0) + printf("Q=YES\n"); + if (Qstyle->count > 0) + printf("Qstyle=%s\n",Qstyle->sval[0]); + if (r->count > 0) + printf("r=YES\n"); + if (R->count > 0) + printf("R=YES\n"); + if (s->count > 0) + printf("s=YES\n"); + if (S->count > 0) + printf("S=YES\n"); + if (sort->count > 0) + printf("sort=%s\n",sort->sval[0]); + if (Time->count > 0) + printf("time=%s\n",Time->sval[0]); + if (timesty->count > 0) + printf("timesty=%s\n",timesty->sval[0]); + if (t->count > 0) + printf("t=YES\n"); + if (T->count > 0) + printf("T=%d\n",T->ival[0]); + if (u->count > 0) + printf("u=YES\n"); + if (U->count > 0) + printf("U=YES\n"); + if (v->count > 0) + printf("v=YES\n"); + if (w->count > 0) + printf("w=%d\n",w->ival[0]); + if (x->count > 0) + printf("x=YES\n"); + if (X->count > 0) + printf("X=YES\n"); + if (one->count > 0) + printf("1=YES\n"); + + /* print the filenames */ + for (j=0; jcount; j++) + printf("filename[%d] = \"%s\"\n", j, files->filename[j]); + + return 0; + } + + +int main(int argc, char **argv) + { + /* The argtable[] entries define the command line options */ + void *argtable[] = { + a = arg_lit0("a", "all", "do not hide entries starting with ."), + A = arg_lit0("A", "almost-all", "do not list implied . and .."), + author = arg_lit0(NULL,"author", "print the author of each file"), + b = arg_lit0("b", "escape", "print octal escapes for nongraphic characters"), + blocksize = arg_int0(NULL,"block-size","SIZE", "use SIZE-byte blocks"), + B = arg_lit0("B", "ignore-backups", "do not list implied entries ending with ~"), + c = arg_lit0("c", NULL, "with -lt: sort by, and show, ctime (time of last"), + arg_rem(NULL, " modification of file status information)"), + arg_rem(NULL, " with -l: show ctime and sort by name"), + arg_rem(NULL, " otherwise: sort by ctime"), + C = arg_lit0("C", NULL, "list entries by columns"), + color = arg_str0(NULL,"color","WHEN", "control whether color is used to distinguish file"), + arg_rem(NULL, " types. WHEN may be `never', `always', or `auto'"), + d = arg_lit0("d", "directory", "list directory entries instead of contents,"), + arg_rem(NULL, " and do not dereference symbolic links"), + D = arg_lit0("D", "dired", "generate output designed for Emacs' dired mode"), + f = arg_lit0("f", NULL, "do not sort, enable -aU, disable -lst"), + F = arg_lit0("F", "classify", "append indicator (one of */=@|) to entries"), + format = arg_str0(NULL,"format","WORD", "across -x, commas -m, horizontal -x, long -l,"), + arg_rem (NULL, " single-column -1, verbose -l, vertical -C"), + fulltime = arg_lit0(NULL,"full-time", "like -l --time-style=full-iso"), + g = arg_lit0("g", NULL, "like -l, but do not list owner"), + G = arg_lit0("G", "no-group", "inhibit display of group information"), + h = arg_lit0("h", "human-readable", "print sizes in human readable format (e.g., 1K 234M 2G)"), + si = arg_lit0(NULL,"si", "likewise, but use powers of 1000 not 1024"), + H = arg_lit0("H", "dereference-command-line","follow symbolic links listed on the command line"), + deref = arg_lit0(NULL,"dereference-command-line-symlink-to-dir","follow each command line symbolic link"), + arg_rem(NULL, " that points to a directory"), + indic = arg_str0(NULL,"indicator-style","WORD","append indicator with style WORD to entry names:"), + arg_rem (NULL, " none (default), classify (-F), file-type (-p)"), + i = arg_lit0("i", "inode", "print index number of each file"), + I = arg_str0("I", "ignore","PATTERN", "do not list implied entries matching shell PATTERN"), + k = arg_lit0("k", NULL, "like --block-size=1K"), + l = arg_lit0("l", NULL, "use a long listing format"), + L = arg_lit0("L", "dereference", "when showing file information for a symbolic"), + arg_rem (NULL, " link, show information for the file the link"), + arg_rem (NULL, " references rather than for the link itself"), + m = arg_lit0("m", NULL, "fill width with a comma separated list of entries"), + n = arg_lit0("n", "numeric-uid-gid", "like -l, but list numeric UIDs and GIDs"), + N = arg_lit0("N", "literal", "print raw entry names (don't treat e.g. control"), + arg_rem (NULL, " characters specially)"), + o = arg_lit0("o", NULL, "like -l, but do not list group information"), + p = arg_lit0("p", "file-type", "append indicator (one of /=@|) to entries"), + q = arg_lit0("q", "hide-control-chars", "print ? instead of non graphic characters"), + shcont = arg_lit0(NULL,"show-control-chars", "show non graphic characters as-is (default"), + arg_rem (NULL, "unless program is `ls' and output is a terminal)"), + Q = arg_lit0("Q", "quote-name", "enclose entry names in double quotes"), + Qstyle = arg_str0(NULL,"quoting-style","WORD","use quoting style WORD for entry names:"), + arg_rem (NULL, " literal, locale, shell, shell-always, c, escape"), + r = arg_lit0("r", "reverse", "reverse order while sorting"), + R = arg_lit0("R", "recursive", "list subdirectories recursively"), + s = arg_lit0("s", "size", "print size of each file, in blocks"), + S = arg_lit0("S", NULL, "sort by file size"), + sort = arg_str0(NULL,"sort","WORD", "extension -X, none -U, size -S, time -t, version -v,"), + arg_rem (NULL, "status -c, time -t, atime -u, access -u, use -u"), + Time = arg_str0(NULL,"time","WORD", "show time as WORD instead of modification time:"), + arg_rem (NULL, " atime, access, use, ctime or status; use"), + arg_rem (NULL, " specified time as sort key if --sort=time"), + timesty = arg_str0(NULL, "time-style","STYLE", "show times using style STYLE:"), + arg_rem (NULL, " full-iso, long-iso, iso, locale, +FORMAT"), + arg_rem (NULL, "FORMAT is interpreted like `date'; if FORMAT is"), + arg_rem (NULL, "FORMAT1FORMAT2, FORMAT1 applies to"), + arg_rem (NULL, "non-recent files and FORMAT2 to recent files;"), + arg_rem (NULL, "if STYLE is prefixed with `posix-', STYLE"), + arg_rem (NULL, "takes effect only outside the POSIX locale"), + t = arg_lit0("t", NULL, "sort by modification time"), + T = arg_int0("T", "tabsize", "COLS", "assume tab stops at each COLS instead of 8"), + u = arg_lit0("u", NULL, "with -lt: sort by, and show, access time"), + arg_rem (NULL, " with -l: show access time and sort by name"), + arg_rem (NULL, " otherwise: sort by access time"), + U = arg_lit0("U", NULL, "do not sort; list entries in directory order"), + v = arg_lit0("v", NULL, "sort by version"), + w = arg_int0("w", "width", "COLS", "assume screen width instead of current value"), + x = arg_lit0("x", NULL, "list entries by lines instead of by columns"), + X = arg_lit0("X", NULL, "sort alphabetically by entry extension"), + one = arg_lit0("1", NULL, "list one file per line"), + help = arg_lit0(NULL,"help", "display this help and exit"), + version = arg_lit0(NULL,"version", "display version information and exit"), + files = arg_filen(NULL, NULL, "FILE", 0, argc+2, NULL), + end = arg_end(20), + }; + const char *progname = "ls"; + int exitcode=0; + int nerrors; + + /* verify the argtable[] entries were allocated sucessfully */ + if (arg_nullcheck(argtable) != 0) + { + /* NULL entries were detected, some allocations must have failed */ + printf("%s: insufficient memory\n",progname); + exitcode=1; + goto exit; + } + + /* allow optional argument values for --color */ + /* and set the default value to "always" */ + color->hdr.flag |= ARG_HASOPTVALUE; + color->sval[0] = "always"; + + /* Parse the command line as defined by argtable[] */ + nerrors = arg_parse(argc,argv,argtable); + + /* special case: '--help' takes precedence over error reporting */ + if (help->count > 0) + { + printf("Usage: %s", progname); + arg_print_syntax(stdout,argtable,"\n"); + printf("List information about the FILE(s) (the current directory by default).\n"); + printf("Sort entries alphabetically if none of -cftuSUX nor --sort.\n\n"); + arg_print_glossary(stdout,argtable," %-25s %s\n"); + printf("\nSIZE may be (or may be an integer optionally followed by) one of following:\n" + "kB 1000, K 1024, MB 1,000,000, M 1,048,576, and so on for G, T, P, E, Z, Y.\n\n" + "By default, color is not used to distinguish types of files. That is\n" + "equivalent to using --color=none. Using the --color option without the\n" + "optional WHEN argument is equivalent to using --color=always. With\n" + "--color=auto, color codes are output only if standard output is connected\n" + "to a terminal (tty).\n\n" + "Report bugs to .\n"); + exitcode=0; + goto exit; + } + + /* special case: '--version' takes precedence error reporting */ + if (version->count > 0) + { + printf("'%s' example program for the \"argtable\" command line argument parser.\n",progname); + printf("September 2003, Stewart Heitmann\n"); + exitcode=0; + goto exit; + } + + /* If the parser returned any errors then display them and exit */ + if (nerrors > 0) + { + /* Display the error details contained in the arg_end struct.*/ + arg_print_errors(stdout,end,progname); + printf("Try '%s --help' for more information.\n",progname); + exitcode=1; + goto exit; + } + + /* Command line parsing is complete, do the main processing */ + exitcode = mymain(); + +exit: + /* deallocate each non-null entry in argtable[] */ + arg_freetable(argtable,sizeof(argtable)/sizeof(argtable[0])); + + return exitcode; + } + + diff --git a/c/utf8filenamecheck/windows/argtable/examples/multisyntax.c b/c/utf8filenamecheck/windows/argtable/examples/multisyntax.c new file mode 100644 index 0000000..b5b7853 --- /dev/null +++ b/c/utf8filenamecheck/windows/argtable/examples/multisyntax.c @@ -0,0 +1,239 @@ +/******************************************************************************* + * Example source code for using the argtable3 library to implement + * a multi-syntax command line argument program + * + * usage 1: multisyntax [-nvR] insert []... [-o ] + * usage 2: multisyntax [-nv] remove + * usage 3: multisyntax [-v] search [-o ] + * usage 4: multisyntax [--help] [--version] + * + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include "argtable3.h" + +#define REG_EXTENDED 1 +#define REG_ICASE (REG_EXTENDED << 1) + +/* mymain1 implements the actions for syntax 1 */ +int mymain1(int n, int v, int R, const char *outfile, + const char **infiles, int ninfiles) + { + int i; + printf("syntax 1 matched OK:\n"); + printf("n=%d\n", n); + printf("v=%d\n", v); + printf("R=%d\n", R); + printf("outfile=\"%s\"\n", outfile); + for (i=0; i [file]... -o */ + struct arg_rex *cmd1 = arg_rex1(NULL, NULL, "insert", NULL, REG_ICASE, NULL); + struct arg_lit *noact1 = arg_lit0("n", NULL, "take no action"); + struct arg_lit *verbose1 = arg_lit0("v", "verbose", "verbose messages"); + struct arg_lit *recurse1 = arg_lit0("R", NULL, "recurse through subdirectories"); + struct arg_file *infiles1 = arg_filen(NULL, NULL, NULL, 1,argc+2, "input file(s)"); + struct arg_file *outfile1 = arg_file0("o", NULL, "", "output file (default is \"-\")"); + struct arg_end *end1 = arg_end(20); + void* argtable1[] = {cmd1,noact1,verbose1,recurse1,infiles1,outfile1,end1}; + int nerrors1; + + /* SYNTAX 2: remove [-nv] */ + struct arg_rex *cmd2 = arg_rex1(NULL, NULL, "remove", NULL, REG_ICASE, NULL); + struct arg_lit *noact2 = arg_lit0("n", NULL, NULL); + struct arg_lit *verbose2 = arg_lit0("v", "verbose", NULL); + struct arg_file *infiles2 = arg_file1(NULL, NULL, NULL, NULL); + struct arg_end *end2 = arg_end(20); + void* argtable2[] = {cmd2,noact2,verbose2,infiles2,end2}; + int nerrors2; + + /* SYNTAX 3: search [-v] [-o ] [--help] [--version] */ + struct arg_rex *cmd3 = arg_rex1(NULL, NULL, "search", NULL, REG_ICASE, NULL); + struct arg_lit *verbose3 = arg_lit0("v", "verbose", NULL); + struct arg_str *pattern3 = arg_str1(NULL, NULL, "", "search string"); + struct arg_file *outfile3 = arg_file0("o", NULL, "", NULL); + struct arg_end *end3 = arg_end(20); + void* argtable3[] = {cmd3,verbose3,pattern3,outfile3,end3}; + int nerrors3; + + /* SYNTAX 4: [-help] [-version] */ + struct arg_lit *help4 = arg_lit0(NULL,"help", "print this help and exit"); + struct arg_lit *version4 = arg_lit0(NULL,"version", "print version information and exit"); + struct arg_end *end4 = arg_end(20); + void* argtable4[] = {help4,version4,end4}; + int nerrors4; + + const char* progname = "multisyntax"; + int exitcode=0; + + /* verify all argtable[] entries were allocated sucessfully */ + if (arg_nullcheck(argtable1)!=0 || + arg_nullcheck(argtable2)!=0 || + arg_nullcheck(argtable3)!=0 || + arg_nullcheck(argtable4)!=0 ) + { + /* NULL entries were detected, some allocations must have failed */ + printf("%s: insufficient memory\n",progname); + exitcode=1; + goto exit; + } + + /* set any command line default values prior to parsing */ + outfile1->filename[0]="-"; + outfile3->filename[0]="-"; + + /* Above we defined a separate argtable for each possible command line syntax */ + /* and here we parse each one in turn to see if any of them are successful */ + nerrors1 = arg_parse(argc,argv,argtable1); + nerrors2 = arg_parse(argc,argv,argtable2); + nerrors3 = arg_parse(argc,argv,argtable3); + nerrors4 = arg_parse(argc,argv,argtable4); + + /* Execute the appropriate main routine for the matching command line syntax */ + /* In this example program our alternate command line syntaxes are mutually */ + /* exclusive, so we know in advance that only one of them can be successful. */ + if (nerrors1==0) + exitcode = mymain1(noact1->count, verbose1->count, recurse1->count, + outfile1->filename[0], infiles1->filename, infiles1->count); + else if (nerrors2==0) + exitcode = mymain2(noact2->count, verbose2->count, infiles2->filename[0]); + else if (nerrors3==0) + exitcode = mymain3(verbose3->count, pattern3->sval[0], outfile3->filename[0]); + else if (nerrors4==0) + exitcode = mymain4(help4->count, version4->count, progname, + argtable1, argtable2, argtable3, argtable4); + else + { + /* We get here if the command line matched none of the possible syntaxes */ + if (cmd1->count > 0) + { + /* here the cmd1 argument was correct, so presume syntax 1 was intended target */ + arg_print_errors(stdout,end1,progname); + printf("usage: %s ", progname); + arg_print_syntax(stdout,argtable1,"\n"); + } + else if (cmd2->count > 0) + { + /* here the cmd2 argument was correct, so presume syntax 2 was intended target */ + arg_print_errors(stdout,end2,progname); + printf("usage: %s ", progname); + arg_print_syntax(stdout,argtable2,"\n"); + } + else if (cmd3->count > 0) + { + /* here the cmd3 argument was correct, so presume syntax 3 was intended target */ + arg_print_errors(stdout,end3,progname); + printf("usage: %s ", progname); + arg_print_syntax(stdout,argtable3,"\n"); + } + else + { + /* no correct cmd literals were given, so we cant presume which syntax was intended */ + printf("%s: missing command.\n",progname); + printf("usage 1: %s ", progname); arg_print_syntax(stdout,argtable1,"\n"); + printf("usage 2: %s ", progname); arg_print_syntax(stdout,argtable2,"\n"); + printf("usage 3: %s ", progname); arg_print_syntax(stdout,argtable3,"\n"); + printf("usage 4: %s", progname); arg_print_syntax(stdout,argtable4,"\n"); + } + } + +exit: + /* deallocate each non-null entry in each argtable */ + arg_freetable(argtable1,sizeof(argtable1)/sizeof(argtable1[0])); + arg_freetable(argtable2,sizeof(argtable2)/sizeof(argtable2[0])); + arg_freetable(argtable3,sizeof(argtable3)/sizeof(argtable3[0])); + arg_freetable(argtable4,sizeof(argtable4)/sizeof(argtable4[0])); + + return exitcode; + } diff --git a/c/utf8filenamecheck/windows/argtable/examples/mv.c b/c/utf8filenamecheck/windows/argtable/examples/mv.c new file mode 100644 index 0000000..1381adf --- /dev/null +++ b/c/utf8filenamecheck/windows/argtable/examples/mv.c @@ -0,0 +1,179 @@ +/******************************************************************************* + * Example source code for using the argtable3 library to implement: + * + * mv [-bfiuv] [--backup=[CONTROL]] [--reply={yes,no,query}] + * [--strip-trailing-slashes] [-S SUFFIX] [--target-directory=DIRECTORY] + * [--help] [--version] SOURCE [SOURCE]... DEST|DIRECTORY + * + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include "argtable3.h" + +int mymain(const char *backup_control, + int backup, + int force, + int interactive, + const char *reply, + int strip_trailing_slashes, + const char *suffix, + const char *targetdir, + int update, + int verbose, + const char **files, + int nfiles) + { + int j; + + /* if verbose option was given then display all option settings */ + if (verbose) + { + printf("backup = %s\n", ((backup)?"YES":"NO")); + printf("backup CONTROL = %s\n", backup_control); + printf("force = %s\n", ((force)?"YES":"NO")); + printf("interactive mode = %s\n", ((interactive)?"YES":"NO")); + printf("reply = %s\n", reply); + printf("strip-trailing-slashes = %s\n", ((strip_trailing_slashes)?"YES":"NO")); + printf("suffix = %s\n", suffix); + printf("target-directory = %s\n", targetdir); + printf("update = %s\n", ((update)?"YES":"NO")); + printf("verbose = %s\n", ((verbose)?"YES":"NO")); + } + + /* print the source filenames */ + for (j=0; jsval[0] = "existing"; /* --backup={none,off,numbered,t,existing,nil,simple,never} */ + suffix->sval[0] = "~"; /* --suffix=~ */ + reply->sval[0] = "query"; /* --reply={yes,no,query} */ + targetd->sval[0] = NULL; + + /* Parse the command line as defined by argtable[] */ + nerrors = arg_parse(argc,argv,argtable); + + /* special case: '--help' takes precedence over error reporting */ + if (help->count > 0) + { + printf("Usage: %s", progname); + arg_print_syntax(stdout,argtable,"\n"); + printf("Rename SOURCE to DEST, or move SOURCE(s) to DIRECTORY.\n\n"); + arg_print_glossary(stdout,argtable," %-30s %s\n"); + printf("\nThe backup suffix is \"~\", unless set with --suffix or SIMPLE_BACKUP_SUFFIX.\n" + "The version control method may be selected via the --backup option or through\n" + "the VERSION_CONTROL environment variable. Here are the values:\n\n" + " none, off never make backups (even if --backup is given)\n" + " numbered, t make numbered backups\n" + " existing, nil numbered if numbered backups exist, simple otherwise\n" + " simple, never always make simple backups\n\n" + "Report bugs to .\n"); + exitcode=0; + goto exit; + } + + /* special case: '--version' takes precedence error reporting */ + if (version->count > 0) + { + printf("'%s' example program for the \"argtable\" command line argument parser.\n",progname); + printf("September 2003, Stewart Heitmann\n"); + exitcode=0; + goto exit; + } + + /* If the parser returned any errors then display them and exit */ + if (nerrors > 0) + { + /* Display the error details contained in the arg_end struct.*/ + arg_print_errors(stdout,end,progname); + printf("Try '%s --help' for more information.\n",progname); + exitcode=1; + goto exit; + } + + /* Command line parsing is complete, do the main processing */ + exitcode = mymain(backupc->sval[0], + backup->count, + force->count, + interact->count, + reply->sval[0], + strpslsh->count, + suffix->sval[0], + targetd->sval[0], + update->count, + verbose->count, + files->filename, + files->count); + +exit: + /* deallocate each non-null entry in argtable[] */ + arg_freetable(argtable,sizeof(argtable)/sizeof(argtable[0])); + + return exitcode; + } diff --git a/c/utf8filenamecheck/windows/argtable/examples/myprog.c b/c/utf8filenamecheck/windows/argtable/examples/myprog.c new file mode 100644 index 0000000..5a152ba --- /dev/null +++ b/c/utf8filenamecheck/windows/argtable/examples/myprog.c @@ -0,0 +1,147 @@ +/******************************************************************************* + * Example source code for using the argtable3 library to implement: + * + * myprog [-lRv] [-k ] [-D MACRO]... [-o ] [--help] + * [--version] []... + * + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include + +int mymain(int l, int R, int k, + const char **defines, int ndefines, + const char *outfile, + int v, + const char **infiles, int ninfiles) + { + int i; + + if (l>0) printf("list files (-l)\n"); + if (R>0) printf("recurse through directories (-R)\n"); + if (v>0) printf("verbose is enabled (-v)\n"); + printf("scalar k=%d\n",k); + printf("output is \"%s\"\n", outfile); + + for (i=0; i", "output file (default is \"-\")"); + struct arg_lit *verbose = arg_lit0("v","verbose,debug", "verbose messages"); + struct arg_lit *help = arg_lit0(NULL,"help", "print this help and exit"); + struct arg_lit *version = arg_lit0(NULL,"version", "print version information and exit"); + struct arg_file *infiles = arg_filen(NULL,NULL,NULL,1,argc+2, "input file(s)"); + struct arg_end *end = arg_end(20); + void* argtable[] = {list,recurse,repeat,defines,outfile,verbose,help,version,infiles,end}; + const char* progname = "myprog"; + int nerrors; + int exitcode=0; + + /* verify the argtable[] entries were allocated sucessfully */ + if (arg_nullcheck(argtable) != 0) + { + /* NULL entries were detected, some allocations must have failed */ + printf("%s: insufficient memory\n",progname); + exitcode=1; + goto exit; + } + + /* set any command line default values prior to parsing */ + repeat->ival[0]=3; + outfile->filename[0]="-"; + + /* Parse the command line as defined by argtable[] */ + nerrors = arg_parse(argc,argv,argtable); + + /* special case: '--help' takes precedence over error reporting */ + if (help->count > 0) + { + printf("Usage: %s", progname); + arg_print_syntax(stdout,argtable,"\n"); + printf("This program demonstrates the use of the argtable2 library\n"); + printf("for parsing command line arguments. Argtable accepts integers\n"); + printf("in decimal (123), hexadecimal (0xff), octal (0o123) and binary\n"); + printf("(0b101101) formats. Suffixes KB, MB and GB are also accepted.\n"); + arg_print_glossary(stdout,argtable," %-25s %s\n"); + exitcode=0; + goto exit; + } + + /* special case: '--version' takes precedence error reporting */ + if (version->count > 0) + { + printf("'%s' example program for the \"argtable\" command line argument parser.\n",progname); + printf("September 2003, Stewart Heitmann\n"); + exitcode=0; + goto exit; + } + + /* If the parser returned any errors then display them and exit */ + if (nerrors > 0) + { + /* Display the error details contained in the arg_end struct.*/ + arg_print_errors(stdout,end,progname); + printf("Try '%s --help' for more information.\n",progname); + exitcode=1; + goto exit; + } + + /* special case: uname with no command line options induces brief help */ + if (argc==1) + { + printf("Try '%s --help' for more information.\n",progname); + exitcode=0; + goto exit; + } + + /* normal case: take the command line options at face value */ + exitcode = mymain(list->count, recurse->count, repeat->ival[0], + defines->sval, defines->count, + outfile->filename[0], verbose->count, + infiles->filename, infiles->count); + + exit: + /* deallocate each non-null entry in argtable[] */ + arg_freetable(argtable,sizeof(argtable)/sizeof(argtable[0])); + + return exitcode; + } diff --git a/c/utf8filenamecheck/windows/argtable/examples/myprog_C89.c b/c/utf8filenamecheck/windows/argtable/examples/myprog_C89.c new file mode 100644 index 0000000..b88d278 --- /dev/null +++ b/c/utf8filenamecheck/windows/argtable/examples/myprog_C89.c @@ -0,0 +1,165 @@ +/******************************************************************************* + * This example source code is an alternate version of myprog.c + * that adheres to ansi C89 standards rather than ansi C99. + * The only difference being that C89 does not permit the argtable array + * to be statically initialized with the contents of variables set at + * runtime whereas C99 does. + * Hence we cannot declare and initialize the argtable array in one declaration + * as + * void* argtable[] = {list, recurse, repeat, defines, outfile, verbose, + * help, version, infiles, end}; + * Instead, we must declare + * void* argtable[10]; + * and initialize the contents of the array separately. + * + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include "argtable3.h" + +int mymain(int l, int R, int k, + const char **defines, int ndefines, + const char *outfile, + int v, + const char **infiles, int ninfiles) + { + int i; + + if (l>0) printf("list files (-l)\n"); + if (R>0) printf("recurse through directories (-R)\n"); + if (v>0) printf("verbose is enabled (-v)\n"); + printf("scalar k=%d\n",k); + printf("output is \"%s\"\n", outfile); + + for (i=0; i", "output file (default is \"-\")"); + struct arg_lit *verbose = arg_lit0("v","verbose,debug", "verbose messages"); + struct arg_lit *help = arg_lit0(NULL,"help", "print this help and exit"); + struct arg_lit *version = arg_lit0(NULL,"version", "print version information and exit"); + struct arg_file *infiles = arg_filen(NULL,NULL,NULL,1,argc+2, "input file(s)"); + struct arg_end *end = arg_end(20); + void* argtable[10]; + const char* progname = "myprog_C89"; + int nerrors; + int exitcode=0; + + /* initialize the argtable array with ptrs to the arg_xxx structures constructed above */ + argtable[0] = list; + argtable[1] = recurse; + argtable[2] = repeat; + argtable[3] = defines; + argtable[4] = outfile; + argtable[5] = verbose; + argtable[6] = help; + argtable[7] = version; + argtable[8] = infiles; + argtable[9] = end; + + /* verify the argtable[] entries were allocated sucessfully */ + if (arg_nullcheck(argtable) != 0) + { + /* NULL entries were detected, some allocations must have failed */ + printf("%s: insufficient memory\n",progname); + exitcode=1; + goto exit; + } + + /* set any command line default values prior to parsing */ + repeat->ival[0]=3; + outfile->filename[0]="-"; + + /* Parse the command line as defined by argtable[] */ + nerrors = arg_parse(argc,argv,argtable); + + /* special case: '--help' takes precedence over error reporting */ + if (help->count > 0) + { + printf("Usage: %s", progname); + arg_print_syntax(stdout,argtable,"\n"); + printf("This program demonstrates the use of the argtable2 library\n"); + printf("for parsing command line arguments.\n"); + arg_print_glossary(stdout,argtable," %-25s %s\n"); + exitcode=0; + goto exit; + } + + /* special case: '--version' takes precedence error reporting */ + if (version->count > 0) + { + printf("'%s' example program for the \"argtable\" command line argument parser.\n",progname); + printf("September 2003, Stewart Heitmann\n"); + exitcode=0; + goto exit; + } + + /* If the parser returned any errors then display them and exit */ + if (nerrors > 0) + { + /* Display the error details contained in the arg_end struct.*/ + arg_print_errors(stdout,end,progname); + printf("Try '%s --help' for more information.\n",progname); + exitcode=1; + goto exit; + } + + /* special case: uname with no command line options induces brief help */ + if (argc==1) + { + printf("Try '%s --help' for more information.\n",progname); + exitcode=0; + goto exit; + } + + /* normal case: take the command line options at face value */ + exitcode = mymain(list->count, recurse->count, repeat->ival[0], + defines->sval, defines->count, + outfile->filename[0], verbose->count, + infiles->filename, infiles->count); + + exit: + /* deallocate each non-null entry in argtable[] */ + arg_freetable(argtable,sizeof(argtable)/sizeof(argtable[0])); + + return exitcode; + } diff --git a/c/utf8filenamecheck/windows/argtable/examples/testargtable3.c b/c/utf8filenamecheck/windows/argtable/examples/testargtable3.c new file mode 100644 index 0000000..be19f3c --- /dev/null +++ b/c/utf8filenamecheck/windows/argtable/examples/testargtable3.c @@ -0,0 +1,58 @@ +#include "argtable3.h" + +/* global arg_xxx structs */ +struct arg_lit *a, *b, *c, *verb, *help, *version; +struct arg_int *scal; +struct arg_file *o, *file; +struct arg_end *end; + +int main(int argc, char *argv[]) +{ + /* the global arg_xxx structs are initialised within the argtable */ + void *argtable[] = { + help = arg_lit0(NULL, "help", "display this help and exit"), + version = arg_lit0(NULL, "version", "display version info and exit"), + a = arg_lit0("a", NULL,"the -a option"), + b = arg_lit0("b", NULL, "the -b option"), + c = arg_lit0("c", NULL, "the -c option"), + scal = arg_int0(NULL, "scalar", "", "foo value"), + verb = arg_lit0("v", "verbose", "verbose output"), + o = arg_file0("o", NULL, "myfile", "output file"), + file = arg_filen(NULL, NULL, "", 1, 100, "input files"), + end = arg_end(20), + }; + + int exitcode = 0; + char progname[] = "testargtable2.exe"; + + int nerrors; + nerrors = arg_parse(argc,argv,argtable); + + /* special case: '--help' takes precedence over error reporting */ + if (help->count > 0) + { + printf("Usage: %s", progname); + arg_print_syntax(stdout, argtable, "\n"); + printf("List information about the FILE(s) " + "(the current directory by default).\n\n"); + arg_print_glossary(stdout, argtable, " %-25s %s\n"); + exitcode = 0; + goto exit; + } + + /* If the parser returned any errors then display them and exit */ + if (nerrors > 0) + { + /* Display the error details contained in the arg_end struct.*/ + arg_print_errors(stdout, end, progname); + printf("Try '%s --help' for more information.\n", progname); + exitcode = 1; + goto exit; + } + +exit: + /* deallocate each non-null entry in argtable[] */ + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); + return exitcode; +} + diff --git a/c/utf8filenamecheck/windows/argtable/examples/uname.c b/c/utf8filenamecheck/windows/argtable/examples/uname.c new file mode 100644 index 0000000..ac3e40c --- /dev/null +++ b/c/utf8filenamecheck/windows/argtable/examples/uname.c @@ -0,0 +1,137 @@ +/******************************************************************************* + * Example source code for using the argtable3 library to implement: + * + * uname [-asnrvmpio] [--help] [--version] + * + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include "argtable3.h" + +/* Here we simulate the uname functionality */ +int mymain(int kname, int nname, int krel, int kver, int mach, int proc, int hard, int opsys) + { + if (kname) printf("Linux "); + if (nname) printf("localhost.localdomain "); + if (krel) printf("2.4.19-16 "); + if (kver) printf("#1 Fri Sep 20 18:15:05 CEST 2002 "); + if (mach) printf("i686 "); + if (proc) printf("Intel "); + if (hard) printf("unknown "); + if (opsys) printf("GNU/Linux "); + printf("\n"); + return 0; + } + + +int main(int argc, char **argv) + { + const char* progname = "uname"; + struct arg_lit *all = arg_lit0("a", "all", "print all information, in the following order:"); + struct arg_lit *kname = arg_lit0("s", "kernel-name", "print the kernel name"); + struct arg_lit *nname = arg_lit0("n", "nodename", "print the node name"); + struct arg_lit *krel = arg_lit0("r", "kernel-release", "print the kernel release"); + struct arg_lit *kver = arg_lit0("v", "kernel-version", "print the kernel version"); + struct arg_lit *mach = arg_lit0("m", "machine", "print the machine hardware name"); + struct arg_lit *proc = arg_lit0("p", "processor", "print the processor type"); + struct arg_lit *hard = arg_lit0("i", "hardware-platform","print the hardware platform"); + struct arg_lit *opsys = arg_lit0("o", "operating-system", "print the operating system"); + struct arg_lit *help = arg_lit0(NULL,"help", "print this help and exit"); + struct arg_lit *vers = arg_lit0(NULL,"version", "print version information and exit"); + struct arg_end *end = arg_end(20); + void* argtable[] = {all,kname,nname,krel,kver,mach,proc,hard,opsys,help,vers,end}; + int nerrors; + int exitcode=0; + + /* verify the argtable[] entries were allocated sucessfully */ + if (arg_nullcheck(argtable) != 0) + { + /* NULL entries were detected, some allocations must have failed */ + printf("%s: insufficient memory\n",progname); + exitcode=1; + goto exit; + } + + /* Parse the command line as defined by argtable[] */ + nerrors = arg_parse(argc,argv,argtable); + + /* special case: '--help' takes precedence over error reporting */ + if (help->count > 0) + { + printf("Usage: %s", progname); + arg_print_syntax(stdout,argtable,"\n"); + printf("Print certain system information. With no options, same as -s.\n\n"); + arg_print_glossary(stdout,argtable," %-25s %s\n"); + printf("\nReport bugs to .\n"); + exitcode=0; + goto exit; + } + + /* special case: '--version' takes precedence error reporting */ + if (vers->count > 0) + { + printf("'%s' example program for the \"argtable\" command line argument parser.\n",progname); + printf("September 2003, Stewart Heitmann\n"); + exitcode=0; + goto exit; + } + + /* If the parser returned any errors then display them and exit */ + if (nerrors > 0) + { + /* Display the error details contained in the arg_end struct.*/ + arg_print_errors(stdout,end,progname); + printf("Try '%s --help' for more information.\n",progname); + exitcode=1; + goto exit; + } + + /* special case: uname with no command line options is equivalent to "uname -s" */ + if (argc==1) + { + exitcode = mymain(0,1,0,0,0,0,0,0); + goto exit; + } + + /* special case: "uname -a" is equivalent to "uname -snrvmpi" */ + if (all->count>0) + { + exitcode = mymain(1,1,1,1,1,1,1,1); + goto exit; + } + + /* normal case: take the command line options at face value */ + exitcode = mymain(kname->count, nname->count, krel->count, kver->count, mach->count, proc->count, hard->count, opsys->count); + + exit: + /* deallocate each non-null entry in argtable[] */ + arg_freetable(argtable,sizeof(argtable)/sizeof(argtable[0])); + + return exitcode; + } diff --git a/c/utf8filenamecheck/windows/argtable/tests/CMakeLists.txt b/c/utf8filenamecheck/windows/argtable/tests/CMakeLists.txt new file mode 100644 index 0000000..e4a553c --- /dev/null +++ b/c/utf8filenamecheck/windows/argtable/tests/CMakeLists.txt @@ -0,0 +1,89 @@ +################################################################################ +# This file is part of the argtable3 library. +# +# Copyright (C) 2016-2019 Tom G. Huang +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of STEWART HEITMANN nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, +# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +################################################################################ + +set(TEST_PUBLIC_SRC_FILES + testall.c + testarglit.c + testargstr.c + testargint.c + testargdate.c + testargdbl.c + testargfile.c + testargrex.c + testargdstr.c + testargcmd.c + CuTest.c +) + +set(TEST_SRC_FILES + ${TEST_PUBLIC_SRC_FILES} + testarghashtable.c +) + +if(UNIX) + set(ARGTABLE3_EXTRA_LIBS m) +endif() + +add_executable(test_shared ${TEST_PUBLIC_SRC_FILES}) +target_compile_definitions(test_shared PRIVATE -DARGTABLE3_TEST_PUBLIC_ONLY) +target_include_directories(test_shared PRIVATE ${PROJECT_SOURCE_DIR}/src) +target_link_libraries(test_shared argtable3 ${ARGTABLE3_EXTRA_LIBS}) +add_custom_command(TARGET test_shared POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + "$" + "$" +) + +add_executable(test_static ${TEST_SRC_FILES}) +target_compile_definitions(test_static PRIVATE -DARGTABLE3_TEST_PUBLIC_ONLY) +target_include_directories(test_static PRIVATE ${PROJECT_SOURCE_DIR}/src) +target_link_libraries(test_static argtable3_static ${ARGTABLE3_EXTRA_LIBS}) + +add_executable(test_src ${TEST_SRC_FILES} ${ARGTABLE3_SRC_FILES}) +target_include_directories(test_src PRIVATE ${PROJECT_SOURCE_DIR}/src) +target_link_libraries(test_src ${ARGTABLE3_EXTRA_LIBS}) + +add_custom_command(OUTPUT ${ARGTABLE3_AMALGAMATION_SRC_FILE} + COMMAND "${PROJECT_SOURCE_DIR}/tools/build" dist + WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/tools" +) + +add_executable(test_amalgamation ${TEST_SRC_FILES} ${ARGTABLE3_AMALGAMATION_SRC_FILE}) +target_include_directories(test_amalgamation PRIVATE ${PROJECT_SOURCE_DIR}/src) +target_link_libraries(test_amalgamation ${ARGTABLE3_EXTRA_LIBS}) +add_custom_command(TARGET test_amalgamation PRE_BUILD + COMMAND "${PROJECT_SOURCE_DIR}/tools/build" dist + WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/tools" +) + +add_test(NAME test_shared COMMAND "$") +add_test(NAME test_static COMMAND "$") +add_test(NAME test_src COMMAND "$") +add_test(NAME test_amalgamation COMMAND "$") diff --git a/c/utf8filenamecheck/windows/argtable/tests/CuTest.c b/c/utf8filenamecheck/windows/argtable/tests/CuTest.c new file mode 100644 index 0000000..9d885a7 --- /dev/null +++ b/c/utf8filenamecheck/windows/argtable/tests/CuTest.c @@ -0,0 +1,325 @@ +#include +#include +#include +#include +#include +#include + +#include "CuTest.h" + +/*-------------------------------------------------------------------------* + * CuStr + *-------------------------------------------------------------------------*/ + +char* CuStrAlloc(size_t size) { + char* newStr = (char*)malloc(sizeof(char) * (size)); + return newStr; +} + +char* CuStrCopy(const char* old) { + size_t len = strlen(old); + char* newStr = CuStrAlloc(len + 1); +#if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__)) + strcpy_s(newStr, len + 1, old); +#else + strcpy(newStr, old); +#endif + + return newStr; +} + +/*-------------------------------------------------------------------------* + * CuString + *-------------------------------------------------------------------------*/ + +void CuStringInit(CuString* str) { + str->length = 0; + str->size = STRING_MAX; + str->buffer = (char*)malloc(sizeof(char) * str->size); + str->buffer[0] = '\0'; +} + +CuString* CuStringNew(void) { + CuString* str = (CuString*)malloc(sizeof(CuString)); + str->length = 0; + str->size = STRING_MAX; + str->buffer = (char*)malloc(sizeof(char) * str->size); + str->buffer[0] = '\0'; + return str; +} + +void CuStringDelete(CuString* str) { + if (!str) + return; + free(str->buffer); + free(str); +} + +void CuStringResize(CuString* str, size_t newSize) { + str->buffer = (char*)realloc(str->buffer, sizeof(char) * newSize); + str->size = newSize; +} + +void CuStringAppend(CuString* str, const char* text) { + size_t length; + + if (text == NULL) { + text = "NULL"; + } + + length = strlen(text); + if (str->length + length + 1 >= str->size) + CuStringResize(str, str->length + length + 1 + STRING_INC); + str->length += length; +#if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__)) + strcat_s(str->buffer, str->size, text); +#else + strcat(str->buffer, text); +#endif +} + +void CuStringAppendChar(CuString* str, char ch) { + char text[2]; + text[0] = ch; + text[1] = '\0'; + CuStringAppend(str, text); +} + +void CuStringAppendFormat(CuString* str, const char* format, ...) { + va_list argp; + char buf[HUGE_STRING_LEN]; + va_start(argp, format); +#if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__)) + vsprintf_s(buf, sizeof(buf), format, argp); +#else + vsprintf(buf, format, argp); +#endif + + va_end(argp); + CuStringAppend(str, buf); +} + +void CuStringInsert(CuString* str, const char* text, int pos) { + size_t length = strlen(text); + if ((size_t)pos > str->length) + pos = (int)str->length; + if (str->length + length + 1 >= str->size) + CuStringResize(str, str->length + length + 1 + STRING_INC); + memmove(str->buffer + pos + length, str->buffer + pos, (str->length - pos) + 1); + str->length += length; + memcpy(str->buffer + pos, text, length); +} + +/*-------------------------------------------------------------------------* + * CuTest + *-------------------------------------------------------------------------*/ + +void CuTestInit(CuTest* t, const char* name, TestFunction function) { + t->name = CuStrCopy(name); + t->failed = 0; + t->ran = 0; + t->message = NULL; + t->function = function; + t->jumpBuf = NULL; +} + +CuTest* CuTestNew(const char* name, TestFunction function) { + CuTest* tc = CU_ALLOC(CuTest); + CuTestInit(tc, name, function); + return tc; +} + +void CuTestDelete(CuTest* t) { + if (!t) + return; + free(t->name); + free(t); +} + +void CuTestRun(CuTest* tc) { + jmp_buf buf; + tc->jumpBuf = &buf; + if (setjmp(buf) == 0) { + tc->ran = 1; + (tc->function)(tc); + } + tc->jumpBuf = 0; +} + +static void CuFailInternal(CuTest* tc, const char* file, int line, CuString* string) { + char buf[HUGE_STRING_LEN]; + +#if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__)) + sprintf_s(buf, sizeof(buf), "%s:%d: ", file, line); +#else + sprintf(buf, "%s:%d: ", file, line); +#endif + CuStringInsert(string, buf, 0); + + tc->failed = 1; + tc->message = string->buffer; + if (tc->jumpBuf != 0) + longjmp(*(tc->jumpBuf), 0); +} + +void CuFail_Line(CuTest* tc, const char* file, int line, const char* message2, const char* message) { + CuString string; + + CuStringInit(&string); + if (message2 != NULL) { + CuStringAppend(&string, message2); + CuStringAppend(&string, ": "); + } + CuStringAppend(&string, message); + CuFailInternal(tc, file, line, &string); +} + +void CuAssert_Line(CuTest* tc, const char* file, int line, const char* message, int condition) { + if (condition) + return; + CuFail_Line(tc, file, line, NULL, message); +} + +void CuAssertStrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, const char* expected, const char* actual) { + CuString string; + if ((expected == NULL && actual == NULL) || (expected != NULL && actual != NULL && strcmp(expected, actual) == 0)) { + return; + } + + CuStringInit(&string); + if (message != NULL) { + CuStringAppend(&string, message); + CuStringAppend(&string, ": "); + } + CuStringAppend(&string, "expected <"); + CuStringAppend(&string, expected); + CuStringAppend(&string, "> but was <"); + CuStringAppend(&string, actual); + CuStringAppend(&string, ">"); + CuFailInternal(tc, file, line, &string); +} + +void CuAssertIntEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, int expected, int actual) { + char buf[STRING_MAX]; + if (expected == actual) + return; +#if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__)) + sprintf_s(buf, sizeof(buf), "expected <%d> but was <%d>", expected, actual); +#else + sprintf(buf, "expected <%d> but was <%d>", expected, actual); +#endif + CuFail_Line(tc, file, line, message, buf); +} + +void CuAssertDblEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, double expected, double actual, double delta) { + char buf[STRING_MAX]; + if (fabs(expected - actual) <= delta) + return; +#if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__)) + sprintf_s(buf, sizeof(buf), "expected <%f> but was <%f>", expected, actual); +#else + sprintf(buf, "expected <%f> but was <%f>", expected, actual); +#endif + CuFail_Line(tc, file, line, message, buf); +} + +void CuAssertPtrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, void* expected, void* actual) { + char buf[STRING_MAX]; + if (expected == actual) + return; +#if (defined(__STDC_LIB_EXT1__) && defined(__STDC_WANT_LIB_EXT1__)) || (defined(__STDC_SECURE_LIB__) && defined(__STDC_WANT_SECURE_LIB__)) + sprintf_s(buf, sizeof(buf), "expected pointer <0x%p> but was <0x%p>", expected, actual); +#else + sprintf(buf, "expected pointer <0x%p> but was <0x%p>", expected, actual); +#endif + CuFail_Line(tc, file, line, message, buf); +} + +/*-------------------------------------------------------------------------* + * CuSuite + *-------------------------------------------------------------------------*/ + +void CuSuiteInit(CuSuite* testSuite) { + testSuite->count = 0; + testSuite->failCount = 0; + memset(testSuite->list, 0, sizeof(testSuite->list)); +} + +CuSuite* CuSuiteNew(void) { + CuSuite* testSuite = CU_ALLOC(CuSuite); + CuSuiteInit(testSuite); + return testSuite; +} + +void CuSuiteDelete(CuSuite* testSuite) { + unsigned int n; + for (n = 0; n < MAX_TEST_CASES; n++) { + if (testSuite->list[n]) { + CuTestDelete(testSuite->list[n]); + } + } + free(testSuite); +} + +void CuSuiteAdd(CuSuite* testSuite, CuTest* testCase) { + assert(testSuite->count < MAX_TEST_CASES); + testSuite->list[testSuite->count] = testCase; + testSuite->count++; +} + +void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2) { + int i; + for (i = 0; i < testSuite2->count; ++i) { + CuTest* testCase = testSuite2->list[i]; + CuSuiteAdd(testSuite, testCase); + } +} + +void CuSuiteRun(CuSuite* testSuite) { + int i; + for (i = 0; i < testSuite->count; ++i) { + CuTest* testCase = testSuite->list[i]; + CuTestRun(testCase); + if (testCase->failed) { + testSuite->failCount += 1; + } + } +} + +void CuSuiteSummary(CuSuite* testSuite, CuString* summary) { + int i; + for (i = 0; i < testSuite->count; ++i) { + CuTest* testCase = testSuite->list[i]; + CuStringAppend(summary, testCase->failed ? "F" : "."); + } + CuStringAppend(summary, "\n\n"); +} + +void CuSuiteDetails(CuSuite* testSuite, CuString* details) { + int i; + int failCount = 0; + + if (testSuite->failCount == 0) { + int passCount = testSuite->count - testSuite->failCount; + const char* testWord = passCount == 1 ? "test" : "tests"; + CuStringAppendFormat(details, "OK (%d %s)\n", passCount, testWord); + } else { + if (testSuite->failCount == 1) + CuStringAppend(details, "There was 1 failure:\n"); + else + CuStringAppendFormat(details, "There were %d failures:\n", testSuite->failCount); + + for (i = 0; i < testSuite->count; ++i) { + CuTest* testCase = testSuite->list[i]; + if (testCase->failed) { + failCount++; + CuStringAppendFormat(details, "%d) %s: %s\n", failCount, testCase->name, testCase->message); + } + } + CuStringAppend(details, "\n!!!FAILURES!!!\n"); + + CuStringAppendFormat(details, "Runs: %d ", testSuite->count); + CuStringAppendFormat(details, "Passes: %d ", testSuite->count - testSuite->failCount); + CuStringAppendFormat(details, "Fails: %d\n", testSuite->failCount); + } +} diff --git a/c/utf8filenamecheck/windows/argtable/tests/CuTest.h b/c/utf8filenamecheck/windows/argtable/tests/CuTest.h new file mode 100644 index 0000000..671cbcf --- /dev/null +++ b/c/utf8filenamecheck/windows/argtable/tests/CuTest.h @@ -0,0 +1,104 @@ +#ifndef CU_TEST_H +#define CU_TEST_H + +#include +#include + +#define CUTEST_VERSION "CuTest 1.5" + +/* CuString */ + +char* CuStrAlloc(size_t size); +char* CuStrCopy(const char* old); + +#define CU_ALLOC(TYPE) ((TYPE*)malloc(sizeof(TYPE))) + +#define HUGE_STRING_LEN 8192 +#define STRING_MAX 256 +#define STRING_INC 256 + +typedef struct { + size_t length; + size_t size; + char* buffer; +} CuString; + +void CuStringInit(CuString* str); +CuString* CuStringNew(void); +void CuStringRead(CuString* str, const char* path); +void CuStringAppend(CuString* str, const char* text); +void CuStringAppendChar(CuString* str, char ch); +void CuStringAppendFormat(CuString* str, const char* format, ...); +void CuStringInsert(CuString* str, const char* text, int pos); +void CuStringResize(CuString* str, size_t newSize); +void CuStringDelete(CuString* str); + +/* CuTest */ + +typedef struct CuTest CuTest; + +typedef void (*TestFunction)(CuTest*); + +struct CuTest { + char* name; + TestFunction function; + int failed; + int ran; + const char* message; + jmp_buf* jumpBuf; +}; + +void CuTestInit(CuTest* t, const char* name, TestFunction function); +CuTest* CuTestNew(const char* name, TestFunction function); +void CuTestRun(CuTest* tc); +void CuTestDelete(CuTest* t); + +/* Internal versions of assert functions -- use the public versions */ +void CuFail_Line(CuTest* tc, const char* file, int line, const char* message2, const char* message); +void CuAssert_Line(CuTest* tc, const char* file, int line, const char* message, int condition); +void CuAssertStrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, const char* expected, const char* actual); +void CuAssertIntEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, int expected, int actual); +void CuAssertDblEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, double expected, double actual, double delta); +void CuAssertPtrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message, void* expected, void* actual); + +/* public assert functions */ + +#define CuFail(tc, ms) CuFail_Line((tc), __FILE__, __LINE__, NULL, (ms)) +#define CuAssert(tc, ms, cond) CuAssert_Line((tc), __FILE__, __LINE__, (ms), (cond)) +#define CuAssertTrue(tc, cond) CuAssert_Line((tc), __FILE__, __LINE__, "assert failed", (cond)) + +#define CuAssertStrEquals(tc, ex, ac) CuAssertStrEquals_LineMsg((tc), __FILE__, __LINE__, NULL, (ex), (ac)) +#define CuAssertStrEquals_Msg(tc, ms, ex, ac) CuAssertStrEquals_LineMsg((tc), __FILE__, __LINE__, (ms), (ex), (ac)) +#define CuAssertIntEquals(tc, ex, ac) CuAssertIntEquals_LineMsg((tc), __FILE__, __LINE__, NULL, (ex), (ac)) +#define CuAssertIntEquals_Msg(tc, ms, ex, ac) CuAssertIntEquals_LineMsg((tc), __FILE__, __LINE__, (ms), (ex), (ac)) +#define CuAssertDblEquals(tc, ex, ac, dl) CuAssertDblEquals_LineMsg((tc), __FILE__, __LINE__, NULL, (ex), (ac), (dl)) +#define CuAssertDblEquals_Msg(tc, ms, ex, ac, dl) CuAssertDblEquals_LineMsg((tc), __FILE__, __LINE__, (ms), (ex), (ac), (dl)) +#define CuAssertPtrEquals(tc, ex, ac) CuAssertPtrEquals_LineMsg((tc), __FILE__, __LINE__, NULL, (ex), (ac)) +#define CuAssertPtrEquals_Msg(tc, ms, ex, ac) CuAssertPtrEquals_LineMsg((tc), __FILE__, __LINE__, (ms), (ex), (ac)) + +#define CuAssertPtrNotNull(tc, p) CuAssert_Line((tc), __FILE__, __LINE__, "null pointer unexpected", (p != NULL)) +#define CuAssertPtrNotNullMsg(tc, msg, p) CuAssert_Line((tc), __FILE__, __LINE__, (msg), (p != NULL)) + +/* CuSuite */ + +#define MAX_TEST_CASES 1024 + +#define SUITE_ADD_TEST(SUITE, TEST) CuSuiteAdd(SUITE, CuTestNew(#TEST, TEST)) + +typedef struct { + int count; + CuTest* list[MAX_TEST_CASES]; + int failCount; + +} CuSuite; + +void CuSuiteInit(CuSuite* testSuite); +CuSuite* CuSuiteNew(void); +void CuSuiteDelete(CuSuite* testSuite); +void CuSuiteAdd(CuSuite* testSuite, CuTest* testCase); +void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2); +void CuSuiteRun(CuSuite* testSuite); +void CuSuiteSummary(CuSuite* testSuite, CuString* summary); +void CuSuiteDetails(CuSuite* testSuite, CuString* details); + +#endif /* CU_TEST_H */ diff --git a/c/utf8filenamecheck/windows/argtable/tests/argtable3_private.h b/c/utf8filenamecheck/windows/argtable/tests/argtable3_private.h new file mode 100644 index 0000000..ad61cfa --- /dev/null +++ b/c/utf8filenamecheck/windows/argtable/tests/argtable3_private.h @@ -0,0 +1,230 @@ +/******************************************************************************* + * argtable3_private: Declares private types, constants, and interfaces + * + * This file is part of the argtable3 library. + * + * Copyright (C) 2013-2019 Tom G. Huang + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#ifndef ARG_UTILS_H +#define ARG_UTILS_H + +#include + +#define ARG_ENABLE_TRACE 0 +#define ARG_ENABLE_LOG 1 + +#ifdef __cplusplus +extern "C" { +#endif + +enum { ARG_ERR_MINCOUNT = 1, ARG_ERR_MAXCOUNT, ARG_ERR_BADINT, ARG_ERR_OVERFLOW, ARG_ERR_BADDOUBLE, ARG_ERR_BADDATE, ARG_ERR_REGNOMATCH }; + +typedef void(arg_panicfn)(const char* fmt, ...); + +#if defined(_MSC_VER) +#define ARG_TRACE(x) \ + __pragma(warning(push)) __pragma(warning(disable : 4127)) do { \ + if (ARG_ENABLE_TRACE) \ + dbg_printf x; \ + } \ + while (0) \ + __pragma(warning(pop)) + +#define ARG_LOG(x) \ + __pragma(warning(push)) __pragma(warning(disable : 4127)) do { \ + if (ARG_ENABLE_LOG) \ + dbg_printf x; \ + } \ + while (0) \ + __pragma(warning(pop)) +#else +#define ARG_TRACE(x) \ + do { \ + if (ARG_ENABLE_TRACE) \ + dbg_printf x; \ + } while (0) + +#define ARG_LOG(x) \ + do { \ + if (ARG_ENABLE_LOG) \ + dbg_printf x; \ + } while (0) +#endif + +extern void dbg_printf(const char* fmt, ...); +extern void arg_set_panic(arg_panicfn* proc); +extern void* xmalloc(size_t size); +extern void* xcalloc(size_t count, size_t size); +extern void* xrealloc(void* ptr, size_t size); +extern void xfree(void* ptr); + +struct arg_hashtable_entry { + void *k, *v; + unsigned int h; + struct arg_hashtable_entry* next; +}; + +typedef struct arg_hashtable { + unsigned int tablelength; + struct arg_hashtable_entry** table; + unsigned int entrycount; + unsigned int loadlimit; + unsigned int primeindex; + unsigned int (*hashfn)(const void* k); + int (*eqfn)(const void* k1, const void* k2); +} arg_hashtable_t; + +/** + * @brief Create a hash table. + * + * @param minsize minimum initial size of hash table + * @param hashfn function for hashing keys + * @param eqfn function for determining key equality + * @return newly created hash table or NULL on failure + */ +arg_hashtable_t* arg_hashtable_create(unsigned int minsize, unsigned int (*hashfn)(const void*), int (*eqfn)(const void*, const void*)); + +/** + * @brief This function will cause the table to expand if the insertion would take + * the ratio of entries to table size over the maximum load factor. + * + * This function does not check for repeated insertions with a duplicate key. + * The value returned when using a duplicate key is undefined -- when + * the hash table changes size, the order of retrieval of duplicate key + * entries is reversed. + * If in doubt, remove before insert. + * + * @param h the hash table to insert into + * @param k the key - hash table claims ownership and will free on removal + * @param v the value - does not claim ownership + * @return non-zero for successful insertion + */ +void arg_hashtable_insert(arg_hashtable_t* h, void* k, void* v); + +#define ARG_DEFINE_HASHTABLE_INSERT(fnname, keytype, valuetype) \ + int fnname(arg_hashtable_t* h, keytype* k, valuetype* v) { return arg_hashtable_insert(h, k, v); } + +/** + * @brief Search the specified key in the hash table. + * + * @param h the hash table to search + * @param k the key to search for - does not claim ownership + * @return the value associated with the key, or NULL if none found + */ +void* arg_hashtable_search(arg_hashtable_t* h, const void* k); + +#define ARG_DEFINE_HASHTABLE_SEARCH(fnname, keytype, valuetype) \ + valuetype* fnname(arg_hashtable_t* h, keytype* k) { return (valuetype*)(arg_hashtable_search(h, k)); } + +/** + * @brief Remove the specified key from the hash table. + * + * @param h the hash table to remove the item from + * @param k the key to search for - does not claim ownership + */ +void arg_hashtable_remove(arg_hashtable_t* h, const void* k); + +#define ARG_DEFINE_HASHTABLE_REMOVE(fnname, keytype, valuetype) \ + valuetype* fnname(arg_hashtable_t* h, keytype* k) { return (valuetype*)(arg_hashtable_remove(h, k)); } + +/** + * @brief Return the number of keys in the hash table. + * + * @param h the hash table + * @return the number of items stored in the hash table + */ +unsigned int arg_hashtable_count(arg_hashtable_t* h); + +/** + * @brief Change the value associated with the key. + * + * function to change the value associated with a key, where there already + * exists a value bound to the key in the hash table. + * Source due to Holger Schemel. + * + * @name hashtable_change + * @param h the hash table + * @param key + * @param value + */ +int arg_hashtable_change(arg_hashtable_t* h, void* k, void* v); + +/** + * @brief Free the hash table and the memory allocated for each key-value pair. + * + * @param h the hash table + * @param free_values whether to call 'free' on the remaining values + */ +void arg_hashtable_destroy(arg_hashtable_t* h, int free_values); + +typedef struct arg_hashtable_itr { + arg_hashtable_t* h; + struct arg_hashtable_entry* e; + struct arg_hashtable_entry* parent; + unsigned int index; +} arg_hashtable_itr_t; + +arg_hashtable_itr_t* arg_hashtable_itr_create(arg_hashtable_t* h); + +void arg_hashtable_itr_destroy(arg_hashtable_itr_t* itr); + +/** + * @brief Return the value of the (key,value) pair at the current position. + */ +extern void* arg_hashtable_itr_key(arg_hashtable_itr_t* i); + +/** + * @brief Return the value of the (key,value) pair at the current position. + */ +extern void* arg_hashtable_itr_value(arg_hashtable_itr_t* i); + +/** + * @brief Advance the iterator to the next element. Returns zero if advanced to end of table. + */ +int arg_hashtable_itr_advance(arg_hashtable_itr_t* itr); + +/** + * @brief Remove current element and advance the iterator to the next element. + */ +int arg_hashtable_itr_remove(arg_hashtable_itr_t* itr); + +/** + * @brief Search and overwrite the supplied iterator, to point to the entry matching the supplied key. + * + * @return Zero if not found. + */ +int arg_hashtable_itr_search(arg_hashtable_itr_t* itr, arg_hashtable_t* h, void* k); + +#define ARG_DEFINE_HASHTABLE_ITERATOR_SEARCH(fnname, keytype) \ + int fnname(arg_hashtable_itr_t* i, arg_hashtable_t* h, keytype* k) { return (arg_hashtable_iterator_search(i, h, k)); } + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/c/utf8filenamecheck/windows/argtable/tests/testall.c b/c/utf8filenamecheck/windows/argtable/tests/testall.c new file mode 100644 index 0000000..8f4ed6f --- /dev/null +++ b/c/utf8filenamecheck/windows/argtable/tests/testall.c @@ -0,0 +1,76 @@ +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 2013-2019 Tom G. Huang + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include + +#include "CuTest.h" + +CuSuite* get_arglit_testsuite(); +CuSuite* get_argstr_testsuite(); +CuSuite* get_argint_testsuite(); +CuSuite* get_argdate_testsuite(); +CuSuite* get_argdbl_testsuite(); +CuSuite* get_argfile_testsuite(); +CuSuite* get_argrex_testsuite(); +CuSuite* get_argdstr_testsuite(); +CuSuite* get_argcmd_testsuite(); + +#ifndef ARGTABLE3_TEST_PUBLIC_ONLY +CuSuite* get_arghashtable_testsuite(); +#endif + +int RunAllTests(void) { + CuString* output = CuStringNew(); + CuSuite* suite = CuSuiteNew(); + + CuSuiteAddSuite(suite, get_arglit_testsuite()); + CuSuiteAddSuite(suite, get_argstr_testsuite()); + CuSuiteAddSuite(suite, get_argint_testsuite()); + CuSuiteAddSuite(suite, get_argdate_testsuite()); + CuSuiteAddSuite(suite, get_argdbl_testsuite()); + CuSuiteAddSuite(suite, get_argfile_testsuite()); + CuSuiteAddSuite(suite, get_argrex_testsuite()); + CuSuiteAddSuite(suite, get_argdstr_testsuite()); + CuSuiteAddSuite(suite, get_argcmd_testsuite()); +#ifndef ARGTABLE3_TEST_PUBLIC_ONLY + CuSuiteAddSuite(suite, get_arghashtable_testsuite()); +#endif + + CuSuiteRun(suite); + CuSuiteSummary(suite, output); + CuSuiteDetails(suite, output); + printf("%s\n", output->buffer); + + return suite->failCount; +} + +int main(void) { + return RunAllTests(); +} diff --git a/c/utf8filenamecheck/windows/argtable/tests/testargcmd.c b/c/utf8filenamecheck/windows/argtable/tests/testargcmd.c new file mode 100644 index 0000000..5ec0836 --- /dev/null +++ b/c/utf8filenamecheck/windows/argtable/tests/testargcmd.c @@ -0,0 +1,92 @@ +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 2013-2019 Tom G. Huang + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include +#include + +#include + +#include "CuTest.h" +#include "argtable3.h" + +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4204) +#endif + +int cmd1_proc(int argc, char* argv[], arg_dstr_t res) { + if (argc == 0) { + arg_dstr_catf(res, "cmd1 fail"); + return 1; + } + + arg_dstr_catf(res, "%d %s", argc, argv[0]); + return 0; +} + +void test_argcmd_basic_001(CuTest* tc) { + arg_cmd_init(); + CuAssertIntEquals(tc, 0, arg_cmd_count()); + + arg_cmd_register("cmd1", cmd1_proc, "description of cmd1"); + CuAssertIntEquals(tc, 1, arg_cmd_count()); + + char* argv[] = { + "cmd1", + "-o", + "file1", + }; + int argc = 3; + CuAssertTrue(tc, strcmp(argv[0], "cmd1") == 0); + CuAssertTrue(tc, strcmp(argv[1], "-o") == 0); + CuAssertTrue(tc, strcmp(argv[2], "file1") == 0); + + arg_dstr_t res = arg_dstr_create(); + int err = arg_cmd_dispatch("cmd1", argc, argv, res); + CuAssertIntEquals(tc, 0, err); + CuAssertTrue(tc, strcmp(arg_dstr_cstr(res), "3 cmd1") == 0); + + arg_dstr_reset(res); + err = arg_cmd_dispatch("cmd1", 0, NULL, res); + CuAssertIntEquals(tc, 1, err); + CuAssertTrue(tc, strcmp(arg_dstr_cstr(res), "cmd1 fail") == 0); + + arg_cmd_uninit(); +} + +CuSuite* get_argcmd_testsuite() { + CuSuite* suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_argcmd_basic_001); + return suite; +} + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif diff --git a/c/utf8filenamecheck/windows/argtable/tests/testargdate.c b/c/utf8filenamecheck/windows/argtable/tests/testargdate.c new file mode 100644 index 0000000..3b4f5a0 --- /dev/null +++ b/c/utf8filenamecheck/windows/argtable/tests/testargdate.c @@ -0,0 +1,377 @@ +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 2013-2019 Tom G. Huang + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include +#include + +#include "CuTest.h" +#include "argtable3.h" + +/* + printf("tm_sec = %d\n", c->tmval->tm_sec); + printf("tm_min = %d\n", c->tmval->tm_min); + printf("tm_hour = %d\n", c->tmval->tm_hour); + printf("tm_mday = %d\n", c->tmval->tm_mday); + printf("tm_mon = %d\n", c->tmval->tm_mon); + printf("tm_year = %d\n", c->tmval->tm_year); + printf("tm_wday = %d\n", c->tmval->tm_wday); + printf("tm_yday = %d\n", c->tmval->tm_yday); + printf("tm_isdst = %d\n", c->tmval->tm_isdst); + +*/ + +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4204) +#endif + +void test_argdate_basic_001(CuTest* tc) { + struct arg_date* a = arg_date1(NULL, NULL, "%H:%M", NULL, "time 23:59"); + struct arg_date* b = arg_date0("b", NULL, "%Y-%m-%d", NULL, "date YYYY-MM-DD"); + struct arg_date* c = arg_daten(NULL, "date", "%D", NULL, 1, 2, "MM/DD/YY"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, end}; + int nerrors; + + char* argv[] = {"program", "23:59", "--date", "12/31/04", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertIntEquals(tc, a->tmval->tm_sec, 0); + CuAssertIntEquals(tc, a->tmval->tm_min, 59); + CuAssertIntEquals(tc, a->tmval->tm_hour, 23); + CuAssertIntEquals(tc, a->tmval->tm_mday, 0); + CuAssertIntEquals(tc, a->tmval->tm_mon, 0); + CuAssertIntEquals(tc, a->tmval->tm_year, 0); + CuAssertIntEquals(tc, a->tmval->tm_wday, 0); + CuAssertIntEquals(tc, a->tmval->tm_yday, 0); + CuAssertIntEquals(tc, a->tmval->tm_isdst, 0); + CuAssertTrue(tc, b->count == 0); + CuAssertTrue(tc, c->count == 1); + CuAssertIntEquals(tc, c->tmval->tm_sec, 0); + CuAssertIntEquals(tc, c->tmval->tm_min, 0); + CuAssertIntEquals(tc, c->tmval->tm_hour, 0); + CuAssertIntEquals(tc, c->tmval->tm_mday, 31); + CuAssertIntEquals(tc, c->tmval->tm_mon, 11); + CuAssertIntEquals(tc, c->tmval->tm_year, 104); + CuAssertIntEquals(tc, c->tmval->tm_wday, 0); + CuAssertIntEquals(tc, c->tmval->tm_yday, 0); + CuAssertIntEquals(tc, c->tmval->tm_isdst, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argdate_basic_002(CuTest* tc) { + struct arg_date* a = arg_date1(NULL, NULL, "%H:%M", NULL, "time 23:59"); + struct arg_date* b = arg_date0("b", NULL, "%Y-%m-%d", NULL, "date YYYY-MM-DD"); + struct arg_date* c = arg_daten(NULL, "date", "%D", NULL, 1, 2, "MM/DD/YY"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, end}; + int nerrors; + + char* argv[] = {"program", "--date", "12/31/04", "20:15", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertIntEquals(tc, a->tmval->tm_sec, 0); + CuAssertIntEquals(tc, a->tmval->tm_min, 15); + CuAssertIntEquals(tc, a->tmval->tm_hour, 20); + CuAssertIntEquals(tc, a->tmval->tm_mday, 0); + CuAssertIntEquals(tc, a->tmval->tm_mon, 0); + CuAssertIntEquals(tc, a->tmval->tm_year, 0); + CuAssertIntEquals(tc, a->tmval->tm_wday, 0); + CuAssertIntEquals(tc, a->tmval->tm_yday, 0); + CuAssertIntEquals(tc, a->tmval->tm_isdst, 0); + CuAssertTrue(tc, b->count == 0); + CuAssertTrue(tc, c->count == 1); + CuAssertIntEquals(tc, c->tmval->tm_sec, 0); + CuAssertIntEquals(tc, c->tmval->tm_min, 0); + CuAssertIntEquals(tc, c->tmval->tm_hour, 0); + CuAssertIntEquals(tc, c->tmval->tm_mday, 31); + CuAssertIntEquals(tc, c->tmval->tm_mon, 11); + CuAssertIntEquals(tc, c->tmval->tm_year, 104); + CuAssertIntEquals(tc, c->tmval->tm_wday, 0); + CuAssertIntEquals(tc, c->tmval->tm_yday, 0); + CuAssertIntEquals(tc, c->tmval->tm_isdst, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argdate_basic_003(CuTest* tc) { + struct arg_date* a = arg_date1(NULL, NULL, "%H:%M", NULL, "time 23:59"); + struct arg_date* b = arg_date0("b", NULL, "%Y-%m-%d", NULL, "date YYYY-MM-DD"); + struct arg_date* c = arg_daten(NULL, "date", "%D", NULL, 1, 2, "MM/DD/YY"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, end}; + int nerrors; + + char* argv[] = {"program", "--date", "12/31/04", "20:15", "--date", "06/07/84", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertIntEquals(tc, a->tmval->tm_sec, 0); + CuAssertIntEquals(tc, a->tmval->tm_min, 15); + CuAssertIntEquals(tc, a->tmval->tm_hour, 20); + CuAssertIntEquals(tc, a->tmval->tm_mday, 0); + CuAssertIntEquals(tc, a->tmval->tm_mon, 0); + CuAssertIntEquals(tc, a->tmval->tm_year, 0); + CuAssertIntEquals(tc, a->tmval->tm_wday, 0); + CuAssertIntEquals(tc, a->tmval->tm_yday, 0); + CuAssertIntEquals(tc, a->tmval->tm_isdst, 0); + CuAssertTrue(tc, b->count == 0); + CuAssertTrue(tc, c->count == 2); + CuAssertIntEquals(tc, c->tmval->tm_sec, 0); + CuAssertIntEquals(tc, c->tmval->tm_min, 0); + CuAssertIntEquals(tc, c->tmval->tm_hour, 0); + CuAssertIntEquals(tc, c->tmval->tm_mday, 31); + CuAssertIntEquals(tc, c->tmval->tm_mon, 11); + CuAssertIntEquals(tc, c->tmval->tm_year, 104); + CuAssertIntEquals(tc, c->tmval->tm_wday, 0); + CuAssertIntEquals(tc, c->tmval->tm_yday, 0); + CuAssertIntEquals(tc, c->tmval->tm_isdst, 0); + CuAssertIntEquals(tc, (c->tmval + 1)->tm_sec, 0); + CuAssertIntEquals(tc, (c->tmval + 1)->tm_min, 0); + CuAssertIntEquals(tc, (c->tmval + 1)->tm_hour, 0); + CuAssertIntEquals(tc, (c->tmval + 1)->tm_mday, 7); + CuAssertIntEquals(tc, (c->tmval + 1)->tm_mon, 5); + CuAssertIntEquals(tc, (c->tmval + 1)->tm_year, 84); + CuAssertIntEquals(tc, (c->tmval + 1)->tm_wday, 0); + CuAssertIntEquals(tc, (c->tmval + 1)->tm_yday, 0); + CuAssertIntEquals(tc, (c->tmval + 1)->tm_isdst, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argdate_basic_004(CuTest* tc) { + struct arg_date* a = arg_date1(NULL, NULL, "%H:%M", NULL, "time 23:59"); + struct arg_date* b = arg_date0("b", NULL, "%Y-%m-%d", NULL, "date YYYY-MM-DD"); + struct arg_date* c = arg_daten(NULL, "date", "%D", NULL, 1, 2, "MM/DD/YY"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, end}; + int nerrors; + + char* argv[] = {"program", "--date", "12/31/04", "20:15", "-b", "1982-11-28", "--date", "06/07/84", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertIntEquals(tc, a->tmval->tm_sec, 0); + CuAssertIntEquals(tc, a->tmval->tm_min, 15); + CuAssertIntEquals(tc, a->tmval->tm_hour, 20); + CuAssertIntEquals(tc, a->tmval->tm_mday, 0); + CuAssertIntEquals(tc, a->tmval->tm_mon, 0); + CuAssertIntEquals(tc, a->tmval->tm_year, 0); + CuAssertIntEquals(tc, a->tmval->tm_wday, 0); + CuAssertIntEquals(tc, a->tmval->tm_yday, 0); + CuAssertIntEquals(tc, a->tmval->tm_isdst, 0); + CuAssertTrue(tc, b->count == 1); + CuAssertIntEquals(tc, b->tmval->tm_sec, 0); + CuAssertIntEquals(tc, b->tmval->tm_min, 0); + CuAssertIntEquals(tc, b->tmval->tm_hour, 0); + CuAssertIntEquals(tc, b->tmval->tm_mday, 28); + CuAssertIntEquals(tc, b->tmval->tm_mon, 10); + CuAssertIntEquals(tc, b->tmval->tm_year, 82); + CuAssertIntEquals(tc, b->tmval->tm_wday, 0); + CuAssertIntEquals(tc, b->tmval->tm_yday, 0); + CuAssertIntEquals(tc, b->tmval->tm_isdst, 0); + CuAssertTrue(tc, c->count == 2); + CuAssertIntEquals(tc, c->tmval->tm_sec, 0); + CuAssertIntEquals(tc, c->tmval->tm_min, 0); + CuAssertIntEquals(tc, c->tmval->tm_hour, 0); + CuAssertIntEquals(tc, c->tmval->tm_mday, 31); + CuAssertIntEquals(tc, c->tmval->tm_mon, 11); + CuAssertIntEquals(tc, c->tmval->tm_year, 104); + CuAssertIntEquals(tc, c->tmval->tm_wday, 0); + CuAssertIntEquals(tc, c->tmval->tm_yday, 0); + CuAssertIntEquals(tc, c->tmval->tm_isdst, 0); + CuAssertIntEquals(tc, (c->tmval + 1)->tm_sec, 0); + CuAssertIntEquals(tc, (c->tmval + 1)->tm_min, 0); + CuAssertIntEquals(tc, (c->tmval + 1)->tm_hour, 0); + CuAssertIntEquals(tc, (c->tmval + 1)->tm_mday, 7); + CuAssertIntEquals(tc, (c->tmval + 1)->tm_mon, 5); + CuAssertIntEquals(tc, (c->tmval + 1)->tm_year, 84); + CuAssertIntEquals(tc, (c->tmval + 1)->tm_wday, 0); + CuAssertIntEquals(tc, (c->tmval + 1)->tm_yday, 0); + CuAssertIntEquals(tc, (c->tmval + 1)->tm_isdst, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argdate_basic_005(CuTest* tc) { + struct arg_date* a = arg_date1(NULL, NULL, "%H:%M", NULL, "time 23:59"); + struct arg_date* b = arg_date0("b", NULL, "%Y-%m-%d", NULL, "date YYYY-MM-DD"); + struct arg_date* c = arg_daten(NULL, "date", "%D", NULL, 1, 2, "MM/DD/YY"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, end}; + int nerrors; + + char* argv[] = {"program", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + CuAssertTrue(tc, nerrors == 2); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argdate_basic_006(CuTest* tc) { + struct arg_date* a = arg_date1(NULL, NULL, "%H:%M", NULL, "time 23:59"); + struct arg_date* b = arg_date0("b", NULL, "%Y-%m-%d", NULL, "date YYYY-MM-DD"); + struct arg_date* c = arg_daten(NULL, "date", "%D", NULL, 1, 2, "MM/DD/YY"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, end}; + int nerrors; + + char* argv[] = {"program", "25:59", "--date", "12/31/04", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + CuAssertTrue(tc, nerrors == 1); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argdate_basic_007(CuTest* tc) { + struct arg_date* a = arg_date1(NULL, NULL, "%H:%M", NULL, "time 23:59"); + struct arg_date* b = arg_date0("b", NULL, "%Y-%m-%d", NULL, "date YYYY-MM-DD"); + struct arg_date* c = arg_daten(NULL, "date", "%D", NULL, 1, 2, "MM/DD/YY"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, end}; + int nerrors; + + char* argv[] = {"program", "23:59", "--date", "12/32/04", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + CuAssertTrue(tc, nerrors == 1); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argdate_basic_008(CuTest* tc) { + struct arg_date* a = arg_date1(NULL, NULL, "%H:%M", NULL, "time 23:59"); + struct arg_date* b = arg_date0("b", NULL, "%Y-%m-%d", NULL, "date YYYY-MM-DD"); + struct arg_date* c = arg_daten(NULL, "date", "%D", NULL, 1, 2, "MM/DD/YY"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, end}; + int nerrors; + + char* argv[] = {"program", "23:59", "--date", "12/31/04", "22:58", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + CuAssertTrue(tc, nerrors == 1); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argdate_basic_009(CuTest* tc) { + struct arg_date* a = arg_date1(NULL, NULL, "%H:%M", NULL, "time 23:59"); + struct arg_date* b = arg_date0("b", NULL, "%Y-%m-%d", NULL, "date YYYY-MM-DD"); + struct arg_date* c = arg_daten(NULL, "date", "%D", NULL, 1, 2, "MM/DD/YY"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, end}; + int nerrors; + + char* argv[] = {"program", "--date", "12/31/04", "20:15", "--date", "26/07/84", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + CuAssertTrue(tc, nerrors == 1); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argdate_basic_010(CuTest* tc) { + struct arg_date* a = arg_date1(NULL, NULL, "%H:%M", NULL, "time 23:59"); + struct arg_date* b = arg_date0("b", NULL, "%Y-%m-%d", NULL, "date YYYY-MM-DD"); + struct arg_date* c = arg_daten(NULL, "date", "%D", NULL, 1, 2, "MM/DD/YY"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, end}; + int nerrors; + + char* argv[] = {"program", "-b", "1982-11-28", "-b", "1976-11-11", "--date", "12/07/84", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + CuAssertTrue(tc, nerrors == 1); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +CuSuite* get_argdate_testsuite() { + CuSuite* suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_argdate_basic_001); + SUITE_ADD_TEST(suite, test_argdate_basic_002); + SUITE_ADD_TEST(suite, test_argdate_basic_003); + SUITE_ADD_TEST(suite, test_argdate_basic_004); + SUITE_ADD_TEST(suite, test_argdate_basic_005); + SUITE_ADD_TEST(suite, test_argdate_basic_006); + SUITE_ADD_TEST(suite, test_argdate_basic_007); + SUITE_ADD_TEST(suite, test_argdate_basic_008); + SUITE_ADD_TEST(suite, test_argdate_basic_009); + SUITE_ADD_TEST(suite, test_argdate_basic_010); + return suite; +} + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif diff --git a/c/utf8filenamecheck/windows/argtable/tests/testargdbl.c b/c/utf8filenamecheck/windows/argtable/tests/testargdbl.c new file mode 100644 index 0000000..9271cae --- /dev/null +++ b/c/utf8filenamecheck/windows/argtable/tests/testargdbl.c @@ -0,0 +1,451 @@ +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 2013-2019 Tom G. Huang + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include +#include + +#include "CuTest.h" +#include "argtable3.h" + +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4204) +#endif + +void test_argdbl_basic_001(CuTest* tc) { + struct arg_dbl* a = arg_dbl1(NULL, NULL, "a", "a is "); + struct arg_dbl* b = arg_dbl0(NULL, NULL, "b", "b is "); + struct arg_dbl* c = arg_dbl0(NULL, NULL, "c", "c is "); + struct arg_dbl* d = arg_dbln("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_dbl* e = arg_dbl0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, end}; + int nerrors; + + char* argv[] = {"program", "0", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + CuAssertTrue(tc, nerrors == 0); + + CuAssertTrue(tc, a->count == 1); + CuAssertDblEquals(tc, a->dval[0], 0, DBL_EPSILON); + CuAssertTrue(tc, b->count == 0); + CuAssertTrue(tc, c->count == 0); + CuAssertTrue(tc, d->count == 0); + CuAssertTrue(tc, e->count == 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argdbl_basic_002(CuTest* tc) { + struct arg_dbl* a = arg_dbl1(NULL, NULL, "a", "a is "); + struct arg_dbl* b = arg_dbl0(NULL, NULL, "b", "b is "); + struct arg_dbl* c = arg_dbl0(NULL, NULL, "c", "c is "); + struct arg_dbl* d = arg_dbln("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_dbl* e = arg_dbl0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, end}; + int nerrors; + + char* argv[] = {"program", "1.234", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + CuAssertTrue(tc, nerrors == 0); + + CuAssertTrue(tc, a->count == 1); + CuAssertDblEquals(tc, a->dval[0], 1.234, DBL_EPSILON); + CuAssertTrue(tc, b->count == 0); + CuAssertTrue(tc, c->count == 0); + CuAssertTrue(tc, d->count == 0); + CuAssertTrue(tc, e->count == 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argdbl_basic_003(CuTest* tc) { + struct arg_dbl* a = arg_dbl1(NULL, NULL, "a", "a is "); + struct arg_dbl* b = arg_dbl0(NULL, NULL, "b", "b is "); + struct arg_dbl* c = arg_dbl0(NULL, NULL, "c", "c is "); + struct arg_dbl* d = arg_dbln("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_dbl* e = arg_dbl0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, end}; + int nerrors; + + char* argv[] = {"program", "1.8", "2.3", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + CuAssertTrue(tc, nerrors == 0); + + CuAssertTrue(tc, a->count == 1); + CuAssertDblEquals(tc, a->dval[0], 1.8, DBL_EPSILON); + CuAssertTrue(tc, b->count == 1); + CuAssertDblEquals(tc, b->dval[0], 2.3, DBL_EPSILON); + CuAssertTrue(tc, c->count == 0); + CuAssertTrue(tc, d->count == 0); + CuAssertTrue(tc, e->count == 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argdbl_basic_004(CuTest* tc) { + struct arg_dbl* a = arg_dbl1(NULL, NULL, "a", "a is "); + struct arg_dbl* b = arg_dbl0(NULL, NULL, "b", "b is "); + struct arg_dbl* c = arg_dbl0(NULL, NULL, "c", "c is "); + struct arg_dbl* d = arg_dbln("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_dbl* e = arg_dbl0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, end}; + int nerrors; + + char* argv[] = {"program", "5", "7", "9", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + CuAssertTrue(tc, nerrors == 0); + + CuAssertTrue(tc, a->count == 1); + CuAssertDblEquals(tc, a->dval[0], 5, DBL_EPSILON); + CuAssertTrue(tc, b->count == 1); + CuAssertDblEquals(tc, b->dval[0], 7, DBL_EPSILON); + CuAssertTrue(tc, c->count == 1); + CuAssertDblEquals(tc, c->dval[0], 9, DBL_EPSILON); + CuAssertTrue(tc, d->count == 0); + CuAssertTrue(tc, e->count == 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argdbl_basic_005(CuTest* tc) { + struct arg_dbl* a = arg_dbl1(NULL, NULL, "a", "a is "); + struct arg_dbl* b = arg_dbl0(NULL, NULL, "b", "b is "); + struct arg_dbl* c = arg_dbl0(NULL, NULL, "c", "c is "); + struct arg_dbl* d = arg_dbln("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_dbl* e = arg_dbl0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, end}; + int nerrors; + + char* argv[] = {"program", "1.9998", "-d", "13e-1", "-D", "17e-1", "--delta", "36e-1", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + CuAssertTrue(tc, nerrors == 0); + + CuAssertTrue(tc, a->count == 1); + CuAssertDblEquals(tc, a->dval[0], 1.9998, DBL_EPSILON); + CuAssertTrue(tc, b->count == 0); + CuAssertTrue(tc, c->count == 0); + CuAssertTrue(tc, d->count == 3); + CuAssertDblEquals(tc, d->dval[0], 13e-1, DBL_EPSILON); + CuAssertDblEquals(tc, d->dval[1], 17e-1, DBL_EPSILON); + CuAssertDblEquals(tc, d->dval[2], 36e-1, DBL_EPSILON); + CuAssertTrue(tc, e->count == 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argdbl_basic_006(CuTest* tc) { + struct arg_dbl* a = arg_dbl1(NULL, NULL, "a", "a is "); + struct arg_dbl* b = arg_dbl0(NULL, NULL, "b", "b is "); + struct arg_dbl* c = arg_dbl0(NULL, NULL, "c", "c is "); + struct arg_dbl* d = arg_dbln("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_dbl* e = arg_dbl0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, end}; + int nerrors; + + char* argv[] = {"program", "1.2", "2.3", "4.5", "--eps", "8.3456789", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + CuAssertTrue(tc, nerrors == 0); + + CuAssertTrue(tc, a->count == 1); + CuAssertDblEquals(tc, a->dval[0], 1.2, DBL_EPSILON); + CuAssertTrue(tc, b->count == 1); + CuAssertDblEquals(tc, b->dval[0], 2.3, DBL_EPSILON); + CuAssertTrue(tc, c->count == 1); + CuAssertDblEquals(tc, c->dval[0], 4.5, DBL_EPSILON); + CuAssertTrue(tc, d->count == 0); + CuAssertTrue(tc, e->count == 1); + CuAssertDblEquals(tc, e->dval[0], 8.3456789, DBL_EPSILON); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argdbl_basic_007(CuTest* tc) { + struct arg_dbl* a = arg_dbl1(NULL, NULL, "a", "a is "); + struct arg_dbl* b = arg_dbl0(NULL, NULL, "b", "b is "); + struct arg_dbl* c = arg_dbl0(NULL, NULL, "c", "c is "); + struct arg_dbl* d = arg_dbln("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_dbl* e = arg_dbl0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, end}; + int nerrors; + + char* argv[] = {"program", "1.2", "2.3", "4.5", "--eqn", "8.3456789", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + CuAssertTrue(tc, nerrors == 0); + + CuAssertTrue(tc, a->count == 1); + CuAssertDblEquals(tc, a->dval[0], 1.2, DBL_EPSILON); + CuAssertTrue(tc, b->count == 1); + CuAssertDblEquals(tc, b->dval[0], 2.3, DBL_EPSILON); + CuAssertTrue(tc, c->count == 1); + CuAssertDblEquals(tc, c->dval[0], 4.5, DBL_EPSILON); + CuAssertTrue(tc, d->count == 0); + CuAssertTrue(tc, e->count == 1); + CuAssertDblEquals(tc, e->dval[0], 8.3456789, DBL_EPSILON); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argdbl_basic_008(CuTest* tc) { + struct arg_dbl* a = arg_dbl1(NULL, NULL, "a", "a is "); + struct arg_dbl* b = arg_dbl0(NULL, NULL, "b", "b is "); + struct arg_dbl* c = arg_dbl0(NULL, NULL, "c", "c is "); + struct arg_dbl* d = arg_dbln("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_dbl* e = arg_dbl0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, end}; + int nerrors; + + char* argv[] = {"program", "1.2", "2.3", "4.5", "--eqn", "8.345", "-D", "0.234", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + CuAssertTrue(tc, nerrors == 0); + + CuAssertTrue(tc, a->count == 1); + CuAssertDblEquals(tc, a->dval[0], 1.2, DBL_EPSILON); + CuAssertTrue(tc, b->count == 1); + CuAssertDblEquals(tc, b->dval[0], 2.3, DBL_EPSILON); + CuAssertTrue(tc, c->count == 1); + CuAssertDblEquals(tc, c->dval[0], 4.5, DBL_EPSILON); + CuAssertTrue(tc, d->count == 1); + CuAssertDblEquals(tc, d->dval[0], 0.234, DBL_EPSILON); + CuAssertTrue(tc, e->count == 1); + CuAssertDblEquals(tc, e->dval[0], 8.345, DBL_EPSILON); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argdbl_basic_009(CuTest* tc) { + struct arg_dbl* a = arg_dbl1(NULL, NULL, "a", "a is "); + struct arg_dbl* b = arg_dbl0(NULL, NULL, "b", "b is "); + struct arg_dbl* c = arg_dbl0(NULL, NULL, "c", "c is "); + struct arg_dbl* d = arg_dbln("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_dbl* e = arg_dbl0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, end}; + int nerrors; + + char* argv[] = {"program", "1", "2", "3", "4", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + CuAssertTrue(tc, nerrors == 1); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argdbl_basic_010(CuTest* tc) { + struct arg_dbl* a = arg_dbl1(NULL, NULL, "a", "a is "); + struct arg_dbl* b = arg_dbl0(NULL, NULL, "b", "b is "); + struct arg_dbl* c = arg_dbl0(NULL, NULL, "c", "c is "); + struct arg_dbl* d = arg_dbln("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_dbl* e = arg_dbl0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, end}; + int nerrors; + + char* argv[] = {"program", "1", "2", "3", "4", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + CuAssertTrue(tc, nerrors == 1); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argdbl_basic_011(CuTest* tc) { + struct arg_dbl* a = arg_dbl1(NULL, NULL, "a", "a is "); + struct arg_dbl* b = arg_dbl0(NULL, NULL, "b", "b is "); + struct arg_dbl* c = arg_dbl0(NULL, NULL, "c", "c is "); + struct arg_dbl* d = arg_dbln("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_dbl* e = arg_dbl0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, end}; + int nerrors; + + char* argv[] = {"program", "1", "2", "3", "-d1", "-d2", "-d3", "-d4", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + CuAssertTrue(tc, nerrors == 1); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argdbl_basic_012(CuTest* tc) { + struct arg_dbl* a = arg_dbl1(NULL, NULL, "a", "a is "); + struct arg_dbl* b = arg_dbl0(NULL, NULL, "b", "b is "); + struct arg_dbl* c = arg_dbl0(NULL, NULL, "c", "c is "); + struct arg_dbl* d = arg_dbln("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_dbl* e = arg_dbl0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, end}; + int nerrors; + + char* argv[] = {"program", "1", "2", "3", "--eps", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + CuAssertTrue(tc, nerrors == 1); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argdbl_basic_013(CuTest* tc) { + struct arg_dbl* a = arg_dbl1(NULL, NULL, "a", "a is "); + struct arg_dbl* b = arg_dbl0(NULL, NULL, "b", "b is "); + struct arg_dbl* c = arg_dbl0(NULL, NULL, "c", "c is "); + struct arg_dbl* d = arg_dbln("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_dbl* e = arg_dbl0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, end}; + int nerrors; + + char* argv[] = {"program", "1", "2", "3", "--eps", "3", "--eqn", "6", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + CuAssertTrue(tc, nerrors == 1); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argdbl_basic_014(CuTest* tc) { + struct arg_dbl* a = arg_dbl1(NULL, NULL, "a", "a is "); + struct arg_dbl* b = arg_dbl0(NULL, NULL, "b", "b is "); + struct arg_dbl* c = arg_dbl0(NULL, NULL, "c", "c is "); + struct arg_dbl* d = arg_dbln("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_dbl* e = arg_dbl0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, end}; + int nerrors; + + char* argv[] = {"program", "hello", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + CuAssertTrue(tc, nerrors == 1); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argdbl_basic_015(CuTest* tc) { + struct arg_dbl* a = arg_dbl1(NULL, NULL, "a", "a is "); + struct arg_dbl* b = arg_dbl0(NULL, NULL, "b", "b is "); + struct arg_dbl* c = arg_dbl0(NULL, NULL, "c", "c is "); + struct arg_dbl* d = arg_dbln("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_dbl* e = arg_dbl0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, end}; + int nerrors; + + char* argv[] = {"program", "4", "hello", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + CuAssertTrue(tc, nerrors == 1); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +CuSuite* get_argdbl_testsuite() { + CuSuite* suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_argdbl_basic_001); + SUITE_ADD_TEST(suite, test_argdbl_basic_002); + SUITE_ADD_TEST(suite, test_argdbl_basic_003); + SUITE_ADD_TEST(suite, test_argdbl_basic_004); + SUITE_ADD_TEST(suite, test_argdbl_basic_005); + SUITE_ADD_TEST(suite, test_argdbl_basic_006); + SUITE_ADD_TEST(suite, test_argdbl_basic_007); + SUITE_ADD_TEST(suite, test_argdbl_basic_008); + SUITE_ADD_TEST(suite, test_argdbl_basic_009); + SUITE_ADD_TEST(suite, test_argdbl_basic_010); + SUITE_ADD_TEST(suite, test_argdbl_basic_011); + SUITE_ADD_TEST(suite, test_argdbl_basic_012); + SUITE_ADD_TEST(suite, test_argdbl_basic_013); + SUITE_ADD_TEST(suite, test_argdbl_basic_014); + SUITE_ADD_TEST(suite, test_argdbl_basic_015); + return suite; +} + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif diff --git a/c/utf8filenamecheck/windows/argtable/tests/testargdstr.c b/c/utf8filenamecheck/windows/argtable/tests/testargdstr.c new file mode 100644 index 0000000..4c8aff0 --- /dev/null +++ b/c/utf8filenamecheck/windows/argtable/tests/testargdstr.c @@ -0,0 +1,123 @@ +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 2013-2019 Tom G. Huang + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include +#include + +#include + +#include "CuTest.h" +#include "argtable3.h" + +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4204) +#endif + +void test_argdstr_basic_001(CuTest* tc) { + arg_dstr_t ds = arg_dstr_create(); + + arg_dstr_set(ds, "hello ", ARG_DSTR_VOLATILE); + CuAssertTrue(tc, strcmp(arg_dstr_cstr(ds), "hello ") == 0); + + arg_dstr_cat(ds, "world"); + CuAssertTrue(tc, strcmp(arg_dstr_cstr(ds), "hello world") == 0); + + arg_dstr_destroy(ds); +} + +void test_argdstr_basic_002(CuTest* tc) { + arg_dstr_t ds = arg_dstr_create(); + + arg_dstr_set(ds, "hello world", ARG_DSTR_VOLATILE); + CuAssertTrue(tc, strcmp(arg_dstr_cstr(ds), "hello world") == 0); + + arg_dstr_reset(ds); + CuAssertTrue(tc, strcmp(arg_dstr_cstr(ds), "") == 0); + + arg_dstr_set(ds, "good", ARG_DSTR_VOLATILE); + CuAssertTrue(tc, strcmp(arg_dstr_cstr(ds), "good") == 0); + + arg_dstr_destroy(ds); +} + +void test_argdstr_basic_003(CuTest* tc) { + arg_dstr_t ds = arg_dstr_create(); + arg_dstr_cat(ds, "hello world"); + CuAssertTrue(tc, strcmp(arg_dstr_cstr(ds), "hello world") == 0); + + arg_dstr_destroy(ds); +} + +void test_argdstr_basic_004(CuTest* tc) { + arg_dstr_t ds = arg_dstr_create(); + arg_dstr_catf(ds, "%s %d", "hello world", 1); + CuAssertTrue(tc, strcmp(arg_dstr_cstr(ds), "hello world 1") == 0); + + arg_dstr_destroy(ds); +} + +void test_argdstr_basic_005(CuTest* tc) { + arg_dstr_t ds = arg_dstr_create(); + arg_dstr_catf(ds, "%d.", 1); + arg_dstr_catf(ds, "%d.", 2); + arg_dstr_catf(ds, "%d.", 3); + arg_dstr_cat(ds, "456"); + CuAssertTrue(tc, strcmp(arg_dstr_cstr(ds), "1.2.3.456") == 0); + + arg_dstr_destroy(ds); +} + +void test_argdstr_basic_006(CuTest* tc) { + int i; + + arg_dstr_t ds = arg_dstr_create(); + for (i = 0; i < 100000; i++) { + arg_dstr_catf(ds, "%s", "1234567890"); + } + CuAssertTrue(tc, strlen(arg_dstr_cstr(ds)) == 1000000); + + arg_dstr_destroy(ds); +} + +CuSuite* get_argdstr_testsuite() { + CuSuite* suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_argdstr_basic_001); + SUITE_ADD_TEST(suite, test_argdstr_basic_002); + SUITE_ADD_TEST(suite, test_argdstr_basic_003); + SUITE_ADD_TEST(suite, test_argdstr_basic_004); + SUITE_ADD_TEST(suite, test_argdstr_basic_005); + SUITE_ADD_TEST(suite, test_argdstr_basic_006); + return suite; +} + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif diff --git a/c/utf8filenamecheck/windows/argtable/tests/testargfile.c b/c/utf8filenamecheck/windows/argtable/tests/testargfile.c new file mode 100644 index 0000000..4ae5e9d --- /dev/null +++ b/c/utf8filenamecheck/windows/argtable/tests/testargfile.c @@ -0,0 +1,752 @@ +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 2013-2019 Tom G. Huang + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include + +#include "CuTest.h" +#include "argtable3.h" + +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4204) +#endif + +void test_argfile_basic_001(CuTest* tc) { + struct arg_file* a = arg_file1(NULL, NULL, "", "filename to test"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, end}; + int nerrors; + + char* argv[] = {"program", "foo.bar", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->filename[0], "foo.bar"); + CuAssertStrEquals(tc, a->basename[0], "foo.bar"); + CuAssertStrEquals(tc, a->extension[0], ".bar"); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argfile_basic_002(CuTest* tc) { + struct arg_file* a = arg_file1(NULL, NULL, "", "filename to test"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, end}; + int nerrors; + + char* argv[] = {"program", "/foo.bar", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->filename[0], "/foo.bar"); + CuAssertStrEquals(tc, a->basename[0], "foo.bar"); + CuAssertStrEquals(tc, a->extension[0], ".bar"); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argfile_basic_003(CuTest* tc) { + struct arg_file* a = arg_file1(NULL, NULL, "", "filename to test"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, end}; + int nerrors; + + char* argv[] = {"program", "./foo.bar", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->filename[0], "./foo.bar"); + CuAssertStrEquals(tc, a->basename[0], "foo.bar"); + CuAssertStrEquals(tc, a->extension[0], ".bar"); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argfile_basic_004(CuTest* tc) { + struct arg_file* a = arg_file1(NULL, NULL, "", "filename to test"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, end}; + int nerrors; + + char* argv[] = {"program", "././foo.bar", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->filename[0], "././foo.bar"); + CuAssertStrEquals(tc, a->basename[0], "foo.bar"); + CuAssertStrEquals(tc, a->extension[0], ".bar"); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argfile_basic_005(CuTest* tc) { + struct arg_file* a = arg_file1(NULL, NULL, "", "filename to test"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, end}; + int nerrors; + + char* argv[] = {"program", "./././foo.bar", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->filename[0], "./././foo.bar"); + CuAssertStrEquals(tc, a->basename[0], "foo.bar"); + CuAssertStrEquals(tc, a->extension[0], ".bar"); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argfile_basic_006(CuTest* tc) { + struct arg_file* a = arg_file1(NULL, NULL, "", "filename to test"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, end}; + int nerrors; + + char* argv[] = {"program", "../foo.bar", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->filename[0], "../foo.bar"); + CuAssertStrEquals(tc, a->basename[0], "foo.bar"); + CuAssertStrEquals(tc, a->extension[0], ".bar"); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argfile_basic_007(CuTest* tc) { + struct arg_file* a = arg_file1(NULL, NULL, "", "filename to test"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, end}; + int nerrors; + + char* argv[] = {"program", "../../foo.bar", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->filename[0], "../../foo.bar"); + CuAssertStrEquals(tc, a->basename[0], "foo.bar"); + CuAssertStrEquals(tc, a->extension[0], ".bar"); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argfile_basic_008(CuTest* tc) { + struct arg_file* a = arg_file1(NULL, NULL, "", "filename to test"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, end}; + int nerrors; + + char* argv[] = {"program", "foo", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->filename[0], "foo"); + CuAssertStrEquals(tc, a->basename[0], "foo"); + CuAssertStrEquals(tc, a->extension[0], ""); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argfile_basic_009(CuTest* tc) { + struct arg_file* a = arg_file1(NULL, NULL, "", "filename to test"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, end}; + int nerrors; + + char* argv[] = {"program", "/foo", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->filename[0], "/foo"); + CuAssertStrEquals(tc, a->basename[0], "foo"); + CuAssertStrEquals(tc, a->extension[0], ""); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argfile_basic_010(CuTest* tc) { + struct arg_file* a = arg_file1(NULL, NULL, "", "filename to test"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, end}; + int nerrors; + + char* argv[] = {"program", "./foo", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->filename[0], "./foo"); + CuAssertStrEquals(tc, a->basename[0], "foo"); + CuAssertStrEquals(tc, a->extension[0], ""); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argfile_basic_011(CuTest* tc) { + struct arg_file* a = arg_file1(NULL, NULL, "", "filename to test"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, end}; + int nerrors; + + char* argv[] = {"program", "././foo", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->filename[0], "././foo"); + CuAssertStrEquals(tc, a->basename[0], "foo"); + CuAssertStrEquals(tc, a->extension[0], ""); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argfile_basic_012(CuTest* tc) { + struct arg_file* a = arg_file1(NULL, NULL, "", "filename to test"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, end}; + int nerrors; + + char* argv[] = {"program", "./././foo", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->filename[0], "./././foo"); + CuAssertStrEquals(tc, a->basename[0], "foo"); + CuAssertStrEquals(tc, a->extension[0], ""); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argfile_basic_013(CuTest* tc) { + struct arg_file* a = arg_file1(NULL, NULL, "", "filename to test"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, end}; + int nerrors; + + char* argv[] = {"program", "../foo", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->filename[0], "../foo"); + CuAssertStrEquals(tc, a->basename[0], "foo"); + CuAssertStrEquals(tc, a->extension[0], ""); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argfile_basic_014(CuTest* tc) { + struct arg_file* a = arg_file1(NULL, NULL, "", "filename to test"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, end}; + int nerrors; + + char* argv[] = {"program", "../../foo", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->filename[0], "../../foo"); + CuAssertStrEquals(tc, a->basename[0], "foo"); + CuAssertStrEquals(tc, a->extension[0], ""); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argfile_basic_015(CuTest* tc) { + struct arg_file* a = arg_file1(NULL, NULL, "", "filename to test"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, end}; + int nerrors; + + char* argv[] = {"program", ".foo", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->filename[0], ".foo"); + CuAssertStrEquals(tc, a->basename[0], ".foo"); + CuAssertStrEquals(tc, a->extension[0], ""); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argfile_basic_016(CuTest* tc) { + struct arg_file* a = arg_file1(NULL, NULL, "", "filename to test"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, end}; + int nerrors; + + char* argv[] = {"program", "/.foo", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->filename[0], "/.foo"); + CuAssertStrEquals(tc, a->basename[0], ".foo"); + CuAssertStrEquals(tc, a->extension[0], ""); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argfile_basic_017(CuTest* tc) { + struct arg_file* a = arg_file1(NULL, NULL, "", "filename to test"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, end}; + int nerrors; + + char* argv[] = {"program", "./.foo", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->filename[0], "./.foo"); + CuAssertStrEquals(tc, a->basename[0], ".foo"); + CuAssertStrEquals(tc, a->extension[0], ""); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argfile_basic_018(CuTest* tc) { + struct arg_file* a = arg_file1(NULL, NULL, "", "filename to test"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, end}; + int nerrors; + + char* argv[] = {"program", "../.foo", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->filename[0], "../.foo"); + CuAssertStrEquals(tc, a->basename[0], ".foo"); + CuAssertStrEquals(tc, a->extension[0], ""); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argfile_basic_019(CuTest* tc) { + struct arg_file* a = arg_file1(NULL, NULL, "", "filename to test"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, end}; + int nerrors; + + char* argv[] = {"program", "foo.", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->filename[0], "foo."); + CuAssertStrEquals(tc, a->basename[0], "foo."); + CuAssertStrEquals(tc, a->extension[0], ""); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argfile_basic_020(CuTest* tc) { + struct arg_file* a = arg_file1(NULL, NULL, "", "filename to test"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, end}; + int nerrors; + + char* argv[] = {"program", "/foo.", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->filename[0], "/foo."); + CuAssertStrEquals(tc, a->basename[0], "foo."); + CuAssertStrEquals(tc, a->extension[0], ""); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argfile_basic_021(CuTest* tc) { + struct arg_file* a = arg_file1(NULL, NULL, "", "filename to test"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, end}; + int nerrors; + + char* argv[] = {"program", "./foo.", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->filename[0], "./foo."); + CuAssertStrEquals(tc, a->basename[0], "foo."); + CuAssertStrEquals(tc, a->extension[0], ""); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argfile_basic_022(CuTest* tc) { + struct arg_file* a = arg_file1(NULL, NULL, "", "filename to test"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, end}; + int nerrors; + + char* argv[] = {"program", "../foo.", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->filename[0], "../foo."); + CuAssertStrEquals(tc, a->basename[0], "foo."); + CuAssertStrEquals(tc, a->extension[0], ""); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argfile_basic_023(CuTest* tc) { + struct arg_file* a = arg_file1(NULL, NULL, "", "filename to test"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, end}; + int nerrors; + + char* argv[] = {"program", "/.foo.", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->filename[0], "/.foo."); + CuAssertStrEquals(tc, a->basename[0], ".foo."); + CuAssertStrEquals(tc, a->extension[0], ""); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argfile_basic_024(CuTest* tc) { + struct arg_file* a = arg_file1(NULL, NULL, "", "filename to test"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, end}; + int nerrors; + + char* argv[] = {"program", "/.foo.c", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->filename[0], "/.foo.c"); + CuAssertStrEquals(tc, a->basename[0], ".foo.c"); + CuAssertStrEquals(tc, a->extension[0], ".c"); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argfile_basic_025(CuTest* tc) { + struct arg_file* a = arg_file1(NULL, NULL, "", "filename to test"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, end}; + int nerrors; + + char* argv[] = {"program", "/.foo..b.c", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->filename[0], "/.foo..b.c"); + CuAssertStrEquals(tc, a->basename[0], ".foo..b.c"); + CuAssertStrEquals(tc, a->extension[0], ".c"); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argfile_basic_026(CuTest* tc) { + struct arg_file* a = arg_file1(NULL, NULL, "", "filename to test"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, end}; + int nerrors; + + char* argv[] = {"program", "/", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->filename[0], "/"); + CuAssertStrEquals(tc, a->basename[0], ""); + CuAssertStrEquals(tc, a->extension[0], ""); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argfile_basic_027(CuTest* tc) { + struct arg_file* a = arg_file1(NULL, NULL, "", "filename to test"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, end}; + int nerrors; + + char* argv[] = {"program", ".", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->filename[0], "."); + CuAssertStrEquals(tc, a->basename[0], ""); + CuAssertStrEquals(tc, a->extension[0], ""); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argfile_basic_028(CuTest* tc) { + struct arg_file* a = arg_file1(NULL, NULL, "", "filename to test"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, end}; + int nerrors; + + char* argv[] = {"program", "..", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->filename[0], ".."); + CuAssertStrEquals(tc, a->basename[0], ""); + CuAssertStrEquals(tc, a->extension[0], ""); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argfile_basic_029(CuTest* tc) { + struct arg_file* a = arg_file1(NULL, NULL, "", "filename to test"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, end}; + int nerrors; + + char* argv[] = {"program", "/.", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->filename[0], "/."); + CuAssertStrEquals(tc, a->basename[0], ""); + CuAssertStrEquals(tc, a->extension[0], ""); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argfile_basic_030(CuTest* tc) { + struct arg_file* a = arg_file1(NULL, NULL, "", "filename to test"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, end}; + int nerrors; + + char* argv[] = {"program", "/..", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->filename[0], "/.."); + CuAssertStrEquals(tc, a->basename[0], ""); + CuAssertStrEquals(tc, a->extension[0], ""); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argfile_basic_031(CuTest* tc) { + struct arg_file* a = arg_file1(NULL, NULL, "", "filename to test"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, end}; + int nerrors; + + char* argv[] = {"program", "./", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->filename[0], "./"); + CuAssertStrEquals(tc, a->basename[0], ""); + CuAssertStrEquals(tc, a->extension[0], ""); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argfile_basic_032(CuTest* tc) { + struct arg_file* a = arg_file1(NULL, NULL, "", "filename to test"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, end}; + int nerrors; + + char* argv[] = {"program", "../", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->filename[0], "../"); + CuAssertStrEquals(tc, a->basename[0], ""); + CuAssertStrEquals(tc, a->extension[0], ""); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +CuSuite* get_argfile_testsuite() { + CuSuite* suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_argfile_basic_001); + SUITE_ADD_TEST(suite, test_argfile_basic_002); + SUITE_ADD_TEST(suite, test_argfile_basic_003); + SUITE_ADD_TEST(suite, test_argfile_basic_004); + SUITE_ADD_TEST(suite, test_argfile_basic_005); + SUITE_ADD_TEST(suite, test_argfile_basic_006); + SUITE_ADD_TEST(suite, test_argfile_basic_007); + SUITE_ADD_TEST(suite, test_argfile_basic_008); + SUITE_ADD_TEST(suite, test_argfile_basic_009); + SUITE_ADD_TEST(suite, test_argfile_basic_010); + SUITE_ADD_TEST(suite, test_argfile_basic_011); + SUITE_ADD_TEST(suite, test_argfile_basic_012); + SUITE_ADD_TEST(suite, test_argfile_basic_013); + SUITE_ADD_TEST(suite, test_argfile_basic_014); + SUITE_ADD_TEST(suite, test_argfile_basic_015); + SUITE_ADD_TEST(suite, test_argfile_basic_016); + SUITE_ADD_TEST(suite, test_argfile_basic_017); + SUITE_ADD_TEST(suite, test_argfile_basic_018); + SUITE_ADD_TEST(suite, test_argfile_basic_019); + SUITE_ADD_TEST(suite, test_argfile_basic_020); + SUITE_ADD_TEST(suite, test_argfile_basic_021); + SUITE_ADD_TEST(suite, test_argfile_basic_022); + SUITE_ADD_TEST(suite, test_argfile_basic_023); + SUITE_ADD_TEST(suite, test_argfile_basic_024); + SUITE_ADD_TEST(suite, test_argfile_basic_025); + SUITE_ADD_TEST(suite, test_argfile_basic_026); + SUITE_ADD_TEST(suite, test_argfile_basic_027); + SUITE_ADD_TEST(suite, test_argfile_basic_028); + SUITE_ADD_TEST(suite, test_argfile_basic_029); + SUITE_ADD_TEST(suite, test_argfile_basic_030); + SUITE_ADD_TEST(suite, test_argfile_basic_031); + SUITE_ADD_TEST(suite, test_argfile_basic_032); + return suite; +} + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif diff --git a/c/utf8filenamecheck/windows/argtable/tests/testarghashtable.c b/c/utf8filenamecheck/windows/argtable/tests/testarghashtable.c new file mode 100644 index 0000000..36e4a7d --- /dev/null +++ b/c/utf8filenamecheck/windows/argtable/tests/testarghashtable.c @@ -0,0 +1,276 @@ +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 2013-2019 Tom G. Huang + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include +#include + +#include + +#include "CuTest.h" +#include "argtable3_private.h" + +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4204) +#pragma warning(disable : 4996) +#endif + +static unsigned int hash_key(const void* key) { + char* str = (char*)key; + int c; + unsigned int hash = 5381; + + while ((c = *str++) != 0) + hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ + + return hash; +} + +static int equal_keys(const void* key1, const void* key2) { + char* k1 = (char*)key1; + char* k2 = (char*)key2; + return (0 == strcmp(k1, k2)); +} + +void test_arghashtable_basic_001(CuTest* tc) { + arg_hashtable_t* h = arg_hashtable_create(32, hash_key, equal_keys); + CuAssertTrue(tc, h != 0); + CuAssertIntEquals(tc, arg_hashtable_count(h), 0); + + arg_hashtable_destroy(h, 1); +} + +void test_arghashtable_basic_002(CuTest* tc) { + arg_hashtable_t* h = arg_hashtable_create(32, hash_key, equal_keys); + CuAssertTrue(tc, h != 0); + CuAssertIntEquals(tc, arg_hashtable_count(h), 0); + + char* key_1 = "k1"; + char* k_1 = (char*)malloc(strlen(key_1) + 1); + memset(k_1, 0, strlen(key_1) + 1); + strncpy(k_1, key_1, strlen(key_1)); + + char* value_1 = "v1"; + char* v_1 = (char*)malloc(strlen(value_1) + 1); + memset(v_1, 0, strlen(value_1) + 1); + strncpy(v_1, value_1, strlen(value_1)); + + arg_hashtable_insert(h, k_1, v_1); + CuAssertIntEquals(tc, 1, arg_hashtable_count(h)); + + arg_hashtable_itr_t* itr = arg_hashtable_itr_create(h); + CuAssertTrue(tc, itr != 0); + CuAssertPtrEquals(tc, k_1, arg_hashtable_itr_key(itr)); + CuAssertTrue(tc, strcmp((char*)arg_hashtable_itr_key(itr), key_1) == 0); + CuAssertPtrEquals(tc, v_1, arg_hashtable_itr_value(itr)); + CuAssertTrue(tc, strcmp((char*)arg_hashtable_itr_value(itr), value_1) == 0); + + arg_hashtable_itr_destroy(itr); + arg_hashtable_destroy(h, 1); +} + +void test_arghashtable_basic_003(CuTest* tc) { + arg_hashtable_t* h = arg_hashtable_create(32, hash_key, equal_keys); + CuAssertTrue(tc, h != 0); + CuAssertIntEquals(tc, arg_hashtable_count(h), 0); + + char* key_1 = "k1"; + char* k_1 = (char*)malloc(strlen(key_1) + 1); + memset(k_1, 0, strlen(key_1) + 1); + strncpy(k_1, key_1, strlen(key_1)); + + char* value_1 = "v1"; + char* v_1 = (char*)malloc(strlen(value_1) + 1); + memset(v_1, 0, strlen(value_1) + 1); + strncpy(v_1, value_1, strlen(value_1)); + + arg_hashtable_insert(h, k_1, v_1); + CuAssertIntEquals(tc, 1, arg_hashtable_count(h)); + + char* key_2 = "k2"; + char* k_2 = (char*)malloc(strlen(key_2) + 1); + memset(k_2, 0, strlen(key_2) + 1); + strncpy(k_2, key_2, strlen(key_2)); + + char* value_2 = "v2"; + char* v_2 = (char*)malloc(strlen(value_2) + 1); + memset(v_2, 0, strlen(value_2) + 1); + strncpy(v_2, value_2, strlen(value_2)); + + arg_hashtable_insert(h, k_2, v_2); + CuAssertIntEquals(tc, 2, arg_hashtable_count(h)); + + arg_hashtable_itr_t* itr = arg_hashtable_itr_create(h); + CuAssertTrue(tc, itr != 0); + + int ret = arg_hashtable_itr_advance(itr); + CuAssertTrue(tc, ret != 0); + + ret = arg_hashtable_itr_advance(itr); + CuAssertTrue(tc, ret == 0); + + arg_hashtable_itr_destroy(itr); + arg_hashtable_destroy(h, 1); +} + +void test_arghashtable_basic_004(CuTest* tc) { + arg_hashtable_t* h = arg_hashtable_create(32, hash_key, equal_keys); + CuAssertTrue(tc, h != 0); + CuAssertIntEquals(tc, arg_hashtable_count(h), 0); + + char* key_1 = "k1"; + char* k_1 = (char*)malloc(strlen(key_1) + 1); + memset(k_1, 0, strlen(key_1) + 1); + strncpy(k_1, key_1, strlen(key_1)); + + char* value_1 = "v1"; + char* v_1 = (char*)malloc(strlen(value_1) + 1); + memset(v_1, 0, strlen(value_1) + 1); + strncpy(v_1, value_1, strlen(value_1)); + + arg_hashtable_insert(h, k_1, v_1); + CuAssertTrue(tc, h != 0); + CuAssertIntEquals(tc, 1, arg_hashtable_count(h)); + + arg_hashtable_itr_t* itr = arg_hashtable_itr_create(h); + int ret = arg_hashtable_itr_remove(itr); + CuAssertTrue(tc, ret == 0); + CuAssertIntEquals(tc, 0, arg_hashtable_count(h)); + + arg_hashtable_itr_destroy(itr); + arg_hashtable_destroy(h, 1); +} + +void test_arghashtable_basic_005(CuTest* tc) { + arg_hashtable_t* h = arg_hashtable_create(3, hash_key, equal_keys); + CuAssertTrue(tc, h != 0); + CuAssertIntEquals(tc, arg_hashtable_count(h), 0); + + char* key_1 = "k1"; + char* k_1 = (char*)malloc(strlen(key_1) + 1); + memset(k_1, 0, strlen(key_1) + 1); + strncpy(k_1, key_1, strlen(key_1)); + + char* value_1 = "v1"; + char* v_1 = (char*)malloc(strlen(value_1) + 1); + memset(v_1, 0, strlen(value_1) + 1); + strncpy(v_1, value_1, strlen(value_1)); + + arg_hashtable_insert(h, k_1, v_1); + CuAssertTrue(tc, h != 0); + CuAssertIntEquals(tc, 1, arg_hashtable_count(h)); + + arg_hashtable_remove(h, k_1); + CuAssertIntEquals(tc, 0, arg_hashtable_count(h)); + + arg_hashtable_destroy(h, 1); +} + +void test_arghashtable_basic_006(CuTest* tc) { + arg_hashtable_t* h = arg_hashtable_create(32, hash_key, equal_keys); + CuAssertTrue(tc, h != 0); + CuAssertIntEquals(tc, arg_hashtable_count(h), 0); + + char* key_1 = "k1"; + char* k_1 = (char*)malloc(strlen(key_1) + 1); + memset(k_1, 0, strlen(key_1) + 1); + strncpy(k_1, key_1, strlen(key_1)); + + char* value_1 = "v1"; + char* v_1 = (char*)malloc(strlen(value_1) + 1); + memset(v_1, 0, strlen(value_1) + 1); + strncpy(v_1, value_1, strlen(value_1)); + + arg_hashtable_insert(h, k_1, v_1); + CuAssertTrue(tc, arg_hashtable_count(h) == 1); + + char* vv = (char*)arg_hashtable_search(h, k_1); + CuAssertTrue(tc, strcmp(vv, v_1) == 0); + + arg_hashtable_destroy(h, 1); +} + +void test_arghashtable_basic_007(CuTest* tc) { + arg_hashtable_t* h = arg_hashtable_create(32, hash_key, equal_keys); + CuAssertTrue(tc, h != 0); + CuAssertIntEquals(tc, arg_hashtable_count(h), 0); + + char* key_1 = "k1"; + char* k_1 = (char*)malloc(strlen(key_1) + 1); + memset(k_1, 0, strlen(key_1) + 1); + strncpy(k_1, key_1, strlen(key_1)); + + char* value_1 = "v1"; + char* v_1 = (char*)malloc(strlen(value_1) + 1); + memset(v_1, 0, strlen(value_1) + 1); + strncpy(v_1, value_1, strlen(value_1)); + + arg_hashtable_insert(h, k_1, v_1); + CuAssertIntEquals(tc, 1, arg_hashtable_count(h)); + + char* key_2 = "k2"; + char* k_2 = (char*)malloc(strlen(key_2) + 1); + memset(k_2, 0, strlen(key_2) + 1); + strncpy(k_2, key_2, strlen(key_2)); + + char* value_2 = "v2"; + char* v_2 = (char*)malloc(strlen(value_2) + 1); + memset(v_2, 0, strlen(value_2) + 1); + strncpy(v_2, value_2, strlen(value_2)); + + arg_hashtable_insert(h, k_2, v_2); + CuAssertIntEquals(tc, 2, arg_hashtable_count(h)); + + arg_hashtable_itr_t itr; + int ret = arg_hashtable_itr_search(&itr, h, k_1); + CuAssertTrue(tc, ret != 0); + CuAssertPtrEquals(tc, k_1, arg_hashtable_itr_key(&itr)); + CuAssertPtrEquals(tc, v_1, arg_hashtable_itr_value(&itr)); + CuAssertTrue(tc, strcmp((char*)arg_hashtable_itr_key(&itr), k_1) == 0); + CuAssertTrue(tc, strcmp((char*)arg_hashtable_itr_value(&itr), v_1) == 0); + + arg_hashtable_destroy(h, 1); +} + +CuSuite* get_arghashtable_testsuite() { + CuSuite* suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_arghashtable_basic_001); + SUITE_ADD_TEST(suite, test_arghashtable_basic_002); + SUITE_ADD_TEST(suite, test_arghashtable_basic_003); + SUITE_ADD_TEST(suite, test_arghashtable_basic_004); + SUITE_ADD_TEST(suite, test_arghashtable_basic_005); + SUITE_ADD_TEST(suite, test_arghashtable_basic_006); + SUITE_ADD_TEST(suite, test_arghashtable_basic_007); + return suite; +} + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif diff --git a/c/utf8filenamecheck/windows/argtable/tests/testargint.c b/c/utf8filenamecheck/windows/argtable/tests/testargint.c new file mode 100644 index 0000000..a474430 --- /dev/null +++ b/c/utf8filenamecheck/windows/argtable/tests/testargint.c @@ -0,0 +1,2018 @@ +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 2013-2019 Tom G. Huang + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include + +#include "CuTest.h" +#include "argtable3.h" + +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4204) +#endif + +void test_argint_basic_001(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + + char* argv[] = {"program", "0", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertIntEquals(tc, a->ival[0], 0); + CuAssertTrue(tc, b->count == 0); + CuAssertTrue(tc, c->count == 0); + CuAssertTrue(tc, d->count == 0); + CuAssertTrue(tc, e->count == 0); + CuAssertTrue(tc, f->count == 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_002(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + + char* argv[] = {"program", "1", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertIntEquals(tc, a->ival[0], 1); + CuAssertTrue(tc, b->count == 0); + CuAssertTrue(tc, c->count == 0); + CuAssertTrue(tc, d->count == 0); + CuAssertTrue(tc, e->count == 0); + CuAssertTrue(tc, f->count == 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_003(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + + char* argv[] = {"program", "1", "2", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertIntEquals(tc, a->ival[0], 1); + CuAssertTrue(tc, b->count == 1); + CuAssertIntEquals(tc, b->ival[0], 2); + CuAssertTrue(tc, c->count == 0); + CuAssertTrue(tc, d->count == 0); + CuAssertTrue(tc, e->count == 0); + CuAssertTrue(tc, f->count == 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_004(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + + char* argv[] = {"program", "5", "7", "9", "-d", "-21", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertIntEquals(tc, a->ival[0], 5); + CuAssertTrue(tc, b->count == 1); + CuAssertIntEquals(tc, b->ival[0], 7); + CuAssertTrue(tc, c->count == 1); + CuAssertIntEquals(tc, c->ival[0], 9); + CuAssertTrue(tc, d->count == 1); + CuAssertIntEquals(tc, d->ival[0], -21); + CuAssertTrue(tc, e->count == 0); + CuAssertTrue(tc, f->count == 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_005(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + + char* argv[] = {"program", "-d", "1", "-D2", "--delta", "3", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 1); + CuAssertTrue(tc, a->count == 0); + CuAssertTrue(tc, b->count == 0); + CuAssertTrue(tc, c->count == 0); + CuAssertTrue(tc, d->count == 3); + CuAssertIntEquals(tc, d->ival[0], 1); + CuAssertIntEquals(tc, d->ival[1], 2); + CuAssertIntEquals(tc, d->ival[2], 3); + CuAssertTrue(tc, e->count == 0); + CuAssertTrue(tc, f->count == 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_006(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + + char* argv[] = {"program", "1", "2", "4", "--eps", "-7", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertIntEquals(tc, a->ival[0], 1); + CuAssertTrue(tc, b->count == 1); + CuAssertIntEquals(tc, b->ival[0], 2); + CuAssertTrue(tc, c->count == 1); + CuAssertIntEquals(tc, c->ival[0], 4); + CuAssertTrue(tc, d->count == 0); + CuAssertTrue(tc, e->count == 1); + CuAssertIntEquals(tc, e->ival[0], -7); + CuAssertTrue(tc, f->count == 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_007(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + + char* argv[] = {"program", "1", "2", "4", "--eqn", "-7", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertIntEquals(tc, a->ival[0], 1); + CuAssertTrue(tc, b->count == 1); + CuAssertIntEquals(tc, b->ival[0], 2); + CuAssertTrue(tc, c->count == 1); + CuAssertIntEquals(tc, c->ival[0], 4); + CuAssertTrue(tc, d->count == 0); + CuAssertTrue(tc, e->count == 1); + CuAssertIntEquals(tc, e->ival[0], -7); + CuAssertTrue(tc, f->count == 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_008(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + + char* argv[] = {"program", "1", "2", "3", "-D4", "--eps", "-10", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertIntEquals(tc, a->ival[0], 1); + CuAssertTrue(tc, b->count == 1); + CuAssertIntEquals(tc, b->ival[0], 2); + CuAssertTrue(tc, c->count == 1); + CuAssertIntEquals(tc, c->ival[0], 3); + CuAssertTrue(tc, d->count == 1); + CuAssertIntEquals(tc, d->ival[0], 4); + CuAssertTrue(tc, e->count == 1); + CuAssertIntEquals(tc, e->ival[0], -10); + CuAssertTrue(tc, f->count == 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_009(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "1", "-f", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertTrue(tc, b->count == 0); + CuAssertTrue(tc, c->count == 0); + CuAssertTrue(tc, d->count == 0); + CuAssertTrue(tc, e->count == 0); + CuAssertTrue(tc, f->count == 1); + CuAssertIntEquals(tc, f->ival[0], -1); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_010(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "-f", "1", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 0); + CuAssertIntEquals(tc, a->count, 1); + CuAssertIntEquals(tc, a->ival[0], 1); + CuAssertIntEquals(tc, b->count, 0); + CuAssertIntEquals(tc, c->count, 0); + CuAssertIntEquals(tc, d->count, 0); + CuAssertIntEquals(tc, e->count, 0); + CuAssertIntEquals(tc, f->count, 1); + CuAssertIntEquals(tc, f->ival[0], -1); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_011(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "-f", "2", "--filler", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 0); + CuAssertIntEquals(tc, a->count, 1); + CuAssertIntEquals(tc, a->ival[0], 2); + CuAssertIntEquals(tc, b->count, 0); + CuAssertIntEquals(tc, c->count, 0); + CuAssertIntEquals(tc, d->count, 0); + CuAssertIntEquals(tc, e->count, 0); + CuAssertIntEquals(tc, f->count, 2); + CuAssertIntEquals(tc, f->ival[0], -1); + CuAssertIntEquals(tc, f->ival[1], -1); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_012(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "-f", "1", "--filler=2", "-f", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 0); + CuAssertIntEquals(tc, a->count, 1); + CuAssertIntEquals(tc, a->ival[0], 1); + CuAssertIntEquals(tc, b->count, 0); + CuAssertIntEquals(tc, c->count, 0); + CuAssertIntEquals(tc, d->count, 0); + CuAssertIntEquals(tc, e->count, 0); + CuAssertIntEquals(tc, f->count, 3); + CuAssertIntEquals(tc, f->ival[0], -1); + CuAssertIntEquals(tc, f->ival[1], 2); + CuAssertIntEquals(tc, f->ival[0], -1); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_013(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "0x0", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 0); + CuAssertIntEquals(tc, a->count, 1); + CuAssertIntEquals(tc, a->ival[0], 0x0); + CuAssertIntEquals(tc, b->count, 0); + CuAssertIntEquals(tc, c->count, 0); + CuAssertIntEquals(tc, d->count, 0); + CuAssertIntEquals(tc, e->count, 0); + CuAssertIntEquals(tc, f->count, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_014(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "0x0", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 0); + CuAssertIntEquals(tc, a->count, 1); + CuAssertIntEquals(tc, a->ival[0], 0x0); + CuAssertIntEquals(tc, b->count, 0); + CuAssertIntEquals(tc, c->count, 0); + CuAssertIntEquals(tc, d->count, 0); + CuAssertIntEquals(tc, e->count, 0); + CuAssertIntEquals(tc, f->count, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_015(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "0x10", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 0); + CuAssertIntEquals(tc, a->count, 1); + CuAssertIntEquals(tc, a->ival[0], 0x10); + CuAssertIntEquals(tc, b->count, 0); + CuAssertIntEquals(tc, c->count, 0); + CuAssertIntEquals(tc, d->count, 0); + CuAssertIntEquals(tc, e->count, 0); + CuAssertIntEquals(tc, f->count, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_016(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "0x10", "0x32", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 0); + CuAssertIntEquals(tc, a->count, 1); + CuAssertIntEquals(tc, a->ival[0], 0x10); + CuAssertIntEquals(tc, b->count, 1); + CuAssertIntEquals(tc, b->ival[0], 0x32); + CuAssertIntEquals(tc, c->count, 0); + CuAssertIntEquals(tc, d->count, 0); + CuAssertIntEquals(tc, e->count, 0); + CuAssertIntEquals(tc, f->count, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_017(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "0x5", "0xA", "0xF", "-d", "-0x1E", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 0); + CuAssertIntEquals(tc, a->count, 1); + CuAssertIntEquals(tc, a->ival[0], 0x5); + CuAssertIntEquals(tc, b->count, 1); + CuAssertIntEquals(tc, b->ival[0], 0xA); + CuAssertIntEquals(tc, c->count, 1); + CuAssertIntEquals(tc, c->ival[0], 0xF); + CuAssertIntEquals(tc, d->count, 1); + CuAssertIntEquals(tc, d->ival[0], -0x1E); + CuAssertIntEquals(tc, e->count, 0); + CuAssertIntEquals(tc, f->count, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_018(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "-d", "0xab", "-D0x09", "--delta", "0x02e", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 1); + CuAssertIntEquals(tc, a->count, 0); + CuAssertIntEquals(tc, b->count, 0); + CuAssertIntEquals(tc, c->count, 0); + CuAssertIntEquals(tc, d->count, 3); + CuAssertIntEquals(tc, d->ival[0], 0xab); + CuAssertIntEquals(tc, d->ival[1], 0x09); + CuAssertIntEquals(tc, d->ival[2], 0x02e); + CuAssertIntEquals(tc, e->count, 0); + CuAssertIntEquals(tc, f->count, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_019(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "0o0", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 0); + CuAssertIntEquals(tc, a->count, 1); + CuAssertIntEquals(tc, a->ival[0], 0); + CuAssertIntEquals(tc, b->count, 0); + CuAssertIntEquals(tc, c->count, 0); + CuAssertIntEquals(tc, d->count, 0); + CuAssertIntEquals(tc, e->count, 0); + CuAssertIntEquals(tc, f->count, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_020(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "0o10", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 0); + CuAssertIntEquals(tc, a->count, 1); + CuAssertIntEquals(tc, a->ival[0], 010); + CuAssertIntEquals(tc, b->count, 0); + CuAssertIntEquals(tc, c->count, 0); + CuAssertIntEquals(tc, d->count, 0); + CuAssertIntEquals(tc, e->count, 0); + CuAssertIntEquals(tc, f->count, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_021(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "0o67", "0O23", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 0); + CuAssertIntEquals(tc, a->count, 1); + CuAssertIntEquals(tc, a->ival[0], 067); + CuAssertIntEquals(tc, b->count, 1); + CuAssertIntEquals(tc, b->ival[0], 023); + CuAssertIntEquals(tc, c->count, 0); + CuAssertIntEquals(tc, d->count, 0); + CuAssertIntEquals(tc, e->count, 0); + CuAssertIntEquals(tc, f->count, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_022(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "0o5", "0O0", "0x1", "-d", "-0o6", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 0); + CuAssertIntEquals(tc, a->count, 1); + CuAssertIntEquals(tc, a->ival[0], 05); + CuAssertIntEquals(tc, b->count, 1); + CuAssertIntEquals(tc, b->ival[0], 0); + CuAssertIntEquals(tc, c->count, 1); + CuAssertIntEquals(tc, c->ival[0], 0x1); + CuAssertIntEquals(tc, d->count, 1); + CuAssertIntEquals(tc, d->ival[0], -06); + CuAssertIntEquals(tc, e->count, 0); + CuAssertIntEquals(tc, f->count, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_023(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "-d", "0o012", "-D0o0777", "--delta", "0o56", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 1); + CuAssertIntEquals(tc, a->count, 0); + CuAssertIntEquals(tc, b->count, 0); + CuAssertIntEquals(tc, c->count, 0); + CuAssertIntEquals(tc, d->count, 3); + CuAssertIntEquals(tc, d->ival[0], 012); + CuAssertIntEquals(tc, d->ival[1], 0777); + CuAssertIntEquals(tc, d->ival[2], 056); + CuAssertIntEquals(tc, e->count, 0); + CuAssertIntEquals(tc, f->count, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_024(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "0B0", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 0); + CuAssertIntEquals(tc, a->count, 1); + CuAssertIntEquals(tc, a->ival[0], 0); + CuAssertIntEquals(tc, b->count, 0); + CuAssertIntEquals(tc, c->count, 0); + CuAssertIntEquals(tc, d->count, 0); + CuAssertIntEquals(tc, e->count, 0); + CuAssertIntEquals(tc, f->count, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_025(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "0B0", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 0); + CuAssertIntEquals(tc, a->count, 1); + CuAssertIntEquals(tc, a->ival[0], 0); + CuAssertIntEquals(tc, b->count, 0); + CuAssertIntEquals(tc, c->count, 0); + CuAssertIntEquals(tc, d->count, 0); + CuAssertIntEquals(tc, e->count, 0); + CuAssertIntEquals(tc, f->count, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_026(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "0b10", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 0); + CuAssertIntEquals(tc, a->count, 1); + CuAssertIntEquals(tc, a->ival[0], 2); + CuAssertIntEquals(tc, b->count, 0); + CuAssertIntEquals(tc, c->count, 0); + CuAssertIntEquals(tc, d->count, 0); + CuAssertIntEquals(tc, e->count, 0); + CuAssertIntEquals(tc, f->count, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_027(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "0B10110", "0b111001", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 0); + CuAssertIntEquals(tc, a->count, 1); + CuAssertIntEquals(tc, a->ival[0], 22); + CuAssertIntEquals(tc, b->count, 1); + CuAssertIntEquals(tc, b->ival[0], 57); + CuAssertIntEquals(tc, c->count, 0); + CuAssertIntEquals(tc, d->count, 0); + CuAssertIntEquals(tc, e->count, 0); + CuAssertIntEquals(tc, f->count, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_028(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "0B10110", "0b111001", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 0); + CuAssertIntEquals(tc, a->count, 1); + CuAssertIntEquals(tc, a->ival[0], 22); + CuAssertIntEquals(tc, b->count, 1); + CuAssertIntEquals(tc, b->ival[0], 57); + CuAssertIntEquals(tc, c->count, 0); + CuAssertIntEquals(tc, d->count, 0); + CuAssertIntEquals(tc, e->count, 0); + CuAssertIntEquals(tc, f->count, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_029(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "0b101001", "0b101", "0b00101010101", "-d", "0B110000011", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 0); + CuAssertIntEquals(tc, a->count, 1); + CuAssertIntEquals(tc, a->ival[0], 41); + CuAssertIntEquals(tc, b->count, 1); + CuAssertIntEquals(tc, b->ival[0], 5); + CuAssertIntEquals(tc, c->count, 1); + CuAssertIntEquals(tc, c->ival[0], 341); + CuAssertIntEquals(tc, d->count, 1); + CuAssertIntEquals(tc, d->ival[0], 387); + CuAssertIntEquals(tc, e->count, 0); + CuAssertIntEquals(tc, f->count, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_030(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "-d", "0b101", "-D0B11", "--delta", "0b11011", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 1); + CuAssertIntEquals(tc, a->count, 0); + CuAssertIntEquals(tc, b->count, 0); + CuAssertIntEquals(tc, c->count, 0); + CuAssertIntEquals(tc, d->count, 3); + CuAssertIntEquals(tc, d->ival[0], 5); + CuAssertIntEquals(tc, d->ival[1], 3); + CuAssertIntEquals(tc, d->ival[2], 27); + CuAssertIntEquals(tc, e->count, 0); + CuAssertIntEquals(tc, f->count, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_031(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "11", "0x11", "0o11", "-D0b11", "--eps", "-0o50", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 0); + CuAssertIntEquals(tc, a->count, 1); + CuAssertIntEquals(tc, a->ival[0], 11); + CuAssertIntEquals(tc, b->count, 1); + CuAssertIntEquals(tc, b->ival[0], 0x11); + CuAssertIntEquals(tc, c->count, 1); + CuAssertIntEquals(tc, c->ival[0], 011); + CuAssertIntEquals(tc, d->count, 1); + CuAssertIntEquals(tc, d->ival[0], 3); + CuAssertIntEquals(tc, e->count, 1); + CuAssertIntEquals(tc, e->ival[0], -050); + CuAssertIntEquals(tc, f->count, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_032(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "1KB", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 0); + CuAssertIntEquals(tc, a->count, 1); + CuAssertIntEquals(tc, a->ival[0], 1024); + CuAssertIntEquals(tc, b->count, 0); + CuAssertIntEquals(tc, c->count, 0); + CuAssertIntEquals(tc, d->count, 0); + CuAssertIntEquals(tc, e->count, 0); + CuAssertIntEquals(tc, f->count, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_033(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "1MB", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 0); + CuAssertIntEquals(tc, a->count, 1); + CuAssertIntEquals(tc, a->ival[0], 1024 * 1024); + CuAssertIntEquals(tc, b->count, 0); + CuAssertIntEquals(tc, c->count, 0); + CuAssertIntEquals(tc, d->count, 0); + CuAssertIntEquals(tc, e->count, 0); + CuAssertIntEquals(tc, f->count, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_034(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "1GB", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 0); + CuAssertIntEquals(tc, a->count, 1); + CuAssertIntEquals(tc, a->ival[0], 1024 * 1024 * 1024); + CuAssertIntEquals(tc, b->count, 0); + CuAssertIntEquals(tc, c->count, 0); + CuAssertIntEquals(tc, d->count, 0); + CuAssertIntEquals(tc, e->count, 0); + CuAssertIntEquals(tc, f->count, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_035(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "0x5KB", "0xAMB", "0x1GB", "-d", "-0x40A01400", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 0); + CuAssertIntEquals(tc, a->count, 1); + CuAssertIntEquals(tc, a->ival[0], 0x5 * 1024); + CuAssertIntEquals(tc, b->count, 1); + CuAssertIntEquals(tc, b->ival[0], 0xA * 1024 * 1024); + CuAssertIntEquals(tc, c->count, 1); + CuAssertIntEquals(tc, c->ival[0], 0x1 * 1024 * 1024 * 1024); + CuAssertIntEquals(tc, d->count, 1); + CuAssertIntEquals(tc, d->ival[0], -0x40A01400); + CuAssertIntEquals(tc, e->count, 0); + CuAssertIntEquals(tc, f->count, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_036(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 1); + CuAssertIntEquals(tc, a->count, 0); + CuAssertIntEquals(tc, b->count, 0); + CuAssertIntEquals(tc, c->count, 0); + CuAssertIntEquals(tc, d->count, 0); + CuAssertIntEquals(tc, e->count, 0); + CuAssertIntEquals(tc, f->count, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_037(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "1", "2", "3", "4", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 1); + CuAssertIntEquals(tc, a->count, 1); + CuAssertIntEquals(tc, a->ival[0], 1); + CuAssertIntEquals(tc, b->count, 1); + CuAssertIntEquals(tc, b->ival[0], 2); + CuAssertIntEquals(tc, c->count, 1); + CuAssertIntEquals(tc, c->ival[0], 3); + CuAssertIntEquals(tc, d->count, 0); + CuAssertIntEquals(tc, e->count, 0); + CuAssertIntEquals(tc, f->count, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_038(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "1", "2", "3", "-d1", "-d2", "-d3", "-d4", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 1); + CuAssertIntEquals(tc, a->count, 1); + CuAssertIntEquals(tc, a->ival[0], 1); + CuAssertIntEquals(tc, b->count, 1); + CuAssertIntEquals(tc, b->ival[0], 2); + CuAssertIntEquals(tc, c->count, 1); + CuAssertIntEquals(tc, c->ival[0], 3); + CuAssertIntEquals(tc, d->count, 3); + CuAssertIntEquals(tc, d->ival[0], 1); + CuAssertIntEquals(tc, d->ival[1], 2); + CuAssertIntEquals(tc, d->ival[2], 3); + CuAssertIntEquals(tc, e->count, 0); + CuAssertIntEquals(tc, f->count, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_039(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "1", "2", "3", "-d1", "-d2", "-d3", "-d", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 1); + CuAssertIntEquals(tc, a->count, 1); + CuAssertIntEquals(tc, a->ival[0], 1); + CuAssertIntEquals(tc, b->count, 1); + CuAssertIntEquals(tc, b->ival[0], 2); + CuAssertIntEquals(tc, c->count, 1); + CuAssertIntEquals(tc, c->ival[0], 3); + CuAssertIntEquals(tc, d->count, 3); + CuAssertIntEquals(tc, d->ival[0], 1); + CuAssertIntEquals(tc, d->ival[1], 2); + CuAssertIntEquals(tc, d->ival[2], 3); + CuAssertIntEquals(tc, e->count, 0); + CuAssertIntEquals(tc, f->count, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_040(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "1", "2", "3", "-d1", "-d2", "-d", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 1); + CuAssertIntEquals(tc, a->count, 1); + CuAssertIntEquals(tc, a->ival[0], 1); + CuAssertIntEquals(tc, b->count, 1); + CuAssertIntEquals(tc, b->ival[0], 2); + CuAssertIntEquals(tc, c->count, 1); + CuAssertIntEquals(tc, c->ival[0], 3); + CuAssertIntEquals(tc, d->count, 2); + CuAssertIntEquals(tc, d->ival[0], 1); + CuAssertIntEquals(tc, d->ival[1], 2); + CuAssertIntEquals(tc, e->count, 0); + CuAssertIntEquals(tc, f->count, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_041(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "1", "2", "3", "-d1", "-d", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 1); + CuAssertIntEquals(tc, a->count, 1); + CuAssertIntEquals(tc, a->ival[0], 1); + CuAssertIntEquals(tc, b->count, 1); + CuAssertIntEquals(tc, b->ival[0], 2); + CuAssertIntEquals(tc, c->count, 1); + CuAssertIntEquals(tc, c->ival[0], 3); + CuAssertIntEquals(tc, d->count, 1); + CuAssertIntEquals(tc, d->ival[0], 1); + CuAssertIntEquals(tc, e->count, 0); + CuAssertIntEquals(tc, f->count, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_042(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "1", "2", "3", "-d", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 1); + CuAssertIntEquals(tc, a->count, 1); + CuAssertIntEquals(tc, a->ival[0], 1); + CuAssertIntEquals(tc, b->count, 1); + CuAssertIntEquals(tc, b->ival[0], 2); + CuAssertIntEquals(tc, c->count, 1); + CuAssertIntEquals(tc, c->ival[0], 3); + CuAssertIntEquals(tc, d->count, 0); + CuAssertIntEquals(tc, e->count, 0); + CuAssertIntEquals(tc, f->count, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_043(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "1", "2", "3", "--eps", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 1); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_044(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "1", "2", "3", "--eps", "3", "--eqn", "6", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 1); + CuAssertIntEquals(tc, a->count, 1); + CuAssertIntEquals(tc, a->ival[0], 1); + CuAssertIntEquals(tc, b->count, 1); + CuAssertIntEquals(tc, b->ival[0], 2); + CuAssertIntEquals(tc, c->count, 1); + CuAssertIntEquals(tc, c->ival[0], 3); + CuAssertIntEquals(tc, d->count, 0); + CuAssertIntEquals(tc, e->count, 1); + CuAssertIntEquals(tc, e->ival[0], 3); + CuAssertIntEquals(tc, f->count, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_045(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "hello", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 1); + CuAssertIntEquals(tc, a->count, 0); + CuAssertIntEquals(tc, b->count, 0); + CuAssertIntEquals(tc, c->count, 0); + CuAssertIntEquals(tc, d->count, 0); + CuAssertIntEquals(tc, e->count, 0); + CuAssertIntEquals(tc, f->count, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_046(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "1.234", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 1); + CuAssertIntEquals(tc, a->count, 0); + CuAssertIntEquals(tc, b->count, 0); + CuAssertIntEquals(tc, c->count, 0); + CuAssertIntEquals(tc, d->count, 0); + CuAssertIntEquals(tc, e->count, 0); + CuAssertIntEquals(tc, f->count, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_047(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "4", "hello", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 1); + CuAssertIntEquals(tc, a->count, 1); + CuAssertIntEquals(tc, a->ival[0], 4); + CuAssertIntEquals(tc, b->count, 0); + CuAssertIntEquals(tc, c->count, 0); + CuAssertIntEquals(tc, d->count, 0); + CuAssertIntEquals(tc, e->count, 0); + CuAssertIntEquals(tc, f->count, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_048(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "5", "1.234", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 1); + CuAssertIntEquals(tc, a->count, 1); + CuAssertIntEquals(tc, a->ival[0], 5); + CuAssertIntEquals(tc, b->count, 0); + CuAssertIntEquals(tc, c->count, 0); + CuAssertIntEquals(tc, d->count, 0); + CuAssertIntEquals(tc, e->count, 0); + CuAssertIntEquals(tc, f->count, 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_049(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "-f", "2", "--filler=", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 2); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_050(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "0x0g", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 1); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_051(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "0o08", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 1); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_052(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "0b02", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 1); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_053(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "1000GB", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 1); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argint_basic_054(CuTest* tc) { + struct arg_int* a = arg_int1(NULL, NULL, "a", "a is "); + struct arg_int* b = arg_int0(NULL, NULL, "b", "b is "); + struct arg_int* c = arg_int0(NULL, NULL, "c", "c is "); + struct arg_int* d = arg_intn("dD", "delta", "", 0, 3, "d can occur 0..3 times"); + struct arg_int* e = arg_int0(NULL, "eps,eqn", "", "eps is optional"); + struct arg_int* f = arg_intn("fF", "filler", "", 0, 3, "f can occur 0..3 times"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, e, f, end}; + int nerrors; + int i; + + char* argv[] = {"program", "1GBH", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + /* allow missing argument values for the f argument, and set defaults to -1 */ + f->hdr.flag |= ARG_HASOPTVALUE; + for (i = 0; i < f->hdr.maxcount; i++) + f->ival[i] = -1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertIntEquals(tc, nerrors, 1); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +CuSuite* get_argint_testsuite() { + CuSuite* suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_argint_basic_001); + SUITE_ADD_TEST(suite, test_argint_basic_002); + SUITE_ADD_TEST(suite, test_argint_basic_003); + SUITE_ADD_TEST(suite, test_argint_basic_004); + SUITE_ADD_TEST(suite, test_argint_basic_005); + SUITE_ADD_TEST(suite, test_argint_basic_006); + SUITE_ADD_TEST(suite, test_argint_basic_007); + SUITE_ADD_TEST(suite, test_argint_basic_008); + SUITE_ADD_TEST(suite, test_argint_basic_009); + SUITE_ADD_TEST(suite, test_argint_basic_010); + SUITE_ADD_TEST(suite, test_argint_basic_011); + SUITE_ADD_TEST(suite, test_argint_basic_012); + SUITE_ADD_TEST(suite, test_argint_basic_013); + SUITE_ADD_TEST(suite, test_argint_basic_014); + SUITE_ADD_TEST(suite, test_argint_basic_015); + SUITE_ADD_TEST(suite, test_argint_basic_016); + SUITE_ADD_TEST(suite, test_argint_basic_017); + SUITE_ADD_TEST(suite, test_argint_basic_018); + SUITE_ADD_TEST(suite, test_argint_basic_019); + SUITE_ADD_TEST(suite, test_argint_basic_020); + SUITE_ADD_TEST(suite, test_argint_basic_021); + SUITE_ADD_TEST(suite, test_argint_basic_022); + SUITE_ADD_TEST(suite, test_argint_basic_023); + SUITE_ADD_TEST(suite, test_argint_basic_024); + SUITE_ADD_TEST(suite, test_argint_basic_025); + SUITE_ADD_TEST(suite, test_argint_basic_026); + SUITE_ADD_TEST(suite, test_argint_basic_027); + SUITE_ADD_TEST(suite, test_argint_basic_028); + SUITE_ADD_TEST(suite, test_argint_basic_029); + SUITE_ADD_TEST(suite, test_argint_basic_030); + SUITE_ADD_TEST(suite, test_argint_basic_031); + SUITE_ADD_TEST(suite, test_argint_basic_032); + SUITE_ADD_TEST(suite, test_argint_basic_033); + SUITE_ADD_TEST(suite, test_argint_basic_034); + SUITE_ADD_TEST(suite, test_argint_basic_035); + SUITE_ADD_TEST(suite, test_argint_basic_036); + SUITE_ADD_TEST(suite, test_argint_basic_037); + SUITE_ADD_TEST(suite, test_argint_basic_038); + SUITE_ADD_TEST(suite, test_argint_basic_039); + SUITE_ADD_TEST(suite, test_argint_basic_040); + SUITE_ADD_TEST(suite, test_argint_basic_041); + SUITE_ADD_TEST(suite, test_argint_basic_042); + SUITE_ADD_TEST(suite, test_argint_basic_043); + SUITE_ADD_TEST(suite, test_argint_basic_044); + SUITE_ADD_TEST(suite, test_argint_basic_045); + SUITE_ADD_TEST(suite, test_argint_basic_046); + SUITE_ADD_TEST(suite, test_argint_basic_047); + SUITE_ADD_TEST(suite, test_argint_basic_048); + SUITE_ADD_TEST(suite, test_argint_basic_049); + SUITE_ADD_TEST(suite, test_argint_basic_050); + SUITE_ADD_TEST(suite, test_argint_basic_051); + SUITE_ADD_TEST(suite, test_argint_basic_052); + SUITE_ADD_TEST(suite, test_argint_basic_053); + SUITE_ADD_TEST(suite, test_argint_basic_054); + return suite; +} + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif diff --git a/c/utf8filenamecheck/windows/argtable/tests/testarglit.c b/c/utf8filenamecheck/windows/argtable/tests/testarglit.c new file mode 100644 index 0000000..8109f87 --- /dev/null +++ b/c/utf8filenamecheck/windows/argtable/tests/testarglit.c @@ -0,0 +1,538 @@ +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 2013-2019 Tom G. Huang + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include + +#include "CuTest.h" +#include "argtable3.h" + +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4204) +#endif + +void test_arglit_basic_001(CuTest* tc) { + struct arg_lit* a = arg_lit0(NULL, "hello,world", "either --hello or --world or none"); + struct arg_lit* b = arg_lit0("bB", NULL, "either -b or -B or none"); + struct arg_lit* c = arg_lit1("cC", NULL, "either -c or -C"); + struct arg_lit* d = arg_litn("dD", "delta", 2, 4, "-d|-D|--delta 2..4 occurences"); + struct arg_lit* help = arg_lit0(NULL, "help", "print this help and exit"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, help, end}; + int nerrors; + + char* argv[] = {"program", "--help", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 2); + CuAssertTrue(tc, a->count == 0); + CuAssertTrue(tc, b->count == 0); + CuAssertTrue(tc, c->count == 0); + CuAssertTrue(tc, d->count == 0); + CuAssertTrue(tc, help->count == 1); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_arglit_basic_002(CuTest* tc) { + struct arg_lit* a = arg_lit0(NULL, "hello,world", "either --hello or --world or none"); + struct arg_lit* b = arg_lit0("bB", NULL, "either -b or -B or none"); + struct arg_lit* c = arg_lit1("cC", NULL, "either -c or -C"); + struct arg_lit* d = arg_litn("dD", "delta", 2, 4, "-d|-D|--delta 2..4 occurences"); + struct arg_lit* help = arg_lit0(NULL, "help", "print this help and exit"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, help, end}; + int nerrors; + + char* argv[] = {"program", "-cDd", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + if (nerrors > 0) + arg_print_errors(stdout, end, argv[0]); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 0); + CuAssertTrue(tc, b->count == 0); + CuAssertTrue(tc, c->count == 1); + CuAssertTrue(tc, d->count == 2); + CuAssertTrue(tc, help->count == 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_arglit_basic_003(CuTest* tc) { + struct arg_lit* a = arg_lit0(NULL, "hello,world", "either --hello or --world or none"); + struct arg_lit* b = arg_lit0("bB", NULL, "either -b or -B or none"); + struct arg_lit* c = arg_lit1("cC", NULL, "either -c or -C"); + struct arg_lit* d = arg_litn("dD", "delta", 2, 4, "-d|-D|--delta 2..4 occurences"); + struct arg_lit* help = arg_lit0(NULL, "help", "print this help and exit"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, help, end}; + int nerrors; + + char* argv[] = {"program", "-cdDd", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + if (nerrors > 0) + arg_print_errors(stdout, end, argv[0]); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 0); + CuAssertTrue(tc, b->count == 0); + CuAssertTrue(tc, c->count == 1); + CuAssertTrue(tc, d->count == 3); + CuAssertTrue(tc, help->count == 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_arglit_basic_004(CuTest* tc) { + struct arg_lit* a = arg_lit0(NULL, "hello,world", "either --hello or --world or none"); + struct arg_lit* b = arg_lit0("bB", NULL, "either -b or -B or none"); + struct arg_lit* c = arg_lit1("cC", NULL, "either -c or -C"); + struct arg_lit* d = arg_litn("dD", "delta", 2, 4, "-d|-D|--delta 2..4 occurences"); + struct arg_lit* help = arg_lit0(NULL, "help", "print this help and exit"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, help, end}; + int nerrors; + + char* argv[] = {"program", "-CDd", "--delta", "--delta", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + if (nerrors > 0) + arg_print_errors(stdout, end, argv[0]); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 0); + CuAssertTrue(tc, b->count == 0); + CuAssertTrue(tc, c->count == 1); + CuAssertTrue(tc, d->count == 4); + CuAssertTrue(tc, help->count == 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_arglit_basic_005(CuTest* tc) { + struct arg_lit* a = arg_lit0(NULL, "hello,world", "either --hello or --world or none"); + struct arg_lit* b = arg_lit0("bB", NULL, "either -b or -B or none"); + struct arg_lit* c = arg_lit1("cC", NULL, "either -c or -C"); + struct arg_lit* d = arg_litn("dD", "delta", 2, 4, "-d|-D|--delta 2..4 occurences"); + struct arg_lit* help = arg_lit0(NULL, "help", "print this help and exit"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, help, end}; + int nerrors; + + char* argv[] = {"program", "--delta", "-cD", "-b", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + if (nerrors > 0) + arg_print_errors(stdout, end, argv[0]); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 0); + CuAssertTrue(tc, b->count == 1); + CuAssertTrue(tc, c->count == 1); + CuAssertTrue(tc, d->count == 2); + CuAssertTrue(tc, help->count == 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_arglit_basic_006(CuTest* tc) { + struct arg_lit* a = arg_lit0(NULL, "hello,world", "either --hello or --world or none"); + struct arg_lit* b = arg_lit0("bB", NULL, "either -b or -B or none"); + struct arg_lit* c = arg_lit1("cC", NULL, "either -c or -C"); + struct arg_lit* d = arg_litn("dD", "delta", 2, 4, "-d|-D|--delta 2..4 occurences"); + struct arg_lit* help = arg_lit0(NULL, "help", "print this help and exit"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, help, end}; + int nerrors; + + char* argv[] = {"program", "-D", "-B", "--delta", "-C", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + if (nerrors > 0) + arg_print_errors(stdout, end, argv[0]); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 0); + CuAssertTrue(tc, b->count == 1); + CuAssertTrue(tc, c->count == 1); + CuAssertTrue(tc, d->count == 2); + CuAssertTrue(tc, help->count == 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_arglit_basic_007(CuTest* tc) { + struct arg_lit* a = arg_lit0(NULL, "hello,world", "either --hello or --world or none"); + struct arg_lit* b = arg_lit0("bB", NULL, "either -b or -B or none"); + struct arg_lit* c = arg_lit1("cC", NULL, "either -c or -C"); + struct arg_lit* d = arg_litn("dD", "delta", 2, 4, "-d|-D|--delta 2..4 occurences"); + struct arg_lit* help = arg_lit0(NULL, "help", "print this help and exit"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, help, end}; + int nerrors; + + char* argv[] = {"program", "-D", "-B", "--delta", "-C", "--hello", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + if (nerrors > 0) + arg_print_errors(stdout, end, argv[0]); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertTrue(tc, b->count == 1); + CuAssertTrue(tc, c->count == 1); + CuAssertTrue(tc, d->count == 2); + CuAssertTrue(tc, help->count == 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_arglit_basic_008(CuTest* tc) { + struct arg_lit* a = arg_lit0(NULL, "hello,world", "either --hello or --world or none"); + struct arg_lit* b = arg_lit0("bB", NULL, "either -b or -B or none"); + struct arg_lit* c = arg_lit1("cC", NULL, "either -c or -C"); + struct arg_lit* d = arg_litn("dD", "delta", 2, 4, "-d|-D|--delta 2..4 occurences"); + struct arg_lit* help = arg_lit0(NULL, "help", "print this help and exit"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, help, end}; + int nerrors; + + char* argv[] = {"program", "-D", "-B", "--delta", "-C", "--world", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + if (nerrors > 0) + arg_print_errors(stdout, end, argv[0]); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertTrue(tc, b->count == 1); + CuAssertTrue(tc, c->count == 1); + CuAssertTrue(tc, d->count == 2); + CuAssertTrue(tc, help->count == 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_arglit_basic_009(CuTest* tc) { + struct arg_lit* a = arg_lit0(NULL, "hello,world", "either --hello or --world or none"); + struct arg_lit* b = arg_lit0("bB", NULL, "either -b or -B or none"); + struct arg_lit* c = arg_lit1("cC", NULL, "either -c or -C"); + struct arg_lit* d = arg_litn("dD", "delta", 2, 4, "-d|-D|--delta 2..4 occurences"); + struct arg_lit* help = arg_lit0(NULL, "help", "print this help and exit"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, help, end}; + int nerrors; + + char* argv[] = {"program", "-c", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 1); + CuAssertTrue(tc, a->count == 0); + CuAssertTrue(tc, b->count == 0); + CuAssertTrue(tc, c->count == 1); + CuAssertTrue(tc, d->count == 0); + CuAssertTrue(tc, help->count == 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_arglit_basic_010(CuTest* tc) { + struct arg_lit* a = arg_lit0(NULL, "hello,world", "either --hello or --world or none"); + struct arg_lit* b = arg_lit0("bB", NULL, "either -b or -B or none"); + struct arg_lit* c = arg_lit1("cC", NULL, "either -c or -C"); + struct arg_lit* d = arg_litn("dD", "delta", 2, 4, "-d|-D|--delta 2..4 occurences"); + struct arg_lit* help = arg_lit0(NULL, "help", "print this help and exit"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, help, end}; + int nerrors; + + char* argv[] = {"program", "-D", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 2); + CuAssertTrue(tc, a->count == 0); + CuAssertTrue(tc, b->count == 0); + CuAssertTrue(tc, c->count == 0); + CuAssertTrue(tc, d->count == 1); + CuAssertTrue(tc, help->count == 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_arglit_basic_011(CuTest* tc) { + struct arg_lit* a = arg_lit0(NULL, "hello,world", "either --hello or --world or none"); + struct arg_lit* b = arg_lit0("bB", NULL, "either -b or -B or none"); + struct arg_lit* c = arg_lit1("cC", NULL, "either -c or -C"); + struct arg_lit* d = arg_litn("dD", "delta", 2, 4, "-d|-D|--delta 2..4 occurences"); + struct arg_lit* help = arg_lit0(NULL, "help", "print this help and exit"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, help, end}; + int nerrors; + + char* argv[] = {"program", "-CD", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 1); + CuAssertTrue(tc, a->count == 0); + CuAssertTrue(tc, b->count == 0); + CuAssertTrue(tc, c->count == 1); + CuAssertTrue(tc, d->count == 1); + CuAssertTrue(tc, help->count == 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_arglit_basic_012(CuTest* tc) { + struct arg_lit* a = arg_lit0(NULL, "hello,world", "either --hello or --world or none"); + struct arg_lit* b = arg_lit0("bB", NULL, "either -b or -B or none"); + struct arg_lit* c = arg_lit1("cC", NULL, "either -c or -C"); + struct arg_lit* d = arg_litn("dD", "delta", 2, 4, "-d|-D|--delta 2..4 occurences"); + struct arg_lit* help = arg_lit0(NULL, "help", "print this help and exit"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, help, end}; + int nerrors; + + char* argv[] = {"program", "-Dd", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 1); + CuAssertTrue(tc, a->count == 0); + CuAssertTrue(tc, b->count == 0); + CuAssertTrue(tc, c->count == 0); + CuAssertTrue(tc, d->count == 2); + CuAssertTrue(tc, help->count == 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_arglit_basic_013(CuTest* tc) { + struct arg_lit* a = arg_lit0(NULL, "hello,world", "either --hello or --world or none"); + struct arg_lit* b = arg_lit0("bB", NULL, "either -b or -B or none"); + struct arg_lit* c = arg_lit1("cC", NULL, "either -c or -C"); + struct arg_lit* d = arg_litn("dD", "delta", 2, 4, "-d|-D|--delta 2..4 occurences"); + struct arg_lit* help = arg_lit0(NULL, "help", "print this help and exit"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, help, end}; + int nerrors; + + char* argv[] = {"program", "-cddddd", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 1); + CuAssertTrue(tc, a->count == 0); + CuAssertTrue(tc, b->count == 0); + CuAssertTrue(tc, c->count == 1); + CuAssertTrue(tc, d->count == 4); + CuAssertTrue(tc, help->count == 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_arglit_basic_014(CuTest* tc) { + struct arg_lit* a = arg_lit0(NULL, "hello,world", "either --hello or --world or none"); + struct arg_lit* b = arg_lit0("bB", NULL, "either -b or -B or none"); + struct arg_lit* c = arg_lit1("cC", NULL, "either -c or -C"); + struct arg_lit* d = arg_litn("dD", "delta", 2, 4, "-d|-D|--delta 2..4 occurences"); + struct arg_lit* help = arg_lit0(NULL, "help", "print this help and exit"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, help, end}; + int nerrors; + + char* argv[] = {"program", "-ccddd", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 1); + CuAssertTrue(tc, a->count == 0); + CuAssertTrue(tc, b->count == 0); + CuAssertTrue(tc, c->count == 1); + CuAssertTrue(tc, d->count == 3); + CuAssertTrue(tc, help->count == 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_arglit_basic_015(CuTest* tc) { + struct arg_lit* a = arg_lit0(NULL, "hello,world", "either --hello or --world or none"); + struct arg_lit* b = arg_lit0("bB", NULL, "either -b or -B or none"); + struct arg_lit* c = arg_lit1("cC", NULL, "either -c or -C"); + struct arg_lit* d = arg_litn("dD", "delta", 2, 4, "-d|-D|--delta 2..4 occurences"); + struct arg_lit* help = arg_lit0(NULL, "help", "print this help and exit"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, help, end}; + int nerrors; + + char* argv[] = {"program", "-C", "-d", "-D", "--delta", "-b", "-B", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 1); + CuAssertTrue(tc, a->count == 0); + CuAssertTrue(tc, b->count == 1); + CuAssertTrue(tc, c->count == 1); + CuAssertTrue(tc, d->count == 3); + CuAssertTrue(tc, help->count == 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_arglit_basic_016(CuTest* tc) { + struct arg_lit* a = arg_lit0(NULL, "hello,world", "either --hello or --world or none"); + struct arg_lit* b = arg_lit0("bB", NULL, "either -b or -B or none"); + struct arg_lit* c = arg_lit1("cC", NULL, "either -c or -C"); + struct arg_lit* d = arg_litn("dD", "delta", 2, 4, "-d|-D|--delta 2..4 occurences"); + struct arg_lit* help = arg_lit0(NULL, "help", "print this help and exit"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, help, end}; + int nerrors; + + char* argv[] = {"program", "-C", "-d", "-D", "--delta", "--hello", "--world", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 1); + CuAssertTrue(tc, a->count == 1); + CuAssertTrue(tc, b->count == 0); + CuAssertTrue(tc, c->count == 1); + CuAssertTrue(tc, d->count == 3); + CuAssertTrue(tc, help->count == 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_arglit_basic_017(CuTest* tc) { + struct arg_lit* a = arg_lit0(NULL, "hello,world", "either --hello or --world or none"); + struct arg_lit* b = arg_lit0("bB", NULL, "either -b or -B or none"); + struct arg_lit* c = arg_lit1("cC", NULL, "either -c or -C"); + struct arg_lit* d = arg_litn("dD", "delta", 2, 4, "-d|-D|--delta 2..4 occurences"); + struct arg_lit* help = arg_lit0(NULL, "help", "print this help and exit"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, help, end}; + int nerrors; + + char* argv[] = {"program", "-C", "-d", "-D", "--delta", "--hello", "X", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 1); + CuAssertTrue(tc, a->count == 1); + CuAssertTrue(tc, b->count == 0); + CuAssertTrue(tc, c->count == 1); + CuAssertTrue(tc, d->count == 3); + CuAssertTrue(tc, help->count == 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +CuSuite* get_arglit_testsuite() { + CuSuite* suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_arglit_basic_001); + SUITE_ADD_TEST(suite, test_arglit_basic_002); + SUITE_ADD_TEST(suite, test_arglit_basic_003); + SUITE_ADD_TEST(suite, test_arglit_basic_004); + SUITE_ADD_TEST(suite, test_arglit_basic_005); + SUITE_ADD_TEST(suite, test_arglit_basic_006); + SUITE_ADD_TEST(suite, test_arglit_basic_007); + SUITE_ADD_TEST(suite, test_arglit_basic_008); + SUITE_ADD_TEST(suite, test_arglit_basic_009); + SUITE_ADD_TEST(suite, test_arglit_basic_010); + SUITE_ADD_TEST(suite, test_arglit_basic_011); + SUITE_ADD_TEST(suite, test_arglit_basic_012); + SUITE_ADD_TEST(suite, test_arglit_basic_013); + SUITE_ADD_TEST(suite, test_arglit_basic_014); + SUITE_ADD_TEST(suite, test_arglit_basic_015); + SUITE_ADD_TEST(suite, test_arglit_basic_016); + SUITE_ADD_TEST(suite, test_arglit_basic_017); + return suite; +} + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif diff --git a/c/utf8filenamecheck/windows/argtable/tests/testargrex.c b/c/utf8filenamecheck/windows/argtable/tests/testargrex.c new file mode 100644 index 0000000..8d846b7 --- /dev/null +++ b/c/utf8filenamecheck/windows/argtable/tests/testargrex.c @@ -0,0 +1,299 @@ +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 2013-2019 Tom G. Huang + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include + +#include "CuTest.h" +#include "argtable3.h" + +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4204) +#endif + +void test_argrex_basic_001(CuTest* tc) { + struct arg_rex* a = arg_rex0("a", NULL, "hello", NULL, 0, "blah blah"); + struct arg_rex* b = arg_rex1(NULL, "beta", "[Ww]orld", NULL, 0, "blah blah"); + struct arg_rex* c = arg_rexn(NULL, NULL, "goodbye", NULL, 1, 5, ARG_REX_ICASE, "blah blah"); + struct arg_rex* d = arg_rex0(NULL, NULL, "any.*", NULL, ARG_REX_ICASE, "blah blah"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, end}; + int nerrors; + + char* argv[] = {"program", "--beta", "world", "goodbye", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + CuAssertTrue(tc, nerrors == 0); + + CuAssertTrue(tc, a->count == 0); + CuAssertTrue(tc, b->count == 1); + CuAssertStrEquals(tc, b->sval[0], "world"); + CuAssertTrue(tc, c->count == 1); + CuAssertStrEquals(tc, c->sval[0], "goodbye"); + CuAssertTrue(tc, d->count == 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argrex_basic_002(CuTest* tc) { + struct arg_rex* a = arg_rex0("a", NULL, "hello", NULL, 0, "blah blah"); + struct arg_rex* b = arg_rex1(NULL, "beta", "[Ww]orld", NULL, 0, "blah blah"); + struct arg_rex* c = arg_rexn(NULL, NULL, "goodbye", NULL, 1, 5, ARG_REX_ICASE, "blah blah"); + struct arg_rex* d = arg_rex0(NULL, NULL, "any.*", NULL, ARG_REX_ICASE, "blah blah"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, end}; + int nerrors; + + char* argv[] = {"program", "GoodBye", "--beta", "World", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + CuAssertTrue(tc, nerrors == 0); + + CuAssertTrue(tc, a->count == 0); + CuAssertTrue(tc, b->count == 1); + CuAssertStrEquals(tc, b->sval[0], "World"); + CuAssertTrue(tc, c->count == 1); + CuAssertStrEquals(tc, c->sval[0], "GoodBye"); + CuAssertTrue(tc, d->count == 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argrex_basic_003(CuTest* tc) { + struct arg_rex* a = arg_rex0("a", NULL, "hello", NULL, 0, "blah blah"); + struct arg_rex* b = arg_rex1(NULL, "beta", "[Ww]orld", NULL, 0, "blah blah"); + struct arg_rex* c = arg_rexn(NULL, NULL, "goodbye", NULL, 1, 5, ARG_REX_ICASE, "blah blah"); + struct arg_rex* d = arg_rex0(NULL, NULL, "any.*", NULL, ARG_REX_ICASE, "blah blah"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, end}; + int nerrors; + + char* argv[] = {"program", "--beta", "world", "GOODBYE", "GoodBye", "gOoDbyE", "Anything", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + CuAssertTrue(tc, nerrors == 0); + + CuAssertTrue(tc, a->count == 0); + CuAssertTrue(tc, b->count == 1); + CuAssertStrEquals(tc, b->sval[0], "world"); + CuAssertTrue(tc, c->count == 3); + CuAssertStrEquals(tc, c->sval[0], "GOODBYE"); + CuAssertStrEquals(tc, c->sval[1], "GoodBye"); + CuAssertStrEquals(tc, c->sval[2], "gOoDbyE"); + CuAssertTrue(tc, d->count == 1); + CuAssertStrEquals(tc, d->sval[0], "Anything"); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argrex_basic_004(CuTest* tc) { + struct arg_rex* a = arg_rex0("a", NULL, "hello", NULL, 0, "blah blah"); + struct arg_rex* b = arg_rex1(NULL, "beta", "[Ww]orld", NULL, 0, "blah blah"); + struct arg_rex* c = arg_rexn(NULL, NULL, "goodbye", NULL, 1, 5, ARG_REX_ICASE, "blah blah"); + struct arg_rex* d = arg_rex0(NULL, NULL, "any.*", NULL, ARG_REX_ICASE, "blah blah"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, end}; + int nerrors; + + char* argv[] = {"program", "--beta", "world", "GOODBYE", "AnyHow", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + CuAssertTrue(tc, nerrors == 0); + + CuAssertTrue(tc, a->count == 0); + CuAssertTrue(tc, b->count == 1); + CuAssertStrEquals(tc, b->sval[0], "world"); + CuAssertTrue(tc, c->count == 1); + CuAssertStrEquals(tc, c->sval[0], "GOODBYE"); + CuAssertTrue(tc, d->count == 1); + CuAssertStrEquals(tc, d->sval[0], "AnyHow"); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argrex_basic_005(CuTest* tc) { + struct arg_rex* a = arg_rex0("a", NULL, "hello", NULL, 0, "blah blah"); + struct arg_rex* b = arg_rex1(NULL, "beta", "[Ww]orld", NULL, 0, "blah blah"); + struct arg_rex* c = arg_rexn(NULL, NULL, "goodbye", NULL, 1, 5, ARG_REX_ICASE, "blah blah"); + struct arg_rex* d = arg_rex0(NULL, NULL, "any.*", NULL, ARG_REX_ICASE, "blah blah"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, end}; + int nerrors; + + char* argv[] = {"program", "-a", "hello", "--beta", "world", "GOODBYE", "AnyHow", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + CuAssertTrue(tc, nerrors == 0); + + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->sval[0], "hello"); + CuAssertTrue(tc, b->count == 1); + CuAssertStrEquals(tc, b->sval[0], "world"); + CuAssertTrue(tc, c->count == 1); + CuAssertStrEquals(tc, c->sval[0], "GOODBYE"); + CuAssertTrue(tc, d->count == 1); + CuAssertStrEquals(tc, d->sval[0], "AnyHow"); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argrex_basic_006(CuTest* tc) { + struct arg_rex* a = arg_rex0("a", NULL, "hello", NULL, 0, "blah blah"); + struct arg_rex* b = arg_rex1(NULL, "beta", "[Ww]orld", NULL, 0, "blah blah"); + struct arg_rex* c = arg_rexn(NULL, NULL, "goodbye", NULL, 1, 5, ARG_REX_ICASE, "blah blah"); + struct arg_rex* d = arg_rex0(NULL, NULL, "any.*", NULL, ARG_REX_ICASE, "blah blah"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, end}; + int nerrors; + + char* argv[] = {"program", "--beta", "WORLD", "goodbye", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + CuAssertTrue(tc, nerrors == 1); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argrex_basic_007(CuTest* tc) { + struct arg_rex* a = arg_rex0("a", NULL, "hello", NULL, 0, "blah blah"); + struct arg_rex* b = arg_rex1(NULL, "beta", "[Ww]orld", NULL, 0, "blah blah"); + struct arg_rex* c = arg_rexn(NULL, NULL, "goodbye", NULL, 1, 5, ARG_REX_ICASE, "blah blah"); + struct arg_rex* d = arg_rex0(NULL, NULL, "any.*", NULL, ARG_REX_ICASE, "blah blah"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, end}; + int nerrors; + + char* argv[] = {"program", "--beta", "World", "goodby", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + CuAssertTrue(tc, nerrors == 1); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argrex_basic_008(CuTest* tc) { + struct arg_rex* a = arg_rex0("a", NULL, "hello", NULL, 0, "blah blah"); + struct arg_rex* b = arg_rex1(NULL, "beta", "[Ww]orld", NULL, 0, "blah blah"); + struct arg_rex* c = arg_rexn(NULL, NULL, "goodbye", NULL, 1, 5, ARG_REX_ICASE, "blah blah"); + struct arg_rex* d = arg_rex0(NULL, NULL, "any.*", NULL, ARG_REX_ICASE, "blah blah"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, end}; + int nerrors; + + char* argv[] = {"program", "--beta", "world", "GoodBye", "Goodbye", "gOoDbyE", "Anything", "goodbye", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + CuAssertTrue(tc, nerrors == 1); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argrex_basic_009(CuTest* tc) { + struct arg_rex* a = arg_rex0("a", NULL, "hello", NULL, 0, "blah blah"); + struct arg_rex* b = arg_rex1(NULL, "beta", "[Ww]orld", NULL, 0, "blah blah"); + struct arg_rex* c = arg_rexn(NULL, NULL, "goodbye", NULL, 1, 5, ARG_REX_ICASE, "blah blah"); + struct arg_rex* d = arg_rex0(NULL, NULL, "any.*", NULL, ARG_REX_ICASE, "blah blah"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, end}; + int nerrors; + + char* argv[] = {"program", "--beta", "world", "GoodBye", "Goodbye", "gOoDbyE", "Anything", "Anytime", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + CuAssertTrue(tc, nerrors == 1); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argrex_basic_010(CuTest* tc) { + struct arg_rex* a = arg_rex0("a", NULL, "hello", NULL, 0, "blah blah"); + struct arg_rex* b = arg_rex1(NULL, "beta", "[Ww]orld", NULL, 0, "blah blah"); + struct arg_rex* c = arg_rexn(NULL, NULL, "goodbye", NULL, 1, 5, ARG_REX_ICASE, "blah blah"); + struct arg_rex* d = arg_rex0(NULL, NULL, "any.*", NULL, ARG_REX_ICASE, "blah blah"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, end}; + int nerrors; + + char* argv[] = {"program", "--beta", "world", "GoodBye", "Goodbye", "Anything", "-a", "Hello", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + CuAssertTrue(tc, nerrors == 1); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +CuSuite* get_argrex_testsuite() { + CuSuite* suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_argrex_basic_001); + SUITE_ADD_TEST(suite, test_argrex_basic_002); + SUITE_ADD_TEST(suite, test_argrex_basic_003); + SUITE_ADD_TEST(suite, test_argrex_basic_004); + SUITE_ADD_TEST(suite, test_argrex_basic_005); + SUITE_ADD_TEST(suite, test_argrex_basic_006); + SUITE_ADD_TEST(suite, test_argrex_basic_007); + SUITE_ADD_TEST(suite, test_argrex_basic_008); + SUITE_ADD_TEST(suite, test_argrex_basic_009); + SUITE_ADD_TEST(suite, test_argrex_basic_010); + return suite; +} + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif diff --git a/c/utf8filenamecheck/windows/argtable/tests/testargstr.c b/c/utf8filenamecheck/windows/argtable/tests/testargstr.c new file mode 100644 index 0000000..ac2e088 --- /dev/null +++ b/c/utf8filenamecheck/windows/argtable/tests/testargstr.c @@ -0,0 +1,531 @@ +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 2013-2019 Tom G. Huang + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include + +#include "CuTest.h" +#include "argtable3.h" + +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4204) +#endif + +void test_argstr_basic_001(CuTest* tc) { + struct arg_str* a = arg_str0(NULL, "hello,world", "STRVAL", "either --hello or --world or none"); + struct arg_str* b = arg_str0("bB", NULL, "STRVAL", "either -b or -B or none"); + struct arg_str* c = arg_str1("cC", NULL, "STRVAL", "either -c or -C"); + struct arg_str* d = arg_strn("dD", "delta", "STRVAL", 2, 4, "-d|-D|--delta 2..4 occurences"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, end}; + int nerrors; + + char* argv[] = {"program", "--hello=string1", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 2); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->sval[0], "string1"); + CuAssertTrue(tc, b->count == 0); + CuAssertTrue(tc, c->count == 0); + CuAssertTrue(tc, d->count == 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argstr_basic_002(CuTest* tc) { + struct arg_str* a = arg_str0(NULL, "hello,world", "STRVAL", "either --hello or --world or none"); + struct arg_str* b = arg_str0("bB", NULL, "STRVAL", "either -b or -B or none"); + struct arg_str* c = arg_str1("cC", NULL, "STRVAL", "either -c or -C"); + struct arg_str* d = arg_strn("dD", "delta", "STRVAL", 2, 4, "-d|-D|--delta 2..4 occurences"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, end}; + int nerrors; + + char* argv[] = {"program", "-cstring1", "-Dstring2", "-dstring3", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + if (nerrors > 0) + arg_print_errors(stdout, end, argv[0]); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 0); + CuAssertTrue(tc, b->count == 0); + CuAssertTrue(tc, c->count == 1); + CuAssertStrEquals(tc, c->sval[0], "string1"); + CuAssertTrue(tc, d->count == 2); + CuAssertStrEquals(tc, d->sval[0], "string2"); + CuAssertStrEquals(tc, d->sval[1], "string3"); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argstr_basic_003(CuTest* tc) { + struct arg_str* a = arg_str0(NULL, "hello,world", "STRVAL", "either --hello or --world or none"); + struct arg_str* b = arg_str0("bB", NULL, "STRVAL", "either -b or -B or none"); + struct arg_str* c = arg_str1("cC", NULL, "STRVAL", "either -c or -C"); + struct arg_str* d = arg_strn("dD", "delta", "STRVAL", 2, 4, "-d|-D|--delta 2..4 occurences"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, end}; + int nerrors; + + char* argv[] = {"program", "-Cstring1", "--delta=string2", "--delta=string3", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + if (nerrors > 0) + arg_print_errors(stdout, end, argv[0]); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 0); + CuAssertTrue(tc, b->count == 0); + CuAssertTrue(tc, c->count == 1); + CuAssertStrEquals(tc, c->sval[0], "string1"); + CuAssertTrue(tc, d->count == 2); + CuAssertStrEquals(tc, d->sval[0], "string2"); + CuAssertStrEquals(tc, d->sval[1], "string3"); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argstr_basic_004(CuTest* tc) { + struct arg_str* a = arg_str0(NULL, "hello,world", "STRVAL", "either --hello or --world or none"); + struct arg_str* b = arg_str0("bB", NULL, "STRVAL", "either -b or -B or none"); + struct arg_str* c = arg_str1("cC", NULL, "STRVAL", "either -c or -C"); + struct arg_str* d = arg_strn("dD", "delta", "STRVAL", 2, 4, "-d|-D|--delta 2..4 occurences"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, end}; + int nerrors; + + char* argv[] = {"program", "--delta=string1", "-cstring2", "-Dstring3", "-bstring4", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + if (nerrors > 0) + arg_print_errors(stdout, end, argv[0]); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 0); + CuAssertTrue(tc, b->count == 1); + CuAssertStrEquals(tc, b->sval[0], "string4"); + CuAssertTrue(tc, c->count == 1); + CuAssertStrEquals(tc, c->sval[0], "string2"); + CuAssertTrue(tc, d->count == 2); + CuAssertStrEquals(tc, d->sval[0], "string1"); + CuAssertStrEquals(tc, d->sval[1], "string3"); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argstr_basic_005(CuTest* tc) { + struct arg_str* a = arg_str0(NULL, "hello,world", "STRVAL", "either --hello or --world or none"); + struct arg_str* b = arg_str0("bB", NULL, "STRVAL", "either -b or -B or none"); + struct arg_str* c = arg_str1("cC", NULL, "STRVAL", "either -c or -C"); + struct arg_str* d = arg_strn("dD", "delta", "STRVAL", 2, 4, "-d|-D|--delta 2..4 occurences"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, end}; + int nerrors; + + char* argv[] = {"program", "-Dstring1", "-Bstring2", "--delta=string3", "-Cstring4", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + if (nerrors > 0) + arg_print_errors(stdout, end, argv[0]); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 0); + CuAssertTrue(tc, b->count == 1); + CuAssertStrEquals(tc, b->sval[0], "string2"); + CuAssertTrue(tc, c->count == 1); + CuAssertStrEquals(tc, c->sval[0], "string4"); + CuAssertTrue(tc, d->count == 2); + CuAssertStrEquals(tc, d->sval[0], "string1"); + CuAssertStrEquals(tc, d->sval[1], "string3"); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argstr_basic_006(CuTest* tc) { + struct arg_str* a = arg_str0(NULL, "hello,world", "STRVAL", "either --hello or --world or none"); + struct arg_str* b = arg_str0("bB", NULL, "STRVAL", "either -b or -B or none"); + struct arg_str* c = arg_str1("cC", NULL, "STRVAL", "either -c or -C"); + struct arg_str* d = arg_strn("dD", "delta", "STRVAL", 2, 4, "-d|-D|--delta 2..4 occurences"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, end}; + int nerrors; + + char* argv[] = {"program", "-Dstring1", "-Bstring2", "--delta=string3", "-Cstring4", "--hello=string5", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + if (nerrors > 0) + arg_print_errors(stdout, end, argv[0]); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->sval[0], "string5"); + CuAssertTrue(tc, b->count == 1); + CuAssertStrEquals(tc, b->sval[0], "string2"); + CuAssertTrue(tc, c->count == 1); + CuAssertStrEquals(tc, c->sval[0], "string4"); + CuAssertTrue(tc, d->count == 2); + CuAssertStrEquals(tc, d->sval[0], "string1"); + CuAssertStrEquals(tc, d->sval[1], "string3"); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argstr_basic_007(CuTest* tc) { + struct arg_str* a = arg_str0(NULL, "hello,world", "STRVAL", "either --hello or --world or none"); + struct arg_str* b = arg_str0("bB", NULL, "STRVAL", "either -b or -B or none"); + struct arg_str* c = arg_str1("cC", NULL, "STRVAL", "either -c or -C"); + struct arg_str* d = arg_strn("dD", "delta", "STRVAL", 2, 4, "-d|-D|--delta 2..4 occurences"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, end}; + int nerrors; + + char* argv[] = {"program", "-Dstring1", "-Bstring2", "--delta=string3", "-Cstring4", "--world=string5", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + if (nerrors > 0) + arg_print_errors(stdout, end, argv[0]); + + CuAssertTrue(tc, nerrors == 0); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->sval[0], "string5"); + CuAssertTrue(tc, b->count == 1); + CuAssertStrEquals(tc, b->sval[0], "string2"); + CuAssertTrue(tc, c->count == 1); + CuAssertStrEquals(tc, c->sval[0], "string4"); + CuAssertTrue(tc, d->count == 2); + CuAssertStrEquals(tc, d->sval[0], "string1"); + CuAssertStrEquals(tc, d->sval[1], "string3"); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argstr_basic_008(CuTest* tc) { + struct arg_str* a = arg_str0(NULL, "hello,world", "STRVAL", "either --hello or --world or none"); + struct arg_str* b = arg_str0("bB", NULL, "STRVAL", "either -b or -B or none"); + struct arg_str* c = arg_str1("cC", NULL, "STRVAL", "either -c or -C"); + struct arg_str* d = arg_strn("dD", "delta", "STRVAL", 2, 4, "-d|-D|--delta 2..4 occurences"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, end}; + int nerrors; + + char* argv[] = {"program", "-cstring1", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 1); + CuAssertTrue(tc, a->count == 0); + CuAssertTrue(tc, b->count == 0); + CuAssertTrue(tc, c->count == 1); + CuAssertStrEquals(tc, c->sval[0], "string1"); + CuAssertTrue(tc, d->count == 0); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argstr_basic_009(CuTest* tc) { + struct arg_str* a = arg_str0(NULL, "hello,world", "STRVAL", "either --hello or --world or none"); + struct arg_str* b = arg_str0("bB", NULL, "STRVAL", "either -b or -B or none"); + struct arg_str* c = arg_str1("cC", NULL, "STRVAL", "either -c or -C"); + struct arg_str* d = arg_strn("dD", "delta", "STRVAL", 2, 4, "-d|-D|--delta 2..4 occurences"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, end}; + int nerrors; + + char* argv[] = {"program", "-Dstring1", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 2); + CuAssertTrue(tc, a->count == 0); + CuAssertTrue(tc, b->count == 0); + CuAssertTrue(tc, c->count == 0); + CuAssertTrue(tc, d->count == 1); + CuAssertStrEquals(tc, d->sval[0], "string1"); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argstr_basic_010(CuTest* tc) { + struct arg_str* a = arg_str0(NULL, "hello,world", "STRVAL", "either --hello or --world or none"); + struct arg_str* b = arg_str0("bB", NULL, "STRVAL", "either -b or -B or none"); + struct arg_str* c = arg_str1("cC", NULL, "STRVAL", "either -c or -C"); + struct arg_str* d = arg_strn("dD", "delta", "STRVAL", 2, 4, "-d|-D|--delta 2..4 occurences"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, end}; + int nerrors; + + char* argv[] = {"program", "-Cstring1", "-Dstring2", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 1); + CuAssertTrue(tc, a->count == 0); + CuAssertTrue(tc, b->count == 0); + CuAssertTrue(tc, c->count == 1); + CuAssertStrEquals(tc, c->sval[0], "string1"); + CuAssertTrue(tc, d->count == 1); + CuAssertStrEquals(tc, d->sval[0], "string2"); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argstr_basic_011(CuTest* tc) { + struct arg_str* a = arg_str0(NULL, "hello,world", "STRVAL", "either --hello or --world or none"); + struct arg_str* b = arg_str0("bB", NULL, "STRVAL", "either -b or -B or none"); + struct arg_str* c = arg_str1("cC", NULL, "STRVAL", "either -c or -C"); + struct arg_str* d = arg_strn("dD", "delta", "STRVAL", 2, 4, "-d|-D|--delta 2..4 occurences"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, end}; + int nerrors; + + char* argv[] = {"program", "-Dstring1", "-dstring2", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 1); + CuAssertTrue(tc, a->count == 0); + CuAssertTrue(tc, b->count == 0); + CuAssertTrue(tc, c->count == 0); + CuAssertTrue(tc, d->count == 2); + CuAssertStrEquals(tc, d->sval[0], "string1"); + CuAssertStrEquals(tc, d->sval[1], "string2"); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argstr_basic_012(CuTest* tc) { + struct arg_str* a = arg_str0(NULL, "hello,world", "STRVAL", "either --hello or --world or none"); + struct arg_str* b = arg_str0("bB", NULL, "STRVAL", "either -b or -B or none"); + struct arg_str* c = arg_str1("cC", NULL, "STRVAL", "either -c or -C"); + struct arg_str* d = arg_strn("dD", "delta", "STRVAL", 2, 4, "-d|-D|--delta 2..4 occurences"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, end}; + int nerrors; + + char* argv[] = {"program", "-cs1", "-ds2", "-ds3", "-ds4", "-ds5", "-ds6", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 1); + CuAssertTrue(tc, a->count == 0); + CuAssertTrue(tc, b->count == 0); + CuAssertTrue(tc, c->count == 1); + CuAssertStrEquals(tc, c->sval[0], "s1"); + CuAssertTrue(tc, d->count == 4); + CuAssertStrEquals(tc, d->sval[0], "s2"); + CuAssertStrEquals(tc, d->sval[1], "s3"); + CuAssertStrEquals(tc, d->sval[2], "s4"); + CuAssertStrEquals(tc, d->sval[3], "s5"); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argstr_basic_013(CuTest* tc) { + struct arg_str* a = arg_str0(NULL, "hello,world", "STRVAL", "either --hello or --world or none"); + struct arg_str* b = arg_str0("bB", NULL, "STRVAL", "either -b or -B or none"); + struct arg_str* c = arg_str1("cC", NULL, "STRVAL", "either -c or -C"); + struct arg_str* d = arg_strn("dD", "delta", "STRVAL", 2, 4, "-d|-D|--delta 2..4 occurences"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, end}; + int nerrors; + + char* argv[] = {"program", "-cs1", "-cs2", "-ds3", "-ds4", "-ds5", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 1); + CuAssertTrue(tc, a->count == 0); + CuAssertTrue(tc, b->count == 0); + CuAssertTrue(tc, c->count == 1); + CuAssertStrEquals(tc, c->sval[0], "s1"); + CuAssertTrue(tc, d->count == 3); + CuAssertStrEquals(tc, d->sval[0], "s3"); + CuAssertStrEquals(tc, d->sval[1], "s4"); + CuAssertStrEquals(tc, d->sval[2], "s5"); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argstr_basic_014(CuTest* tc) { + struct arg_str* a = arg_str0(NULL, "hello,world", "STRVAL", "either --hello or --world or none"); + struct arg_str* b = arg_str0("bB", NULL, "STRVAL", "either -b or -B or none"); + struct arg_str* c = arg_str1("cC", NULL, "STRVAL", "either -c or -C"); + struct arg_str* d = arg_strn("dD", "delta", "STRVAL", 2, 4, "-d|-D|--delta 2..4 occurences"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, end}; + int nerrors; + + char* argv[] = {"program", "-Cs1", "-ds2", "-Ds3", "--delta=s4", "-bs5", "-Bs6", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 1); + CuAssertTrue(tc, a->count == 0); + CuAssertTrue(tc, b->count == 1); + CuAssertStrEquals(tc, b->sval[0], "s5"); + CuAssertTrue(tc, c->count == 1); + CuAssertStrEquals(tc, c->sval[0], "s1"); + CuAssertTrue(tc, d->count == 3); + CuAssertStrEquals(tc, d->sval[0], "s2"); + CuAssertStrEquals(tc, d->sval[1], "s3"); + CuAssertStrEquals(tc, d->sval[2], "s4"); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argstr_basic_015(CuTest* tc) { + struct arg_str* a = arg_str0(NULL, "hello,world", "STRVAL", "either --hello or --world or none"); + struct arg_str* b = arg_str0("bB", NULL, "STRVAL", "either -b or -B or none"); + struct arg_str* c = arg_str1("cC", NULL, "STRVAL", "either -c or -C"); + struct arg_str* d = arg_strn("dD", "delta", "STRVAL", 2, 4, "-d|-D|--delta 2..4 occurences"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, end}; + int nerrors; + + char* argv[] = {"program", "-Cs1", "-ds2", "-Ds3", "--delta=s4", "--hello=s5", "--world=s6", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 1); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->sval[0], "s5"); + CuAssertTrue(tc, b->count == 0); + CuAssertTrue(tc, c->count == 1); + CuAssertStrEquals(tc, c->sval[0], "s1"); + CuAssertTrue(tc, d->count == 3); + CuAssertStrEquals(tc, d->sval[0], "s2"); + CuAssertStrEquals(tc, d->sval[1], "s3"); + CuAssertStrEquals(tc, d->sval[2], "s4"); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +void test_argstr_basic_016(CuTest* tc) { + struct arg_str* a = arg_str0(NULL, "hello,world", "STRVAL", "either --hello or --world or none"); + struct arg_str* b = arg_str0("bB", NULL, "STRVAL", "either -b or -B or none"); + struct arg_str* c = arg_str1("cC", NULL, "STRVAL", "either -c or -C"); + struct arg_str* d = arg_strn("dD", "delta", "STRVAL", 2, 4, "-d|-D|--delta 2..4 occurences"); + struct arg_end* end = arg_end(20); + void* argtable[] = {a, b, c, d, end}; + int nerrors; + + char* argv[] = {"program", "-Cs1", "-ds2", "-Ds3", "--delta=s4", "--hello=s5", "X", NULL}; + int argc = sizeof(argv) / sizeof(char*) - 1; + + CuAssertTrue(tc, arg_nullcheck(argtable) == 0); + + nerrors = arg_parse(argc, argv, argtable); + + CuAssertTrue(tc, nerrors == 1); + CuAssertTrue(tc, a->count == 1); + CuAssertStrEquals(tc, a->sval[0], "s5"); + CuAssertTrue(tc, b->count == 0); + CuAssertTrue(tc, c->count == 1); + CuAssertStrEquals(tc, c->sval[0], "s1"); + CuAssertTrue(tc, d->count == 3); + CuAssertStrEquals(tc, d->sval[0], "s2"); + CuAssertStrEquals(tc, d->sval[1], "s3"); + CuAssertStrEquals(tc, d->sval[2], "s4"); + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); +} + +CuSuite* get_argstr_testsuite() { + CuSuite* suite = CuSuiteNew(); + SUITE_ADD_TEST(suite, test_argstr_basic_001); + SUITE_ADD_TEST(suite, test_argstr_basic_002); + SUITE_ADD_TEST(suite, test_argstr_basic_003); + SUITE_ADD_TEST(suite, test_argstr_basic_004); + SUITE_ADD_TEST(suite, test_argstr_basic_005); + SUITE_ADD_TEST(suite, test_argstr_basic_006); + SUITE_ADD_TEST(suite, test_argstr_basic_007); + SUITE_ADD_TEST(suite, test_argstr_basic_008); + SUITE_ADD_TEST(suite, test_argstr_basic_009); + SUITE_ADD_TEST(suite, test_argstr_basic_010); + SUITE_ADD_TEST(suite, test_argstr_basic_011); + SUITE_ADD_TEST(suite, test_argstr_basic_012); + SUITE_ADD_TEST(suite, test_argstr_basic_013); + SUITE_ADD_TEST(suite, test_argstr_basic_014); + SUITE_ADD_TEST(suite, test_argstr_basic_015); + SUITE_ADD_TEST(suite, test_argstr_basic_016); + return suite; +} + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif diff --git a/c/utf8filenamecheck/windows/bin/utf8filenamecheck.exe b/c/utf8filenamecheck/windows/bin/utf8filenamecheck.exe new file mode 100644 index 0000000000000000000000000000000000000000..fa2ab2e4666c8a5ff7e449bcdce1c3fddef7a31d GIT binary patch literal 591589 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%0D7q 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

DEKj7j`!$O){K<$N{5XC1HPk*28=s>SkArv! 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 z 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 literal 0 HcmV?d00001 diff --git a/c/utf8filenamecheck/windows/makefile.bat b/c/utf8filenamecheck/windows/makefile.bat new file mode 100644 index 0000000..a67a3c8 --- /dev/null +++ b/c/utf8filenamecheck/windows/makefile.bat @@ -0,0 +1,18 @@ +:: utf8filenamecheck Check if all the filenames in a fiven folder are UTF-8 +:: Copyright (C) 2023 Johannes 'Banana' Keßler +:: +:: 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 3 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, see . +@echo off +cls +gcc -std=c99 -march=native -O3 -Wall -Iargtable/ -Isimdutf8check/ utf8filenamecheck.c argtable/argtable3.c -o bin/utf8filenamecheck.exe \ No newline at end of file diff --git a/c/utf8filenamecheck/windows/notes.txt b/c/utf8filenamecheck/windows/notes.txt new file mode 100644 index 0000000..6304e04 --- /dev/null +++ b/c/utf8filenamecheck/windows/notes.txt @@ -0,0 +1,5 @@ +https://github.com/adamretter/utf8-validator-c +https://stackoverflow.com/questions/1301402/example-invalid-utf8-string + +https://codeforwin.org/c-programming/c-program-to-list-all-files-in-a-directory-recursively +https://man7.org/linux/man-pages/man3/nftw.3.html \ No newline at end of file diff --git a/c/utf8filenamecheck/windows/simdutf8check/simdutf8check.h b/c/utf8filenamecheck/windows/simdutf8check/simdutf8check.h new file mode 100644 index 0000000..7644bfa --- /dev/null +++ b/c/utf8filenamecheck/windows/simdutf8check/simdutf8check.h @@ -0,0 +1,457 @@ +#ifndef SIMDUTF8CHECK_H +#define SIMDUTF8CHECK_H +#include +#include +#include +#include +#include +/* + * legal utf-8 byte sequence + * http://www.unicode.org/versions/Unicode6.0.0/ch03.pdf - page 94 + * + * Code Points 1st 2s 3s 4s + * U+0000..U+007F 00..7F + * U+0080..U+07FF C2..DF 80..BF + * U+0800..U+0FFF E0 A0..BF 80..BF + * U+1000..U+CFFF E1..EC 80..BF 80..BF + * U+D000..U+D7FF ED 80..9F 80..BF + * U+E000..U+FFFF EE..EF 80..BF 80..BF + * U+10000..U+3FFFF F0 90..BF 80..BF 80..BF + * U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF + * U+100000..U+10FFFF F4 80..8F 80..BF 80..BF + * + */ + +// all byte values must be no larger than 0xF4 +static inline void checkSmallerThan0xF4(__m128i current_bytes, + __m128i *has_error) { + // unsigned, saturates to 0 below max + *has_error = _mm_or_si128(*has_error, + _mm_subs_epu8(current_bytes, _mm_set1_epi8(0xF4))); +} + +static inline __m128i continuationLengths(__m128i high_nibbles) { + return _mm_shuffle_epi8( + _mm_setr_epi8(1, 1, 1, 1, 1, 1, 1, 1, // 0xxx (ASCII) + 0, 0, 0, 0, // 10xx (continuation) + 2, 2, // 110x + 3, // 1110 + 4), // 1111, next should be 0 (not checked here) + high_nibbles); +} + +static inline __m128i carryContinuations(__m128i initial_lengths, + __m128i previous_carries) { + + __m128i right1 = + _mm_subs_epu8(_mm_alignr_epi8(initial_lengths, previous_carries, 16 - 1), + _mm_set1_epi8(1)); + __m128i sum = _mm_add_epi8(initial_lengths, right1); + + __m128i right2 = _mm_subs_epu8(_mm_alignr_epi8(sum, previous_carries, 16 - 2), + _mm_set1_epi8(2)); + return _mm_add_epi8(sum, right2); +} + +static inline void checkContinuations(__m128i initial_lengths, __m128i carries, + __m128i *has_error) { + + // overlap || underlap + // carry > length && length > 0 || !(carry > length) && !(length > 0) + // (carries > length) == (lengths > 0) + __m128i overunder = + _mm_cmpeq_epi8(_mm_cmpgt_epi8(carries, initial_lengths), + _mm_cmpgt_epi8(initial_lengths, _mm_setzero_si128())); + + *has_error = _mm_or_si128(*has_error, overunder); +} + +// when 0xED is found, next byte must be no larger than 0x9F +// when 0xF4 is found, next byte must be no larger than 0x8F +// next byte must be continuation, ie sign bit is set, so signed < is ok +static inline void checkFirstContinuationMax(__m128i current_bytes, + __m128i off1_current_bytes, + __m128i *has_error) { + __m128i maskED = _mm_cmpeq_epi8(off1_current_bytes, _mm_set1_epi8(0xED)); + __m128i maskF4 = _mm_cmpeq_epi8(off1_current_bytes, _mm_set1_epi8(0xF4)); + + __m128i badfollowED = + _mm_and_si128(_mm_cmpgt_epi8(current_bytes, _mm_set1_epi8(0x9F)), maskED); + __m128i badfollowF4 = + _mm_and_si128(_mm_cmpgt_epi8(current_bytes, _mm_set1_epi8(0x8F)), maskF4); + + *has_error = _mm_or_si128(*has_error, _mm_or_si128(badfollowED, badfollowF4)); +} + +// map off1_hibits => error condition +// hibits off1 cur +// C => < C2 && true +// E => < E1 && < A0 +// F => < F1 && < 90 +// else false && false +static inline void checkOverlong(__m128i current_bytes, + __m128i off1_current_bytes, __m128i hibits, + __m128i previous_hibits, __m128i *has_error) { + __m128i off1_hibits = _mm_alignr_epi8(hibits, previous_hibits, 16 - 1); + __m128i initial_mins = _mm_shuffle_epi8( + _mm_setr_epi8(-128, -128, -128, -128, -128, -128, -128, -128, -128, -128, + -128, -128, // 10xx => false + 0xC2, -128, // 110x + 0xE1, // 1110 + 0xF1), + off1_hibits); + + __m128i initial_under = _mm_cmpgt_epi8(initial_mins, off1_current_bytes); + + __m128i second_mins = _mm_shuffle_epi8( + _mm_setr_epi8(-128, -128, -128, -128, -128, -128, -128, -128, -128, -128, + -128, -128, // 10xx => false + 127, 127, // 110x => true + 0xA0, // 1110 + 0x90), + off1_hibits); + __m128i second_under = _mm_cmpgt_epi8(second_mins, current_bytes); + *has_error = + _mm_or_si128(*has_error, _mm_and_si128(initial_under, second_under)); +} + +struct processed_utf_bytes { + __m128i rawbytes; + __m128i high_nibbles; + __m128i carried_continuations; +}; + +static inline void count_nibbles(__m128i bytes, + struct processed_utf_bytes *answer) { + answer->rawbytes = bytes; + answer->high_nibbles = + _mm_and_si128(_mm_srli_epi16(bytes, 4), _mm_set1_epi8(0x0F)); +} + +// check whether the current bytes are valid UTF-8 +// at the end of the function, previous gets updated +static struct processed_utf_bytes +checkUTF8Bytes(__m128i current_bytes, struct processed_utf_bytes *previous, + __m128i *has_error) { + struct processed_utf_bytes pb; + count_nibbles(current_bytes, &pb); + + checkSmallerThan0xF4(current_bytes, has_error); + + __m128i initial_lengths = continuationLengths(pb.high_nibbles); + + pb.carried_continuations = + carryContinuations(initial_lengths, previous->carried_continuations); + + checkContinuations(initial_lengths, pb.carried_continuations, has_error); + + __m128i off1_current_bytes = + _mm_alignr_epi8(pb.rawbytes, previous->rawbytes, 16 - 1); + checkFirstContinuationMax(current_bytes, off1_current_bytes, has_error); + + checkOverlong(current_bytes, off1_current_bytes, pb.high_nibbles, + previous->high_nibbles, has_error); + return pb; +} + +static bool validate_utf8_fast(const char *src, size_t len) { + size_t i = 0; + __m128i has_error = _mm_setzero_si128(); + struct processed_utf_bytes previous = {.rawbytes = _mm_setzero_si128(), + .high_nibbles = _mm_setzero_si128(), + .carried_continuations = + _mm_setzero_si128()}; + if (len >= 16) { + for (; i <= len - 16; i += 16) { + __m128i current_bytes = _mm_loadu_si128((const __m128i *)(src + i)); + previous = checkUTF8Bytes(current_bytes, &previous, &has_error); + } + } + + // last part + if (i < len) { + char buffer[16]; + memset(buffer, 0, 16); + memcpy(buffer, src + i, len - i); + __m128i current_bytes = _mm_loadu_si128((const __m128i *)(buffer)); + previous = checkUTF8Bytes(current_bytes, &previous, &has_error); + } else { + has_error = + _mm_or_si128(_mm_cmpgt_epi8(previous.carried_continuations, + _mm_setr_epi8(9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 1)), + has_error); + } + + return _mm_testz_si128(has_error, has_error); +} + +#ifdef __AVX2__ + +/*****************************/ +static inline __m256i push_last_byte_of_a_to_b(__m256i a, __m256i b) { + return _mm256_alignr_epi8(b, _mm256_permute2x128_si256(a, b, 0x21), 15); +} + +static inline __m256i push_last_2bytes_of_a_to_b(__m256i a, __m256i b) { + return _mm256_alignr_epi8(b, _mm256_permute2x128_si256(a, b, 0x21), 14); +} + +// all byte values must be no larger than 0xF4 +static inline void avxcheckSmallerThan0xF4(__m256i current_bytes, + __m256i *has_error) { + // unsigned, saturates to 0 below max + *has_error = _mm256_or_si256( + *has_error, _mm256_subs_epu8(current_bytes, _mm256_set1_epi8(0xF4))); +} + +static inline __m256i avxcontinuationLengths(__m256i high_nibbles) { + return _mm256_shuffle_epi8( + _mm256_setr_epi8(1, 1, 1, 1, 1, 1, 1, 1, // 0xxx (ASCII) + 0, 0, 0, 0, // 10xx (continuation) + 2, 2, // 110x + 3, // 1110 + 4, // 1111, next should be 0 (not checked here) + 1, 1, 1, 1, 1, 1, 1, 1, // 0xxx (ASCII) + 0, 0, 0, 0, // 10xx (continuation) + 2, 2, // 110x + 3, // 1110 + 4 // 1111, next should be 0 (not checked here) + ), + high_nibbles); +} + +static inline __m256i avxcarryContinuations(__m256i initial_lengths, + __m256i previous_carries) { + + __m256i right1 = _mm256_subs_epu8( + push_last_byte_of_a_to_b(previous_carries, initial_lengths), + _mm256_set1_epi8(1)); + __m256i sum = _mm256_add_epi8(initial_lengths, right1); + + __m256i right2 = _mm256_subs_epu8( + push_last_2bytes_of_a_to_b(previous_carries, sum), _mm256_set1_epi8(2)); + return _mm256_add_epi8(sum, right2); +} + +static inline void avxcheckContinuations(__m256i initial_lengths, + __m256i carries, __m256i *has_error) { + + // overlap || underlap + // carry > length && length > 0 || !(carry > length) && !(length > 0) + // (carries > length) == (lengths > 0) + __m256i overunder = _mm256_cmpeq_epi8( + _mm256_cmpgt_epi8(carries, initial_lengths), + _mm256_cmpgt_epi8(initial_lengths, _mm256_setzero_si256())); + + *has_error = _mm256_or_si256(*has_error, overunder); +} + +// when 0xED is found, next byte must be no larger than 0x9F +// when 0xF4 is found, next byte must be no larger than 0x8F +// next byte must be continuation, ie sign bit is set, so signed < is ok +static inline void avxcheckFirstContinuationMax(__m256i current_bytes, + __m256i off1_current_bytes, + __m256i *has_error) { + __m256i maskED = + _mm256_cmpeq_epi8(off1_current_bytes, _mm256_set1_epi8(0xED)); + __m256i maskF4 = + _mm256_cmpeq_epi8(off1_current_bytes, _mm256_set1_epi8(0xF4)); + + __m256i badfollowED = _mm256_and_si256( + _mm256_cmpgt_epi8(current_bytes, _mm256_set1_epi8(0x9F)), maskED); + __m256i badfollowF4 = _mm256_and_si256( + _mm256_cmpgt_epi8(current_bytes, _mm256_set1_epi8(0x8F)), maskF4); + + *has_error = + _mm256_or_si256(*has_error, _mm256_or_si256(badfollowED, badfollowF4)); +} + +// map off1_hibits => error condition +// hibits off1 cur +// C => < C2 && true +// E => < E1 && < A0 +// F => < F1 && < 90 +// else false && false +static inline void avxcheckOverlong(__m256i current_bytes, + __m256i off1_current_bytes, __m256i hibits, + __m256i previous_hibits, + __m256i *has_error) { + __m256i off1_hibits = push_last_byte_of_a_to_b(previous_hibits, hibits); + __m256i initial_mins = _mm256_shuffle_epi8( + _mm256_setr_epi8(-128, -128, -128, -128, -128, -128, -128, -128, -128, + -128, -128, -128, // 10xx => false + 0xC2, -128, // 110x + 0xE1, // 1110 + 0xF1, -128, -128, -128, -128, -128, -128, -128, -128, + -128, -128, -128, -128, // 10xx => false + 0xC2, -128, // 110x + 0xE1, // 1110 + 0xF1), + off1_hibits); + + __m256i initial_under = _mm256_cmpgt_epi8(initial_mins, off1_current_bytes); + + __m256i second_mins = _mm256_shuffle_epi8( + _mm256_setr_epi8(-128, -128, -128, -128, -128, -128, -128, -128, -128, + -128, -128, -128, // 10xx => false + 127, 127, // 110x => true + 0xA0, // 1110 + 0x90, -128, -128, -128, -128, -128, -128, -128, -128, + -128, -128, -128, -128, // 10xx => false + 127, 127, // 110x => true + 0xA0, // 1110 + 0x90), + off1_hibits); + __m256i second_under = _mm256_cmpgt_epi8(second_mins, current_bytes); + *has_error = _mm256_or_si256(*has_error, + _mm256_and_si256(initial_under, second_under)); +} + +struct avx_processed_utf_bytes { + __m256i rawbytes; + __m256i high_nibbles; + __m256i carried_continuations; +}; + +static inline void avx_count_nibbles(__m256i bytes, + struct avx_processed_utf_bytes *answer) { + answer->rawbytes = bytes; + answer->high_nibbles = + _mm256_and_si256(_mm256_srli_epi16(bytes, 4), _mm256_set1_epi8(0x0F)); +} + +// check whether the current bytes are valid UTF-8 +// at the end of the function, previous gets updated +static struct avx_processed_utf_bytes +avxcheckUTF8Bytes(__m256i current_bytes, + struct avx_processed_utf_bytes *previous, + __m256i *has_error) { + struct avx_processed_utf_bytes pb; + avx_count_nibbles(current_bytes, &pb); + + avxcheckSmallerThan0xF4(current_bytes, has_error); + + __m256i initial_lengths = avxcontinuationLengths(pb.high_nibbles); + + pb.carried_continuations = + avxcarryContinuations(initial_lengths, previous->carried_continuations); + + avxcheckContinuations(initial_lengths, pb.carried_continuations, has_error); + + __m256i off1_current_bytes = + push_last_byte_of_a_to_b(previous->rawbytes, pb.rawbytes); + avxcheckFirstContinuationMax(current_bytes, off1_current_bytes, has_error); + + avxcheckOverlong(current_bytes, off1_current_bytes, pb.high_nibbles, + previous->high_nibbles, has_error); + return pb; +} + +// check whether the current bytes are valid UTF-8 +// at the end of the function, previous gets updated +static struct avx_processed_utf_bytes +avxcheckUTF8Bytes_asciipath(__m256i current_bytes, + struct avx_processed_utf_bytes *previous, + __m256i *has_error) { + if (_mm256_testz_si256(current_bytes, + _mm256_set1_epi8(0x80))) { // fast ascii path + *has_error = _mm256_or_si256( + _mm256_cmpgt_epi8(previous->carried_continuations, + _mm256_setr_epi8(9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 1)), + *has_error); + return *previous; + } + + struct avx_processed_utf_bytes pb; + avx_count_nibbles(current_bytes, &pb); + + avxcheckSmallerThan0xF4(current_bytes, has_error); + + __m256i initial_lengths = avxcontinuationLengths(pb.high_nibbles); + + pb.carried_continuations = + avxcarryContinuations(initial_lengths, previous->carried_continuations); + + avxcheckContinuations(initial_lengths, pb.carried_continuations, has_error); + + __m256i off1_current_bytes = + push_last_byte_of_a_to_b(previous->rawbytes, pb.rawbytes); + avxcheckFirstContinuationMax(current_bytes, off1_current_bytes, has_error); + + avxcheckOverlong(current_bytes, off1_current_bytes, pb.high_nibbles, + previous->high_nibbles, has_error); + return pb; +} + +static bool validate_utf8_fast_avx_asciipath(const char *src, size_t len) { + size_t i = 0; + __m256i has_error = _mm256_setzero_si256(); + struct avx_processed_utf_bytes previous = { + .rawbytes = _mm256_setzero_si256(), + .high_nibbles = _mm256_setzero_si256(), + .carried_continuations = _mm256_setzero_si256()}; + if (len >= 32) { + for (; i <= len - 32; i += 32) { + __m256i current_bytes = _mm256_loadu_si256((const __m256i *)(src + i)); + previous = + avxcheckUTF8Bytes_asciipath(current_bytes, &previous, &has_error); + } + } + + // last part + if (i < len) { + char buffer[32]; + memset(buffer, 0, 32); + memcpy(buffer, src + i, len - i); + __m256i current_bytes = _mm256_loadu_si256((const __m256i *)(buffer)); + previous = avxcheckUTF8Bytes(current_bytes, &previous, &has_error); + } else { + has_error = _mm256_or_si256( + _mm256_cmpgt_epi8(previous.carried_continuations, + _mm256_setr_epi8(9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 1)), + has_error); + } + + return _mm256_testz_si256(has_error, has_error); +} + +static bool validate_utf8_fast_avx(const char *src, size_t len) { + size_t i = 0; + __m256i has_error = _mm256_setzero_si256(); + struct avx_processed_utf_bytes previous = { + .rawbytes = _mm256_setzero_si256(), + .high_nibbles = _mm256_setzero_si256(), + .carried_continuations = _mm256_setzero_si256()}; + if (len >= 32) { + for (; i <= len - 32; i += 32) { + __m256i current_bytes = _mm256_loadu_si256((const __m256i *)(src + i)); + previous = avxcheckUTF8Bytes(current_bytes, &previous, &has_error); + } + } + + // last part + if (i < len) { + char buffer[32]; + memset(buffer, 0, 32); + memcpy(buffer, src + i, len - i); + __m256i current_bytes = _mm256_loadu_si256((const __m256i *)(buffer)); + previous = avxcheckUTF8Bytes(current_bytes, &previous, &has_error); + } else { + has_error = _mm256_or_si256( + _mm256_cmpgt_epi8(previous.carried_continuations, + _mm256_setr_epi8(9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 1)), + has_error); + } + + return _mm256_testz_si256(has_error, has_error); +} + +#endif // __AVX2__ +#endif diff --git a/c/utf8filenamecheck/windows/utf8filenamecheck.c b/c/utf8filenamecheck/windows/utf8filenamecheck.c new file mode 100644 index 0000000..764cc09 --- /dev/null +++ b/c/utf8filenamecheck/windows/utf8filenamecheck.c @@ -0,0 +1,147 @@ +/** + * utf8filenamecheck Check if all the filenames in a fiven folder are UTF-8 + * Copyright (C) 2023 Johannes 'Banana' Keßler + * + * 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 3 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, see . + */ + +/** + * 2023 Small windows C tool to check if paths in a folder are utf-8 formatted + * This is the windows version + */ + +#include +#include +#include +#include + +// https://linux.die.net/man/3/nftw +#define _XOPEN_SOURCE 500 +#include + +// https://www.argtable.org +#include + +// https://github.com/simdutf/simdutf +#include + +/** + * global arg_xxx structs + * https://www.argtable.org/ + */ +struct arg_lit *verbose, *quiet, *help; +struct arg_file *folderToRead; +struct arg_end *end; +const char *program_version = "1.0"; +const char *program_bug_address = "https://://www.bananas-playground.net"; + +struct cmdArguments { + int quiet, verbose; + char *folder_to_read; +}; + +struct cmdArguments arguments; + +/** + * the callback function for nftw + * https://linux.die.net/man/3/nftw + */ +static int nftw_callback(const char *fpath, + const struct stat *sb, + int tflag, + struct FTW *ftwbuf) { + if (strcmp(fpath, ".") == 0 || strcmp(fpath, "..") == 0) { + return 0; + } + + if(tflag == FTW_DNR) { + if(!arguments.quiet) printf("Can not read %s", fpath); + } + + bool result = validate_utf8_fast(fpath, strlen(fpath)); + if(result) { + if(!arguments.quiet) printf("%s Valid OK \n", fpath); + } else { + printf("%s Valid FAILED \n", fpath); + } + + // continue + return 0; +} + +/** + * the main stuff + */ +int main(int argc, char *argv[]) { + + /** + * command line argument default values + */ + arguments.quiet = 0; + arguments.verbose = 0; + arguments.folder_to_read = "."; + + /** + * https://www.argtable.org/ + */ + void *argtable[] = { + help = arg_litn(NULL, "help", 0, 1, "Display this help and exit"), + quiet = arg_litn("q", "quiet", 0, 1, "Display only false ones"), + verbose = arg_litn("v", "verbose", 0, 1, "Verbose additional output"), + folderToRead = arg_filen(NULL, NULL, "", 1, 1, "Folder to read"), + end = arg_end(20), + }; + /* argtable parsing */ + int nerrors; + nerrors = arg_parse(argc,argv,argtable); + /* special case: '--help' takes precedence over error reporting */ + if (help->count > 0) { + printf("Usage: utf8check.exe"); + arg_print_syntax(stdout, argtable, "\n"); + arg_print_glossary(stdout, argtable, " %-25s %s\n"); + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); + return(1); + } + /* If the parser returned any errors then display them and exit */ + if (nerrors > 0) { + /* Display the error details contained in the arg_end struct.*/ + arg_print_errors(stdout, end, "utf8check.exe"); + printf("Try '%s --help' for more information.\n", "utf8check.exe"); + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); + return(1); + } + else { + arguments.quiet = quiet->count; + arguments.verbose = verbose->count; + arguments.folder_to_read = folderToRead->filename[0]; + } + + if(arguments.verbose) { + printf ("Folder = %s\n" + "Verbose = %s\n" + "Quiet = %s\n\n", + arguments.folder_to_read, + arguments.verbose ? "yes" : "no", + arguments.quiet ? "yes" : "no" + ); + } + + if (nftw(arguments.folder_to_read, nftw_callback, 15, FTW_PHYS)== -1) { + perror("Reading dir failed"); + exit(EXIT_FAILURE); + } + + arg_freetable(argtable, sizeof(argtable) / sizeof(argtable[0])); + exit(EXIT_SUCCESS); +} \ No newline at end of file -- 2.39.5