pax_global_header00006660000000000000000000000064121772263210014515gustar00rootroot0000000000000052 comment=9e16abeb4275f01b2041972a2edbd6ad46d945c1 cppcheck-1.61/000077500000000000000000000000001217722632100132245ustar00rootroot00000000000000cppcheck-1.61/.gitattributes000066400000000000000000000000371217722632100161170ustar00rootroot00000000000000htdocs/site/js/pack.js eol=lf cppcheck-1.61/.gitignore000066400000000000000000000014211217722632100152120ustar00rootroot00000000000000*.bak *.gcno *.o *.pyc cppcheck cppcheck.exe dmake reduce reduce.exe tags testrunner testrunner.exe tools/dmake tools/errmsg tools/extracttests # VS generated files *.aps *.idb *.ncb *.obj *.opensdf *.orig *.pdb *.sdf *.suo *.user # VS build folders bin/ Build/ BuildTmp/ cli/temp/ ipch/ lib/temp/ test/temp/ # XCode build folders and files *.mode[0-9]v[0-9] *.pbxuser build/ # GUI build folders gui/debug/ gui/release/ gui/temp/ # Other (generated) GUI files gui/*.qm gui/cppcheck-gui gui/gui.sln gui/gui.vcproj gui/Makefile gui/Makefile.debug gui/Makefile.release gui/qrc_gui.cpp # Doxygen output folder doxyoutput/ # qmake generated htmlreport/.tox/ htmlreport/MANIFEST # Backup files and stuff from patches *.orig *.rej *~ # kdevelop 4.x *.kdev4 htdocs/site/node_modules cppcheck-1.61/.travis.yml000066400000000000000000000006011217722632100153320ustar00rootroot00000000000000language: cpp compiler: - gcc - clang script: - mkdir build - make test SRCDIR=build VERIFY=1 - ./cppcheck --error-exitcode=1 -Ilib --enable=style --suppress=duplicateBranch -q cli gui lib -igui/test notifications: irc: channels: - "irc.freenode.org#cppcheck" template: - "[%{commit} : %{author}] %{message}" - "%{build_url}" skip_join: true cppcheck-1.61/AUTHORS000066400000000000000000000034411217722632100142760ustar00rootroot00000000000000The cppcheck team, in alphabetical order: Abhishek Bharadwaj Ahti Legonkov Akio Idehara Aleksey Palazhchenko Alexander Mai Andreas Bießmann Andrew C. Martin Andy Maloney Ankita Gupta anuraggarg011 Armin Müller Arpit Chaudhary August Sodora Baris Demiray Benjamin Goose Benjamin Kramer Benjamin Wolsey Bill Egert booga Carlo Marcelo Arenas Belon Cary R Changkyoon Kim Chuck Larson Daniel Marjamäki Debrard Sebastien Deepak Gupta dencat Dirk Jagdmann Duraffort Edoardo Prezioso Emmanuel Blot Eric Sesterhenn Erik Lax Ettl Martin Felix Geyer Frank Zingsheim gaurav kaushik Gerhard Zlabinger Gianluca Scacco Goran 'vBm' Džaferi Greg Hewgill Guillaume Miossec Günther Makulik Henrik Nilsson He Yuqi Hoang Tuan Su Jens Bäckman János Maros Johan Samuelson John Smits Jonathan Neuschäfer Jose Roquette Joshua Beck Jussi Lehtola Kamil Dudka Kartik Bajaj Kevin Christian Kimmo Varis Konrad Windszus Kumar Ashwani larudwer Lauri Nurmi Leandro Lisboa Penz Lena Herscheid Lieven de Cock lioncash Lucas Manuel Rodriguez Marc-Antoine Perennou Marek Zmysłowski Markus Elfring Martin Ettl Martin Exner Mateusz Pusz Mathias De Maré Mohit Mate Monika Lukow Moritz Barsnick Moritz Lipp ms myint Nguyen Duong Tuan Nicolas Alvarez Nicolas Le Cam Nilesh Kumar OGAWA KenIchi Oliver Stoeneberg Pete Johns Peter Pentchev Philipp Kloke Pierre Schweitzer Pino Toscano Pranav Khanna Raphael Geissert Reijo Tomperi Richard Quirk Robert Morin Robert Reif rofl0r Roman Zaytsev Borisovich root Ryan Pavlik Sandeep Dutta Sébastien Debrard Simon Kagstrom Simon Martin Slava Semushin Stefan Naewe Stefan Weil Thomas Jarosch Thomas Sondergaard Tim Gerundt WenChung Chiu Vesa Pikki Ville Skyttä XhmikosR Zachary Blair Zhao Qifa Zhiyuan Zhang Дмитрий Старцев GUI graphics courtesy of Tango Desktop Project: http://tango.freedesktop.org cppcheck-1.61/COPYING000066400000000000000000001045131217722632100142630ustar00rootroot00000000000000 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 . cppcheck-1.61/Cppcheck.xcodeproj/000077500000000000000000000000001217722632100167405ustar00rootroot00000000000000cppcheck-1.61/Cppcheck.xcodeproj/project.pbxproj000066400000000000000000001163401217722632100220210ustar00rootroot00000000000000// !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 39E60EB91270DE3A00AC0D02 /* checkautovariables.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 39E60E8D1270DE3A00AC0D02 /* checkautovariables.cpp */; }; 39E60EBA1270DE3A00AC0D02 /* checkbufferoverrun.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 39E60E8F1270DE3A00AC0D02 /* checkbufferoverrun.cpp */; }; 39E60EBB1270DE3A00AC0D02 /* checkclass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 39E60E911270DE3A00AC0D02 /* checkclass.cpp */; }; 39E60EBC1270DE3A00AC0D02 /* checkexceptionsafety.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 39E60E931270DE3A00AC0D02 /* checkexceptionsafety.cpp */; }; 39E60EBD1270DE3A00AC0D02 /* checkmemoryleak.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 39E60E951270DE3A00AC0D02 /* checkmemoryleak.cpp */; }; 39E60EBE1270DE3A00AC0D02 /* checkobsoletefunctions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 39E60E971270DE3A00AC0D02 /* checkobsoletefunctions.cpp */; }; 39E60EBF1270DE3A00AC0D02 /* checkother.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 39E60E991270DE3A00AC0D02 /* checkother.cpp */; }; 39E60EC01270DE3A00AC0D02 /* checkpostfixoperator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 39E60E9B1270DE3A00AC0D02 /* checkpostfixoperator.cpp */; }; 39E60EC11270DE3A00AC0D02 /* checkstl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 39E60E9D1270DE3A00AC0D02 /* checkstl.cpp */; }; 39E60EC21270DE3A00AC0D02 /* checkunusedfunctions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 39E60E9F1270DE3A00AC0D02 /* checkunusedfunctions.cpp */; }; 39E60EC31270DE3A00AC0D02 /* cppcheck.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 39E60EA11270DE3A00AC0D02 /* cppcheck.cpp */; }; 39E60EC41270DE3A00AC0D02 /* errorlogger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 39E60EA31270DE3A00AC0D02 /* errorlogger.cpp */; }; 39E60EC51270DE3A00AC0D02 /* executionpath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 39E60EA51270DE3A00AC0D02 /* executionpath.cpp */; }; 39E60EC81270DE3A00AC0D02 /* mathlib.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 39E60EAB1270DE3A00AC0D02 /* mathlib.cpp */; }; 39E60EC91270DE3A00AC0D02 /* path.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 39E60EAD1270DE3A00AC0D02 /* path.cpp */; }; 39E60ECA1270DE3A00AC0D02 /* preprocessor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 39E60EAF1270DE3A00AC0D02 /* preprocessor.cpp */; }; 39E60ECB1270DE3A00AC0D02 /* settings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 39E60EB11270DE3A00AC0D02 /* settings.cpp */; }; 39E60ECC1270DE3A00AC0D02 /* timer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 39E60EB31270DE3A00AC0D02 /* timer.cpp */; }; 39E60ECD1270DE3A00AC0D02 /* token.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 39E60EB51270DE3A00AC0D02 /* token.cpp */; }; 39E60ECE1270DE3A00AC0D02 /* tokenize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 39E60EB71270DE3A00AC0D02 /* tokenize.cpp */; }; 39E60ED61270DE5000AC0D02 /* cmdlineparser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 39E60ECF1270DE5000AC0D02 /* cmdlineparser.cpp */; }; 39E60ED71270DE5000AC0D02 /* cppcheckexecutor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 39E60ED11270DE5000AC0D02 /* cppcheckexecutor.cpp */; }; 39E60ED81270DE5000AC0D02 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 39E60ED31270DE5000AC0D02 /* main.cpp */; }; 39E60ED91270DE5000AC0D02 /* threadexecutor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 39E60ED41270DE5000AC0D02 /* threadexecutor.cpp */; }; F4043DB1177F08A800CD5A40 /* filelister.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4043DAD177F08A800CD5A40 /* filelister.cpp */; }; F4043DB2177F08A800CD5A40 /* pathmatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4043DAF177F08A800CD5A40 /* pathmatch.cpp */; }; F4043DD7177F093300CD5A40 /* check64bit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4043DB3177F093300CD5A40 /* check64bit.cpp */; }; F4043DD8177F093300CD5A40 /* checkassert.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4043DB5177F093300CD5A40 /* checkassert.cpp */; }; F4043DD9177F093300CD5A40 /* checkassignif.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4043DB7177F093300CD5A40 /* checkassignif.cpp */; }; F4043DDA177F093300CD5A40 /* checkbool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4043DB9177F093300CD5A40 /* checkbool.cpp */; }; F4043DDB177F093300CD5A40 /* checkboost.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4043DBB177F093300CD5A40 /* checkboost.cpp */; }; F4043DDC177F093300CD5A40 /* checkinternal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4043DBD177F093300CD5A40 /* checkinternal.cpp */; }; F4043DDD177F093300CD5A40 /* checkio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4043DBF177F093300CD5A40 /* checkio.cpp */; }; F4043DDE177F093300CD5A40 /* checkleakautovar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4043DC1177F093300CD5A40 /* checkleakautovar.cpp */; }; F4043DDF177F093300CD5A40 /* checknonreentrantfunctions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4043DC3177F093300CD5A40 /* checknonreentrantfunctions.cpp */; }; F4043DE0177F093300CD5A40 /* checknullpointer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4043DC5177F093300CD5A40 /* checknullpointer.cpp */; }; F4043DE1177F093300CD5A40 /* checksizeof.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4043DC7177F093300CD5A40 /* checksizeof.cpp */; }; F4043DE2177F093300CD5A40 /* checkuninitvar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4043DC9177F093300CD5A40 /* checkuninitvar.cpp */; }; F4043DE3177F093300CD5A40 /* checkunusedvar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4043DCB177F093300CD5A40 /* checkunusedvar.cpp */; }; F4043DE4177F093300CD5A40 /* suppressions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4043DCE177F093300CD5A40 /* suppressions.cpp */; }; F4043DE5177F093300CD5A40 /* symboldatabase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4043DD0177F093300CD5A40 /* symboldatabase.cpp */; }; F4043DE6177F093300CD5A40 /* templatesimplifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4043DD2177F093300CD5A40 /* templatesimplifier.cpp */; }; F4043DE7177F093300CD5A40 /* tokenlist.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F4043DD4177F093300CD5A40 /* tokenlist.cpp */; }; F47E507E17896A8600C684DC /* environment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F47E507C17896A8600C684DC /* environment.cpp */; }; F47E508317896AEB00C684DC /* tinyxml2.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F47E508117896AEB00C684DC /* tinyxml2.cpp */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ 8DD76F690486A84900D96B5E /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 8; dstPath = /usr/share/man/man1/; dstSubfolderSpec = 0; files = ( ); runOnlyForDeploymentPostprocessing = 1; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ 39E60E8C1270DE3A00AC0D02 /* check.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = check.h; path = lib/check.h; sourceTree = ""; }; 39E60E8D1270DE3A00AC0D02 /* checkautovariables.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = checkautovariables.cpp; path = lib/checkautovariables.cpp; sourceTree = ""; }; 39E60E8E1270DE3A00AC0D02 /* checkautovariables.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = checkautovariables.h; path = lib/checkautovariables.h; sourceTree = ""; }; 39E60E8F1270DE3A00AC0D02 /* checkbufferoverrun.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = checkbufferoverrun.cpp; path = lib/checkbufferoverrun.cpp; sourceTree = ""; }; 39E60E901270DE3A00AC0D02 /* checkbufferoverrun.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = checkbufferoverrun.h; path = lib/checkbufferoverrun.h; sourceTree = ""; }; 39E60E911270DE3A00AC0D02 /* checkclass.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = checkclass.cpp; path = lib/checkclass.cpp; sourceTree = ""; }; 39E60E921270DE3A00AC0D02 /* checkclass.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = checkclass.h; path = lib/checkclass.h; sourceTree = ""; }; 39E60E931270DE3A00AC0D02 /* checkexceptionsafety.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = checkexceptionsafety.cpp; path = lib/checkexceptionsafety.cpp; sourceTree = ""; }; 39E60E941270DE3A00AC0D02 /* checkexceptionsafety.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = checkexceptionsafety.h; path = lib/checkexceptionsafety.h; sourceTree = ""; }; 39E60E951270DE3A00AC0D02 /* checkmemoryleak.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = checkmemoryleak.cpp; path = lib/checkmemoryleak.cpp; sourceTree = ""; }; 39E60E961270DE3A00AC0D02 /* checkmemoryleak.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = checkmemoryleak.h; path = lib/checkmemoryleak.h; sourceTree = ""; }; 39E60E971270DE3A00AC0D02 /* checkobsoletefunctions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = checkobsoletefunctions.cpp; path = lib/checkobsoletefunctions.cpp; sourceTree = ""; }; 39E60E981270DE3A00AC0D02 /* checkobsoletefunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = checkobsoletefunctions.h; path = lib/checkobsoletefunctions.h; sourceTree = ""; }; 39E60E991270DE3A00AC0D02 /* checkother.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = checkother.cpp; path = lib/checkother.cpp; sourceTree = ""; }; 39E60E9A1270DE3A00AC0D02 /* checkother.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = checkother.h; path = lib/checkother.h; sourceTree = ""; }; 39E60E9B1270DE3A00AC0D02 /* checkpostfixoperator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = checkpostfixoperator.cpp; path = lib/checkpostfixoperator.cpp; sourceTree = ""; }; 39E60E9C1270DE3A00AC0D02 /* checkpostfixoperator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = checkpostfixoperator.h; path = lib/checkpostfixoperator.h; sourceTree = ""; }; 39E60E9D1270DE3A00AC0D02 /* checkstl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = checkstl.cpp; path = lib/checkstl.cpp; sourceTree = ""; }; 39E60E9E1270DE3A00AC0D02 /* checkstl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = checkstl.h; path = lib/checkstl.h; sourceTree = ""; }; 39E60E9F1270DE3A00AC0D02 /* checkunusedfunctions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = checkunusedfunctions.cpp; path = lib/checkunusedfunctions.cpp; sourceTree = ""; }; 39E60EA01270DE3A00AC0D02 /* checkunusedfunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = checkunusedfunctions.h; path = lib/checkunusedfunctions.h; sourceTree = ""; }; 39E60EA11270DE3A00AC0D02 /* cppcheck.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = cppcheck.cpp; path = lib/cppcheck.cpp; sourceTree = ""; }; 39E60EA21270DE3A00AC0D02 /* cppcheck.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cppcheck.h; path = lib/cppcheck.h; sourceTree = ""; }; 39E60EA31270DE3A00AC0D02 /* errorlogger.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = errorlogger.cpp; path = lib/errorlogger.cpp; sourceTree = ""; }; 39E60EA41270DE3A00AC0D02 /* errorlogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = errorlogger.h; path = lib/errorlogger.h; sourceTree = ""; }; 39E60EA51270DE3A00AC0D02 /* executionpath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = executionpath.cpp; path = lib/executionpath.cpp; sourceTree = ""; }; 39E60EA61270DE3A00AC0D02 /* executionpath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = executionpath.h; path = lib/executionpath.h; sourceTree = ""; }; 39E60EAB1270DE3A00AC0D02 /* mathlib.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = mathlib.cpp; path = lib/mathlib.cpp; sourceTree = ""; }; 39E60EAC1270DE3A00AC0D02 /* mathlib.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mathlib.h; path = lib/mathlib.h; sourceTree = ""; }; 39E60EAD1270DE3A00AC0D02 /* path.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = path.cpp; path = lib/path.cpp; sourceTree = ""; }; 39E60EAE1270DE3A00AC0D02 /* path.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = path.h; path = lib/path.h; sourceTree = ""; }; 39E60EAF1270DE3A00AC0D02 /* preprocessor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = preprocessor.cpp; path = lib/preprocessor.cpp; sourceTree = ""; }; 39E60EB01270DE3A00AC0D02 /* preprocessor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = preprocessor.h; path = lib/preprocessor.h; sourceTree = ""; }; 39E60EB11270DE3A00AC0D02 /* settings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = settings.cpp; path = lib/settings.cpp; sourceTree = ""; }; 39E60EB21270DE3A00AC0D02 /* settings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = settings.h; path = lib/settings.h; sourceTree = ""; }; 39E60EB31270DE3A00AC0D02 /* timer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = timer.cpp; path = lib/timer.cpp; sourceTree = ""; }; 39E60EB41270DE3A00AC0D02 /* timer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = timer.h; path = lib/timer.h; sourceTree = ""; }; 39E60EB51270DE3A00AC0D02 /* token.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = token.cpp; path = lib/token.cpp; sourceTree = ""; }; 39E60EB61270DE3A00AC0D02 /* token.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = token.h; path = lib/token.h; sourceTree = ""; }; 39E60EB71270DE3A00AC0D02 /* tokenize.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tokenize.cpp; path = lib/tokenize.cpp; sourceTree = ""; }; 39E60EB81270DE3A00AC0D02 /* tokenize.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tokenize.h; path = lib/tokenize.h; sourceTree = ""; }; 39E60ECF1270DE5000AC0D02 /* cmdlineparser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = cmdlineparser.cpp; path = cli/cmdlineparser.cpp; sourceTree = ""; }; 39E60ED01270DE5000AC0D02 /* cmdlineparser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cmdlineparser.h; path = cli/cmdlineparser.h; sourceTree = ""; }; 39E60ED11270DE5000AC0D02 /* cppcheckexecutor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = cppcheckexecutor.cpp; path = cli/cppcheckexecutor.cpp; sourceTree = ""; }; 39E60ED21270DE5000AC0D02 /* cppcheckexecutor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = cppcheckexecutor.h; path = cli/cppcheckexecutor.h; sourceTree = ""; }; 39E60ED31270DE5000AC0D02 /* main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = main.cpp; path = cli/main.cpp; sourceTree = ""; }; 39E60ED41270DE5000AC0D02 /* threadexecutor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = threadexecutor.cpp; path = cli/threadexecutor.cpp; sourceTree = ""; }; 39E60ED51270DE5000AC0D02 /* threadexecutor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = threadexecutor.h; path = cli/threadexecutor.h; sourceTree = ""; }; 39E60EDE1270DEB100AC0D02 /* cppcheck */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = cppcheck; sourceTree = BUILT_PRODUCTS_DIR; }; F4043DAD177F08A800CD5A40 /* filelister.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = filelister.cpp; path = cli/filelister.cpp; sourceTree = ""; }; F4043DAE177F08A800CD5A40 /* filelister.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = filelister.h; path = cli/filelister.h; sourceTree = ""; }; F4043DAF177F08A800CD5A40 /* pathmatch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = pathmatch.cpp; path = cli/pathmatch.cpp; sourceTree = ""; }; F4043DB0177F08A800CD5A40 /* pathmatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pathmatch.h; path = cli/pathmatch.h; sourceTree = ""; }; F4043DB3177F093300CD5A40 /* check64bit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = check64bit.cpp; path = lib/check64bit.cpp; sourceTree = ""; }; F4043DB4177F093300CD5A40 /* check64bit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = check64bit.h; path = lib/check64bit.h; sourceTree = ""; }; F4043DB5177F093300CD5A40 /* checkassert.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = checkassert.cpp; path = lib/checkassert.cpp; sourceTree = ""; }; F4043DB6177F093300CD5A40 /* checkassert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = checkassert.h; path = lib/checkassert.h; sourceTree = ""; }; F4043DB7177F093300CD5A40 /* checkassignif.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = checkassignif.cpp; path = lib/checkassignif.cpp; sourceTree = ""; }; F4043DB8177F093300CD5A40 /* checkassignif.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = checkassignif.h; path = lib/checkassignif.h; sourceTree = ""; }; F4043DB9177F093300CD5A40 /* checkbool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = checkbool.cpp; path = lib/checkbool.cpp; sourceTree = ""; }; F4043DBA177F093300CD5A40 /* checkbool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = checkbool.h; path = lib/checkbool.h; sourceTree = ""; }; F4043DBB177F093300CD5A40 /* checkboost.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = checkboost.cpp; path = lib/checkboost.cpp; sourceTree = ""; }; F4043DBC177F093300CD5A40 /* checkboost.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = checkboost.h; path = lib/checkboost.h; sourceTree = ""; }; F4043DBD177F093300CD5A40 /* checkinternal.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = checkinternal.cpp; path = lib/checkinternal.cpp; sourceTree = ""; }; F4043DBE177F093300CD5A40 /* checkinternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = checkinternal.h; path = lib/checkinternal.h; sourceTree = ""; }; F4043DBF177F093300CD5A40 /* checkio.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = checkio.cpp; path = lib/checkio.cpp; sourceTree = ""; }; F4043DC0177F093300CD5A40 /* checkio.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = checkio.h; path = lib/checkio.h; sourceTree = ""; }; F4043DC1177F093300CD5A40 /* checkleakautovar.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = checkleakautovar.cpp; path = lib/checkleakautovar.cpp; sourceTree = ""; }; F4043DC2177F093300CD5A40 /* checkleakautovar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = checkleakautovar.h; path = lib/checkleakautovar.h; sourceTree = ""; }; F4043DC3177F093300CD5A40 /* checknonreentrantfunctions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = checknonreentrantfunctions.cpp; path = lib/checknonreentrantfunctions.cpp; sourceTree = ""; }; F4043DC4177F093300CD5A40 /* checknonreentrantfunctions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = checknonreentrantfunctions.h; path = lib/checknonreentrantfunctions.h; sourceTree = ""; }; F4043DC5177F093300CD5A40 /* checknullpointer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = checknullpointer.cpp; path = lib/checknullpointer.cpp; sourceTree = ""; }; F4043DC6177F093300CD5A40 /* checknullpointer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = checknullpointer.h; path = lib/checknullpointer.h; sourceTree = ""; }; F4043DC7177F093300CD5A40 /* checksizeof.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = checksizeof.cpp; path = lib/checksizeof.cpp; sourceTree = ""; }; F4043DC8177F093300CD5A40 /* checksizeof.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = checksizeof.h; path = lib/checksizeof.h; sourceTree = ""; }; F4043DC9177F093300CD5A40 /* checkuninitvar.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = checkuninitvar.cpp; path = lib/checkuninitvar.cpp; sourceTree = ""; }; F4043DCA177F093300CD5A40 /* checkuninitvar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = checkuninitvar.h; path = lib/checkuninitvar.h; sourceTree = ""; }; F4043DCB177F093300CD5A40 /* checkunusedvar.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = checkunusedvar.cpp; path = lib/checkunusedvar.cpp; sourceTree = ""; }; F4043DCC177F093300CD5A40 /* checkunusedvar.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = checkunusedvar.h; path = lib/checkunusedvar.h; sourceTree = ""; }; F4043DCD177F093300CD5A40 /* standards.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = standards.h; path = lib/standards.h; sourceTree = ""; }; F4043DCE177F093300CD5A40 /* suppressions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = suppressions.cpp; path = lib/suppressions.cpp; sourceTree = ""; }; F4043DCF177F093300CD5A40 /* suppressions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = suppressions.h; path = lib/suppressions.h; sourceTree = ""; }; F4043DD0177F093300CD5A40 /* symboldatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = symboldatabase.cpp; path = lib/symboldatabase.cpp; sourceTree = ""; }; F4043DD1177F093300CD5A40 /* symboldatabase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = symboldatabase.h; path = lib/symboldatabase.h; sourceTree = ""; }; F4043DD2177F093300CD5A40 /* templatesimplifier.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = templatesimplifier.cpp; path = lib/templatesimplifier.cpp; sourceTree = ""; }; F4043DD3177F093300CD5A40 /* templatesimplifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = templatesimplifier.h; path = lib/templatesimplifier.h; sourceTree = ""; }; F4043DD4177F093300CD5A40 /* tokenlist.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tokenlist.cpp; path = lib/tokenlist.cpp; sourceTree = ""; }; F4043DD5177F093300CD5A40 /* tokenlist.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tokenlist.h; path = lib/tokenlist.h; sourceTree = ""; }; F4043DD6177F093300CD5A40 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = version.h; path = lib/version.h; sourceTree = ""; }; F47E507C17896A8600C684DC /* environment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = environment.cpp; path = lib/environment.cpp; sourceTree = ""; }; F47E507D17896A8600C684DC /* environment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = environment.h; path = lib/environment.h; sourceTree = ""; }; F47E508117896AEB00C684DC /* tinyxml2.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = tinyxml2.cpp; path = externals/tinyxml/tinyxml2.cpp; sourceTree = ""; }; F47E508217896AEB00C684DC /* tinyxml2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = tinyxml2.h; path = externals/tinyxml/tinyxml2.h; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 8DD76F660486A84900D96B5E /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 08FB7794FE84155DC02AAC07 /* cppcheck */ = { isa = PBXGroup; children = ( 08FB7795FE84155DC02AAC07 /* Source */, C6859E8C029090F304C91782 /* Documentation */, 1AB674ADFE9D54B511CA2CBB /* Products */, ); name = cppcheck; sourceTree = ""; }; 08FB7795FE84155DC02AAC07 /* Source */ = { isa = PBXGroup; children = ( F47E507F17896AC700C684DC /* Externals */, 2C21A45D1178BB0B00D35009 /* Library */, 2C21A45C1178BB0400D35009 /* Command */, ); name = Source; sourceTree = ""; }; 1AB674ADFE9D54B511CA2CBB /* Products */ = { isa = PBXGroup; children = ( 39E60EDE1270DEB100AC0D02 /* cppcheck */, ); name = Products; sourceTree = ""; }; 2C21A45C1178BB0400D35009 /* Command */ = { isa = PBXGroup; children = ( 39E60ECF1270DE5000AC0D02 /* cmdlineparser.cpp */, 39E60ED01270DE5000AC0D02 /* cmdlineparser.h */, 39E60ED11270DE5000AC0D02 /* cppcheckexecutor.cpp */, 39E60ED21270DE5000AC0D02 /* cppcheckexecutor.h */, F4043DAD177F08A800CD5A40 /* filelister.cpp */, F4043DAE177F08A800CD5A40 /* filelister.h */, 39E60ED31270DE5000AC0D02 /* main.cpp */, F4043DAF177F08A800CD5A40 /* pathmatch.cpp */, F4043DB0177F08A800CD5A40 /* pathmatch.h */, 39E60ED41270DE5000AC0D02 /* threadexecutor.cpp */, 39E60ED51270DE5000AC0D02 /* threadexecutor.h */, ); name = Command; sourceTree = ""; }; 2C21A45D1178BB0B00D35009 /* Library */ = { isa = PBXGroup; children = ( 39E60E8C1270DE3A00AC0D02 /* check.h */, F4043DB3177F093300CD5A40 /* check64bit.cpp */, F4043DB4177F093300CD5A40 /* check64bit.h */, F4043DB5177F093300CD5A40 /* checkassert.cpp */, F4043DB6177F093300CD5A40 /* checkassert.h */, F4043DB7177F093300CD5A40 /* checkassignif.cpp */, F4043DB8177F093300CD5A40 /* checkassignif.h */, 39E60E8D1270DE3A00AC0D02 /* checkautovariables.cpp */, 39E60E8E1270DE3A00AC0D02 /* checkautovariables.h */, F4043DB9177F093300CD5A40 /* checkbool.cpp */, F4043DBA177F093300CD5A40 /* checkbool.h */, F4043DBB177F093300CD5A40 /* checkboost.cpp */, F4043DBC177F093300CD5A40 /* checkboost.h */, 39E60E8F1270DE3A00AC0D02 /* checkbufferoverrun.cpp */, 39E60E901270DE3A00AC0D02 /* checkbufferoverrun.h */, 39E60E911270DE3A00AC0D02 /* checkclass.cpp */, 39E60E921270DE3A00AC0D02 /* checkclass.h */, 39E60E931270DE3A00AC0D02 /* checkexceptionsafety.cpp */, 39E60E941270DE3A00AC0D02 /* checkexceptionsafety.h */, F4043DBD177F093300CD5A40 /* checkinternal.cpp */, F4043DBE177F093300CD5A40 /* checkinternal.h */, F4043DBF177F093300CD5A40 /* checkio.cpp */, F4043DC0177F093300CD5A40 /* checkio.h */, F4043DC1177F093300CD5A40 /* checkleakautovar.cpp */, F4043DC2177F093300CD5A40 /* checkleakautovar.h */, 39E60E951270DE3A00AC0D02 /* checkmemoryleak.cpp */, 39E60E961270DE3A00AC0D02 /* checkmemoryleak.h */, F4043DC3177F093300CD5A40 /* checknonreentrantfunctions.cpp */, F4043DC4177F093300CD5A40 /* checknonreentrantfunctions.h */, F4043DC5177F093300CD5A40 /* checknullpointer.cpp */, F4043DC6177F093300CD5A40 /* checknullpointer.h */, 39E60E971270DE3A00AC0D02 /* checkobsoletefunctions.cpp */, 39E60E981270DE3A00AC0D02 /* checkobsoletefunctions.h */, 39E60E991270DE3A00AC0D02 /* checkother.cpp */, 39E60E9A1270DE3A00AC0D02 /* checkother.h */, 39E60E9B1270DE3A00AC0D02 /* checkpostfixoperator.cpp */, 39E60E9C1270DE3A00AC0D02 /* checkpostfixoperator.h */, F4043DC7177F093300CD5A40 /* checksizeof.cpp */, F4043DC8177F093300CD5A40 /* checksizeof.h */, 39E60E9D1270DE3A00AC0D02 /* checkstl.cpp */, 39E60E9E1270DE3A00AC0D02 /* checkstl.h */, F4043DC9177F093300CD5A40 /* checkuninitvar.cpp */, F4043DCA177F093300CD5A40 /* checkuninitvar.h */, 39E60E9F1270DE3A00AC0D02 /* checkunusedfunctions.cpp */, 39E60EA01270DE3A00AC0D02 /* checkunusedfunctions.h */, F4043DCB177F093300CD5A40 /* checkunusedvar.cpp */, F4043DCC177F093300CD5A40 /* checkunusedvar.h */, 39E60EA11270DE3A00AC0D02 /* cppcheck.cpp */, 39E60EA21270DE3A00AC0D02 /* cppcheck.h */, F47E507C17896A8600C684DC /* environment.cpp */, F47E507D17896A8600C684DC /* environment.h */, 39E60EA31270DE3A00AC0D02 /* errorlogger.cpp */, 39E60EA41270DE3A00AC0D02 /* errorlogger.h */, 39E60EA51270DE3A00AC0D02 /* executionpath.cpp */, 39E60EA61270DE3A00AC0D02 /* executionpath.h */, 39E60EAB1270DE3A00AC0D02 /* mathlib.cpp */, 39E60EAC1270DE3A00AC0D02 /* mathlib.h */, 39E60EAD1270DE3A00AC0D02 /* path.cpp */, 39E60EAE1270DE3A00AC0D02 /* path.h */, 39E60EAF1270DE3A00AC0D02 /* preprocessor.cpp */, 39E60EB01270DE3A00AC0D02 /* preprocessor.h */, 39E60EB11270DE3A00AC0D02 /* settings.cpp */, 39E60EB21270DE3A00AC0D02 /* settings.h */, F4043DCD177F093300CD5A40 /* standards.h */, F4043DCE177F093300CD5A40 /* suppressions.cpp */, F4043DCF177F093300CD5A40 /* suppressions.h */, F4043DD0177F093300CD5A40 /* symboldatabase.cpp */, F4043DD1177F093300CD5A40 /* symboldatabase.h */, F4043DD2177F093300CD5A40 /* templatesimplifier.cpp */, F4043DD3177F093300CD5A40 /* templatesimplifier.h */, 39E60EB31270DE3A00AC0D02 /* timer.cpp */, 39E60EB41270DE3A00AC0D02 /* timer.h */, 39E60EB51270DE3A00AC0D02 /* token.cpp */, 39E60EB61270DE3A00AC0D02 /* token.h */, 39E60EB71270DE3A00AC0D02 /* tokenize.cpp */, 39E60EB81270DE3A00AC0D02 /* tokenize.h */, F4043DD4177F093300CD5A40 /* tokenlist.cpp */, F4043DD5177F093300CD5A40 /* tokenlist.h */, F4043DD6177F093300CD5A40 /* version.h */, ); name = Library; sourceTree = ""; }; C6859E8C029090F304C91782 /* Documentation */ = { isa = PBXGroup; children = ( ); name = Documentation; sourceTree = ""; }; F47E507F17896AC700C684DC /* Externals */ = { isa = PBXGroup; children = ( F47E508017896AD200C684DC /* tinyxml */, ); name = Externals; sourceTree = ""; }; F47E508017896AD200C684DC /* tinyxml */ = { isa = PBXGroup; children = ( F47E508117896AEB00C684DC /* tinyxml2.cpp */, F47E508217896AEB00C684DC /* tinyxml2.h */, ); name = tinyxml; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 8DD76F620486A84900D96B5E /* cppcheck */ = { isa = PBXNativeTarget; buildConfigurationList = 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "cppcheck" */; buildPhases = ( 8DD76F640486A84900D96B5E /* Sources */, 8DD76F660486A84900D96B5E /* Frameworks */, 8DD76F690486A84900D96B5E /* CopyFiles */, ); buildRules = ( ); dependencies = ( ); name = cppcheck; productInstallPath = "$(HOME)/bin"; productName = cppcheck; productReference = 39E60EDE1270DEB100AC0D02 /* cppcheck */; productType = "com.apple.product-type.tool"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 08FB7793FE84155DC02AAC07 /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0460; }; buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "Cppcheck" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 1; knownRegions = ( English, Japanese, French, German, ); mainGroup = 08FB7794FE84155DC02AAC07 /* cppcheck */; projectDirPath = ""; projectRoot = ""; targets = ( 8DD76F620486A84900D96B5E /* cppcheck */, ); }; /* End PBXProject section */ /* Begin PBXSourcesBuildPhase section */ 8DD76F640486A84900D96B5E /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 39E60EB91270DE3A00AC0D02 /* checkautovariables.cpp in Sources */, 39E60EBA1270DE3A00AC0D02 /* checkbufferoverrun.cpp in Sources */, 39E60EBB1270DE3A00AC0D02 /* checkclass.cpp in Sources */, 39E60EBC1270DE3A00AC0D02 /* checkexceptionsafety.cpp in Sources */, 39E60EBD1270DE3A00AC0D02 /* checkmemoryleak.cpp in Sources */, 39E60EBE1270DE3A00AC0D02 /* checkobsoletefunctions.cpp in Sources */, 39E60EBF1270DE3A00AC0D02 /* checkother.cpp in Sources */, 39E60EC01270DE3A00AC0D02 /* checkpostfixoperator.cpp in Sources */, 39E60EC11270DE3A00AC0D02 /* checkstl.cpp in Sources */, 39E60EC21270DE3A00AC0D02 /* checkunusedfunctions.cpp in Sources */, 39E60EC31270DE3A00AC0D02 /* cppcheck.cpp in Sources */, 39E60EC41270DE3A00AC0D02 /* errorlogger.cpp in Sources */, 39E60EC51270DE3A00AC0D02 /* executionpath.cpp in Sources */, 39E60EC81270DE3A00AC0D02 /* mathlib.cpp in Sources */, 39E60EC91270DE3A00AC0D02 /* path.cpp in Sources */, 39E60ECA1270DE3A00AC0D02 /* preprocessor.cpp in Sources */, 39E60ECB1270DE3A00AC0D02 /* settings.cpp in Sources */, 39E60ECC1270DE3A00AC0D02 /* timer.cpp in Sources */, 39E60ECD1270DE3A00AC0D02 /* token.cpp in Sources */, 39E60ECE1270DE3A00AC0D02 /* tokenize.cpp in Sources */, 39E60ED61270DE5000AC0D02 /* cmdlineparser.cpp in Sources */, 39E60ED71270DE5000AC0D02 /* cppcheckexecutor.cpp in Sources */, 39E60ED81270DE5000AC0D02 /* main.cpp in Sources */, 39E60ED91270DE5000AC0D02 /* threadexecutor.cpp in Sources */, F4043DB1177F08A800CD5A40 /* filelister.cpp in Sources */, F4043DB2177F08A800CD5A40 /* pathmatch.cpp in Sources */, F4043DD7177F093300CD5A40 /* check64bit.cpp in Sources */, F4043DD8177F093300CD5A40 /* checkassert.cpp in Sources */, F4043DD9177F093300CD5A40 /* checkassignif.cpp in Sources */, F4043DDA177F093300CD5A40 /* checkbool.cpp in Sources */, F4043DDB177F093300CD5A40 /* checkboost.cpp in Sources */, F4043DDC177F093300CD5A40 /* checkinternal.cpp in Sources */, F4043DDD177F093300CD5A40 /* checkio.cpp in Sources */, F4043DDE177F093300CD5A40 /* checkleakautovar.cpp in Sources */, F4043DDF177F093300CD5A40 /* checknonreentrantfunctions.cpp in Sources */, F4043DE0177F093300CD5A40 /* checknullpointer.cpp in Sources */, F4043DE1177F093300CD5A40 /* checksizeof.cpp in Sources */, F4043DE2177F093300CD5A40 /* checkuninitvar.cpp in Sources */, F4043DE3177F093300CD5A40 /* checkunusedvar.cpp in Sources */, F4043DE4177F093300CD5A40 /* suppressions.cpp in Sources */, F4043DE5177F093300CD5A40 /* symboldatabase.cpp in Sources */, F4043DE6177F093300CD5A40 /* templatesimplifier.cpp in Sources */, F4043DE7177F093300CD5A40 /* tokenlist.cpp in Sources */, F47E507E17896A8600C684DC /* environment.cpp in Sources */, F47E508317896AEB00C684DC /* tinyxml2.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 1DEB923208733DC60010E9CD /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; COPY_PHASE_STRIP = NO; GCC_DYNAMIC_NO_PIC = NO; GCC_MODEL_TUNING = ""; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ""; GCC_VERSION = ""; INSTALL_PATH = /usr/local/bin; PRECOMPS_INCLUDE_HEADERS_FROM_BUILT_PRODUCTS_DIR = NO; PRODUCT_NAME = cppcheck; }; name = Debug; }; 1DEB923308733DC60010E9CD /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; DEBUG_INFORMATION_FORMAT = dwarf; GCC_MODEL_TUNING = ""; INSTALL_PATH = /usr/local/bin; PRODUCT_NAME = cppcheck; }; name = Release; }; 1DEB923608733DC60010E9CD /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_OPTIMIZATION_LEVEL = 0; GCC_VERSION = 4.0; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; }; name = Debug; }; 1DEB923708733DC60010E9CD /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; SDKROOT = macosx; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 1DEB923108733DC60010E9CD /* Build configuration list for PBXNativeTarget "cppcheck" */ = { isa = XCConfigurationList; buildConfigurations = ( 1DEB923208733DC60010E9CD /* Debug */, 1DEB923308733DC60010E9CD /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "Cppcheck" */ = { isa = XCConfigurationList; buildConfigurations = ( 1DEB923608733DC60010E9CD /* Debug */, 1DEB923708733DC60010E9CD /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; } cppcheck-1.61/Makefile000066400000000000000000001104741217722632100146730ustar00rootroot00000000000000# This file is generated by tools/dmake, do not edit. # To compile with rules, use 'make HAVE_RULES=yes' ifndef HAVE_RULES HAVE_RULES=no endif # folder where lib/*.cpp files are located ifndef SRCDIR SRCDIR=lib endif ifeq ($(SRCDIR),build) ifdef VERIFY matchcompiler_S := $(shell python tools/matchcompiler.py --verify) else matchcompiler_S := $(shell python tools/matchcompiler.py) endif endif # Set the CPPCHK_GLIBCXX_DEBUG flag. This flag is not used in release Makefiles. # The _GLIBCXX_DEBUG define doesn't work in Cygwin or other Win32 systems. ifndef COMSPEC ifdef ComSpec #### ComSpec is defined on some WIN32's. COMSPEC=$(ComSpec) endif # ComSpec endif # COMSPEC ifdef COMSPEC #### Maybe Windows ifndef CPPCHK_GLIBCXX_DEBUG CPPCHK_GLIBCXX_DEBUG= endif # !CPPCHK_GLIBCXX_DEBUG ifeq ($(MSYSTEM),MINGW32) LDFLAGS=-lshlwapi endif else # !COMSPEC uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') ifeq ($(uname_S),Linux) ifndef CPPCHK_GLIBCXX_DEBUG CPPCHK_GLIBCXX_DEBUG=-D_GLIBCXX_DEBUG endif # !CPPCHK_GLIBCXX_DEBUG endif # Linux ifeq ($(uname_S),GNU/kFreeBSD) ifndef CPPCHK_GLIBCXX_DEBUG CPPCHK_GLIBCXX_DEBUG=-D_GLIBCXX_DEBUG endif # !CPPCHK_GLIBCXX_DEBUG endif # GNU/kFreeBSD endif # COMSPEC ifndef CXXFLAGS CXXFLAGS=-O2 -DNDEBUG -Wall endif ifeq ($(HAVE_RULES),yes) CXXFLAGS += -DHAVE_RULES -DTIXML_USE_STL $(shell pcre-config --cflags) ifdef LIBS LIBS += $(shell pcre-config --libs) else LIBS=$(shell pcre-config --libs) endif endif ifndef CXX CXX=g++ endif ifndef PREFIX PREFIX=/usr endif ifndef INCLUDE_FOR_LIB INCLUDE_FOR_LIB=-Ilib -Iexternals -Iexternals/tinyxml endif ifndef INCLUDE_FOR_CLI INCLUDE_FOR_CLI=-Ilib -Iexternals -Iexternals/tinyxml endif ifndef INCLUDE_FOR_TEST INCLUDE_FOR_TEST=-Ilib -Icli -Iexternals -Iexternals/tinyxml endif BIN=$(DESTDIR)$(PREFIX)/bin # For 'make man': sudo apt-get install xsltproc docbook-xsl docbook-xml on Linux DB2MAN=/usr/share/sgml/docbook/stylesheet/xsl/nwalsh/manpages/docbook.xsl XP=xsltproc -''-nonet -''-param man.charmap.use.subset "0" MAN_SOURCE=man/cppcheck.1.xml ###### Object Files LIBOBJ = $(SRCDIR)/check64bit.o \ $(SRCDIR)/checkassert.o \ $(SRCDIR)/checkassignif.o \ $(SRCDIR)/checkautovariables.o \ $(SRCDIR)/checkbool.o \ $(SRCDIR)/checkboost.o \ $(SRCDIR)/checkbufferoverrun.o \ $(SRCDIR)/checkclass.o \ $(SRCDIR)/checkexceptionsafety.o \ $(SRCDIR)/checkinternal.o \ $(SRCDIR)/checkio.o \ $(SRCDIR)/checkleakautovar.o \ $(SRCDIR)/checkmemoryleak.o \ $(SRCDIR)/checknonreentrantfunctions.o \ $(SRCDIR)/checknullpointer.o \ $(SRCDIR)/checkobsoletefunctions.o \ $(SRCDIR)/checkother.o \ $(SRCDIR)/checkpostfixoperator.o \ $(SRCDIR)/checksizeof.o \ $(SRCDIR)/checkstl.o \ $(SRCDIR)/checkuninitvar.o \ $(SRCDIR)/checkunusedfunctions.o \ $(SRCDIR)/checkunusedvar.o \ $(SRCDIR)/cppcheck.o \ $(SRCDIR)/errorlogger.o \ $(SRCDIR)/executionpath.o \ $(SRCDIR)/library.o \ $(SRCDIR)/mathlib.o \ $(SRCDIR)/path.o \ $(SRCDIR)/preprocessor.o \ $(SRCDIR)/settings.o \ $(SRCDIR)/suppressions.o \ $(SRCDIR)/symboldatabase.o \ $(SRCDIR)/templatesimplifier.o \ $(SRCDIR)/timer.o \ $(SRCDIR)/token.o \ $(SRCDIR)/tokenize.o \ $(SRCDIR)/tokenlist.o CLIOBJ = cli/cmdlineparser.o \ cli/cppcheckexecutor.o \ cli/filelister.o \ cli/main.o \ cli/pathmatch.o \ cli/threadexecutor.o TESTOBJ = test/options.o \ test/test64bit.o \ test/testassert.o \ test/testassignif.o \ test/testautovariables.o \ test/testbool.o \ test/testboost.o \ test/testbufferoverrun.o \ test/testcharvar.o \ test/testclass.o \ test/testcmdlineparser.o \ test/testconstructors.o \ test/testcppcheck.o \ test/testdivision.o \ test/testerrorlogger.o \ test/testexceptionsafety.o \ test/testfilelister.o \ test/testincompletestatement.o \ test/testinternal.o \ test/testio.o \ test/testleakautovar.o \ test/testmathlib.o \ test/testmemleak.o \ test/testnonreentrantfunctions.o \ test/testnullpointer.o \ test/testobsoletefunctions.o \ test/testoptions.o \ test/testother.o \ test/testpath.o \ test/testpathmatch.o \ test/testpostfixoperator.o \ test/testpreprocessor.o \ test/testrunner.o \ test/testsimplifytokens.o \ test/testsizeof.o \ test/teststl.o \ test/testsuite.o \ test/testsuppressions.o \ test/testsymboldatabase.o \ test/testthreadexecutor.o \ test/testtimer.o \ test/testtoken.o \ test/testtokenize.o \ test/testuninitvar.o \ test/testunusedfunctions.o \ test/testunusedprivfunc.o \ test/testunusedvar.o ifndef TINYXML TINYXML = externals/tinyxml/tinyxml2.o endif EXTOBJ += $(TINYXML) ###### Targets cppcheck: $(LIBOBJ) $(CLIOBJ) $(EXTOBJ) $(CXX) $(CPPFLAGS) $(CXXFLAGS) -o cppcheck $(CLIOBJ) $(LIBOBJ) $(EXTOBJ) $(LIBS) $(LDFLAGS) all: cppcheck testrunner testrunner: $(TESTOBJ) $(LIBOBJ) $(EXTOBJ) cli/threadexecutor.o cli/cmdlineparser.o cli/cppcheckexecutor.o cli/filelister.o cli/pathmatch.o $(CXX) $(CPPFLAGS) $(CXXFLAGS) -o testrunner $(TESTOBJ) $(LIBOBJ) cli/threadexecutor.o cli/cppcheckexecutor.o cli/cmdlineparser.o cli/filelister.o cli/pathmatch.o $(EXTOBJ) $(LIBS) $(LDFLAGS) test: all ./testrunner check: all ./testrunner -g -q dmake: tools/dmake.cpp $(CXX) -o dmake tools/dmake.cpp cli/filelister.cpp lib/path.cpp -Ilib $(LDFLAGS) reduce: tools/reduce.cpp $(CXX) -g -o reduce tools/reduce.cpp -Ilib lib/*.cpp clean: rm -f build/*.o lib/*.o cli/*.o test/*.o externals/tinyxml/*.o testrunner reduce cppcheck cppcheck.1 man: man/cppcheck.1 man/cppcheck.1: $(MAN_SOURCE) $(XP) $(DB2MAN) $(MAN_SOURCE) tags: ctags -R --exclude=doxyoutput . install: cppcheck install -d ${BIN} install cppcheck ${BIN} ###### Build $(SRCDIR)/check64bit.o: lib/check64bit.cpp lib/check64bit.h lib/config.h lib/check.h lib/token.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/symboldatabase.h lib/mathlib.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/check64bit.o $(SRCDIR)/check64bit.cpp $(SRCDIR)/checkassert.o: lib/checkassert.cpp lib/checkassert.h lib/config.h lib/check.h lib/token.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/symboldatabase.h lib/mathlib.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/checkassert.o $(SRCDIR)/checkassert.cpp $(SRCDIR)/checkassignif.o: lib/checkassignif.cpp lib/checkassignif.h lib/config.h lib/check.h lib/token.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/mathlib.h lib/symboldatabase.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/checkassignif.o $(SRCDIR)/checkassignif.cpp $(SRCDIR)/checkautovariables.o: lib/checkautovariables.cpp lib/checkautovariables.h lib/config.h lib/check.h lib/token.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/symboldatabase.h lib/mathlib.h lib/checkuninitvar.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/checkautovariables.o $(SRCDIR)/checkautovariables.cpp $(SRCDIR)/checkbool.o: lib/checkbool.cpp lib/checkbool.h lib/config.h lib/check.h lib/token.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/mathlib.h lib/symboldatabase.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/checkbool.o $(SRCDIR)/checkbool.cpp $(SRCDIR)/checkboost.o: lib/checkboost.cpp lib/checkboost.h lib/config.h lib/check.h lib/token.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/symboldatabase.h lib/mathlib.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/checkboost.o $(SRCDIR)/checkboost.cpp $(SRCDIR)/checkbufferoverrun.o: lib/checkbufferoverrun.cpp lib/checkbufferoverrun.h lib/config.h lib/check.h lib/token.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/mathlib.h lib/symboldatabase.h lib/executionpath.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/checkbufferoverrun.o $(SRCDIR)/checkbufferoverrun.cpp $(SRCDIR)/checkclass.o: lib/checkclass.cpp lib/checkclass.h lib/config.h lib/check.h lib/token.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/symboldatabase.h lib/mathlib.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/checkclass.o $(SRCDIR)/checkclass.cpp $(SRCDIR)/checkexceptionsafety.o: lib/checkexceptionsafety.cpp lib/checkexceptionsafety.h lib/config.h lib/check.h lib/token.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/symboldatabase.h lib/mathlib.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/checkexceptionsafety.o $(SRCDIR)/checkexceptionsafety.cpp $(SRCDIR)/checkinternal.o: lib/checkinternal.cpp lib/checkinternal.h lib/check.h lib/config.h lib/token.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/symboldatabase.h lib/mathlib.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/checkinternal.o $(SRCDIR)/checkinternal.cpp $(SRCDIR)/checkio.o: lib/checkio.cpp lib/checkio.h lib/check.h lib/config.h lib/token.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/symboldatabase.h lib/mathlib.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/checkio.o $(SRCDIR)/checkio.cpp $(SRCDIR)/checkleakautovar.o: lib/checkleakautovar.cpp lib/checkleakautovar.h lib/config.h lib/check.h lib/token.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/checkmemoryleak.h lib/checkother.h lib/symboldatabase.h lib/mathlib.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/checkleakautovar.o $(SRCDIR)/checkleakautovar.cpp $(SRCDIR)/checkmemoryleak.o: lib/checkmemoryleak.cpp lib/checkmemoryleak.h lib/config.h lib/check.h lib/token.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/symboldatabase.h lib/mathlib.h lib/checkuninitvar.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/checkmemoryleak.o $(SRCDIR)/checkmemoryleak.cpp $(SRCDIR)/checknonreentrantfunctions.o: lib/checknonreentrantfunctions.cpp lib/checknonreentrantfunctions.h lib/config.h lib/check.h lib/token.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/checknonreentrantfunctions.o $(SRCDIR)/checknonreentrantfunctions.cpp $(SRCDIR)/checknullpointer.o: lib/checknullpointer.cpp lib/checknullpointer.h lib/config.h lib/check.h lib/token.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/executionpath.h lib/mathlib.h lib/symboldatabase.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/checknullpointer.o $(SRCDIR)/checknullpointer.cpp $(SRCDIR)/checkobsoletefunctions.o: lib/checkobsoletefunctions.cpp lib/checkobsoletefunctions.h lib/config.h lib/check.h lib/token.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/symboldatabase.h lib/mathlib.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/checkobsoletefunctions.o $(SRCDIR)/checkobsoletefunctions.cpp $(SRCDIR)/checkother.o: lib/checkother.cpp lib/checkother.h lib/config.h lib/check.h lib/token.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/mathlib.h lib/symboldatabase.h lib/templatesimplifier.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/checkother.o $(SRCDIR)/checkother.cpp $(SRCDIR)/checkpostfixoperator.o: lib/checkpostfixoperator.cpp lib/checkpostfixoperator.h lib/config.h lib/check.h lib/token.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/symboldatabase.h lib/mathlib.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/checkpostfixoperator.o $(SRCDIR)/checkpostfixoperator.cpp $(SRCDIR)/checksizeof.o: lib/checksizeof.cpp lib/checksizeof.h lib/config.h lib/check.h lib/token.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/symboldatabase.h lib/mathlib.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/checksizeof.o $(SRCDIR)/checksizeof.cpp $(SRCDIR)/checkstl.o: lib/checkstl.cpp lib/checkstl.h lib/config.h lib/check.h lib/token.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/executionpath.h lib/symboldatabase.h lib/mathlib.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/checkstl.o $(SRCDIR)/checkstl.cpp $(SRCDIR)/checkuninitvar.o: lib/checkuninitvar.cpp lib/checkuninitvar.h lib/config.h lib/check.h lib/token.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/mathlib.h lib/executionpath.h lib/checknullpointer.h lib/symboldatabase.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/checkuninitvar.o $(SRCDIR)/checkuninitvar.cpp $(SRCDIR)/checkunusedfunctions.o: lib/checkunusedfunctions.cpp lib/checkunusedfunctions.h lib/config.h lib/check.h lib/token.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/checkunusedfunctions.o $(SRCDIR)/checkunusedfunctions.cpp $(SRCDIR)/checkunusedvar.o: lib/checkunusedvar.cpp lib/checkunusedvar.h lib/config.h lib/check.h lib/token.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/symboldatabase.h lib/mathlib.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/checkunusedvar.o $(SRCDIR)/checkunusedvar.cpp $(SRCDIR)/cppcheck.o: lib/cppcheck.cpp lib/cppcheck.h lib/config.h lib/settings.h lib/library.h lib/suppressions.h lib/standards.h lib/errorlogger.h lib/checkunusedfunctions.h lib/check.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/preprocessor.h lib/path.h lib/timer.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/cppcheck.o $(SRCDIR)/cppcheck.cpp $(SRCDIR)/errorlogger.o: lib/errorlogger.cpp lib/errorlogger.h lib/config.h lib/suppressions.h lib/path.h lib/cppcheck.h lib/settings.h lib/library.h lib/standards.h lib/checkunusedfunctions.h lib/check.h lib/token.h lib/tokenize.h lib/tokenlist.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/errorlogger.o $(SRCDIR)/errorlogger.cpp $(SRCDIR)/executionpath.o: lib/executionpath.cpp lib/executionpath.h lib/config.h lib/token.h lib/symboldatabase.h lib/mathlib.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/executionpath.o $(SRCDIR)/executionpath.cpp $(SRCDIR)/library.o: lib/library.cpp lib/library.h lib/config.h lib/path.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/library.o $(SRCDIR)/library.cpp $(SRCDIR)/mathlib.o: lib/mathlib.cpp lib/mathlib.h lib/config.h lib/errorlogger.h lib/suppressions.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/mathlib.o $(SRCDIR)/mathlib.cpp $(SRCDIR)/path.o: lib/path.cpp lib/path.h lib/config.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/path.o $(SRCDIR)/path.cpp $(SRCDIR)/preprocessor.o: lib/preprocessor.cpp lib/preprocessor.h lib/config.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/token.h lib/path.h lib/settings.h lib/library.h lib/standards.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/preprocessor.o $(SRCDIR)/preprocessor.cpp $(SRCDIR)/settings.o: lib/settings.cpp lib/settings.h lib/config.h lib/library.h lib/suppressions.h lib/standards.h lib/path.h lib/preprocessor.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/settings.o $(SRCDIR)/settings.cpp $(SRCDIR)/suppressions.o: lib/suppressions.cpp lib/suppressions.h lib/config.h lib/settings.h lib/library.h lib/standards.h lib/path.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/suppressions.o $(SRCDIR)/suppressions.cpp $(SRCDIR)/symboldatabase.o: lib/symboldatabase.cpp lib/symboldatabase.h lib/config.h lib/token.h lib/mathlib.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h lib/check.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/symboldatabase.o $(SRCDIR)/symboldatabase.cpp $(SRCDIR)/templatesimplifier.o: lib/templatesimplifier.cpp lib/templatesimplifier.h lib/config.h lib/mathlib.h lib/token.h lib/tokenlist.h lib/errorlogger.h lib/suppressions.h lib/settings.h lib/library.h lib/standards.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/templatesimplifier.o $(SRCDIR)/templatesimplifier.cpp $(SRCDIR)/timer.o: lib/timer.cpp lib/timer.h lib/config.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/timer.o $(SRCDIR)/timer.cpp $(SRCDIR)/token.o: lib/token.cpp lib/token.h lib/config.h lib/errorlogger.h lib/suppressions.h lib/check.h lib/tokenize.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/token.o $(SRCDIR)/token.cpp $(SRCDIR)/tokenize.o: lib/tokenize.cpp lib/tokenize.h lib/errorlogger.h lib/config.h lib/suppressions.h lib/tokenlist.h lib/mathlib.h lib/settings.h lib/library.h lib/standards.h lib/check.h lib/token.h lib/path.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/tokenize.o $(SRCDIR)/tokenize.cpp $(SRCDIR)/tokenlist.o: lib/tokenlist.cpp lib/tokenlist.h lib/config.h lib/token.h lib/mathlib.h lib/path.h lib/preprocessor.h lib/settings.h lib/library.h lib/suppressions.h lib/standards.h lib/errorlogger.h $(CXX) ${INCLUDE_FOR_LIB} $(CPPFLAGS) $(CXXFLAGS) -c -o $(SRCDIR)/tokenlist.o $(SRCDIR)/tokenlist.cpp cli/cmdlineparser.o: cli/cmdlineparser.cpp lib/cppcheck.h lib/config.h lib/settings.h lib/library.h lib/suppressions.h lib/standards.h lib/errorlogger.h lib/checkunusedfunctions.h lib/check.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/timer.h cli/cmdlineparser.h lib/path.h cli/filelister.h $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o cli/cmdlineparser.o cli/cmdlineparser.cpp cli/cppcheckexecutor.o: cli/cppcheckexecutor.cpp cli/cppcheckexecutor.h lib/errorlogger.h lib/config.h lib/suppressions.h lib/cppcheck.h lib/settings.h lib/library.h lib/standards.h lib/checkunusedfunctions.h lib/check.h lib/token.h lib/tokenize.h lib/tokenlist.h cli/threadexecutor.h lib/preprocessor.h cli/cmdlineparser.h cli/filelister.h lib/path.h cli/pathmatch.h $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o cli/cppcheckexecutor.o cli/cppcheckexecutor.cpp cli/filelister.o: cli/filelister.cpp cli/filelister.h lib/path.h lib/config.h $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o cli/filelister.o cli/filelister.cpp cli/main.o: cli/main.cpp cli/cppcheckexecutor.h lib/errorlogger.h lib/config.h lib/suppressions.h $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o cli/main.o cli/main.cpp cli/pathmatch.o: cli/pathmatch.cpp cli/pathmatch.h $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o cli/pathmatch.o cli/pathmatch.cpp cli/threadexecutor.o: cli/threadexecutor.cpp cli/cppcheckexecutor.h lib/errorlogger.h lib/config.h lib/suppressions.h cli/threadexecutor.h lib/cppcheck.h lib/settings.h lib/library.h lib/standards.h lib/checkunusedfunctions.h lib/check.h lib/token.h lib/tokenize.h lib/tokenlist.h $(CXX) ${INCLUDE_FOR_CLI} $(CPPFLAGS) $(CXXFLAGS) -c -o cli/threadexecutor.o cli/threadexecutor.cpp test/options.o: test/options.cpp test/options.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/options.o test/options.cpp test/test64bit.o: test/test64bit.cpp lib/tokenize.h lib/errorlogger.h lib/config.h lib/suppressions.h lib/tokenlist.h lib/check64bit.h lib/check.h lib/token.h lib/settings.h lib/library.h lib/standards.h test/testsuite.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/test64bit.o test/test64bit.cpp test/testassert.o: test/testassert.cpp lib/tokenize.h lib/errorlogger.h lib/config.h lib/suppressions.h lib/tokenlist.h lib/checkassert.h lib/check.h lib/token.h lib/settings.h lib/library.h lib/standards.h test/testsuite.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testassert.o test/testassert.cpp test/testassignif.o: test/testassignif.cpp lib/tokenize.h lib/errorlogger.h lib/config.h lib/suppressions.h lib/tokenlist.h lib/checkassignif.h lib/check.h lib/token.h lib/settings.h lib/library.h lib/standards.h lib/mathlib.h test/testsuite.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testassignif.o test/testassignif.cpp test/testautovariables.o: test/testautovariables.cpp lib/tokenize.h lib/errorlogger.h lib/config.h lib/suppressions.h lib/tokenlist.h lib/checkautovariables.h lib/check.h lib/token.h lib/settings.h lib/library.h lib/standards.h test/testsuite.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testautovariables.o test/testautovariables.cpp test/testbool.o: test/testbool.cpp lib/tokenize.h lib/errorlogger.h lib/config.h lib/suppressions.h lib/tokenlist.h lib/checkbool.h lib/check.h lib/token.h lib/settings.h lib/library.h lib/standards.h test/testsuite.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testbool.o test/testbool.cpp test/testboost.o: test/testboost.cpp lib/tokenize.h lib/errorlogger.h lib/config.h lib/suppressions.h lib/tokenlist.h lib/checkboost.h lib/check.h lib/token.h lib/settings.h lib/library.h lib/standards.h test/testsuite.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testboost.o test/testboost.cpp test/testbufferoverrun.o: test/testbufferoverrun.cpp lib/tokenize.h lib/errorlogger.h lib/config.h lib/suppressions.h lib/tokenlist.h lib/checkbufferoverrun.h lib/check.h lib/token.h lib/settings.h lib/library.h lib/standards.h lib/mathlib.h test/testsuite.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testbufferoverrun.o test/testbufferoverrun.cpp test/testcharvar.o: test/testcharvar.cpp lib/tokenize.h lib/errorlogger.h lib/config.h lib/suppressions.h lib/tokenlist.h lib/checkother.h lib/check.h lib/token.h lib/settings.h lib/library.h lib/standards.h test/testsuite.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testcharvar.o test/testcharvar.cpp test/testclass.o: test/testclass.cpp lib/tokenize.h lib/errorlogger.h lib/config.h lib/suppressions.h lib/tokenlist.h lib/checkclass.h lib/check.h lib/token.h lib/settings.h lib/library.h lib/standards.h test/testsuite.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testclass.o test/testclass.cpp test/testcmdlineparser.o: test/testcmdlineparser.cpp test/testsuite.h lib/errorlogger.h lib/config.h lib/suppressions.h test/redirect.h lib/settings.h lib/library.h lib/standards.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testcmdlineparser.o test/testcmdlineparser.cpp test/testconstructors.o: test/testconstructors.cpp lib/tokenize.h lib/errorlogger.h lib/config.h lib/suppressions.h lib/tokenlist.h lib/checkclass.h lib/check.h lib/token.h lib/settings.h lib/library.h lib/standards.h test/testsuite.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testconstructors.o test/testconstructors.cpp test/testcppcheck.o: test/testcppcheck.cpp lib/cppcheck.h lib/config.h lib/settings.h lib/library.h lib/suppressions.h lib/standards.h lib/errorlogger.h lib/checkunusedfunctions.h lib/check.h lib/token.h lib/tokenize.h lib/tokenlist.h test/testsuite.h test/redirect.h lib/path.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testcppcheck.o test/testcppcheck.cpp test/testdivision.o: test/testdivision.cpp lib/tokenize.h lib/errorlogger.h lib/config.h lib/suppressions.h lib/tokenlist.h lib/checkother.h lib/check.h lib/token.h lib/settings.h lib/library.h lib/standards.h test/testsuite.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testdivision.o test/testdivision.cpp test/testerrorlogger.o: test/testerrorlogger.cpp lib/cppcheck.h lib/config.h lib/settings.h lib/library.h lib/suppressions.h lib/standards.h lib/errorlogger.h lib/checkunusedfunctions.h lib/check.h lib/token.h lib/tokenize.h lib/tokenlist.h test/testsuite.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testerrorlogger.o test/testerrorlogger.cpp test/testexceptionsafety.o: test/testexceptionsafety.cpp lib/tokenize.h lib/errorlogger.h lib/config.h lib/suppressions.h lib/tokenlist.h lib/checkexceptionsafety.h lib/check.h lib/token.h lib/settings.h lib/library.h lib/standards.h test/testsuite.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testexceptionsafety.o test/testexceptionsafety.cpp test/testfilelister.o: test/testfilelister.cpp test/testsuite.h lib/errorlogger.h lib/config.h lib/suppressions.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testfilelister.o test/testfilelister.cpp test/testincompletestatement.o: test/testincompletestatement.cpp test/testsuite.h lib/errorlogger.h lib/config.h lib/suppressions.h test/redirect.h lib/tokenize.h lib/tokenlist.h lib/checkother.h lib/check.h lib/token.h lib/settings.h lib/library.h lib/standards.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testincompletestatement.o test/testincompletestatement.cpp test/testinternal.o: test/testinternal.cpp lib/tokenize.h lib/errorlogger.h lib/config.h lib/suppressions.h lib/tokenlist.h lib/checkinternal.h lib/check.h lib/token.h lib/settings.h lib/library.h lib/standards.h test/testsuite.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testinternal.o test/testinternal.cpp test/testio.o: test/testio.cpp lib/checkio.h lib/check.h lib/config.h lib/token.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/settings.h lib/library.h lib/standards.h test/testsuite.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testio.o test/testio.cpp test/testleakautovar.o: test/testleakautovar.cpp lib/tokenize.h lib/errorlogger.h lib/config.h lib/suppressions.h lib/tokenlist.h lib/checkleakautovar.h lib/check.h lib/token.h lib/settings.h lib/library.h lib/standards.h test/testsuite.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testleakautovar.o test/testleakautovar.cpp test/testmathlib.o: test/testmathlib.cpp lib/mathlib.h lib/config.h test/testsuite.h lib/errorlogger.h lib/suppressions.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testmathlib.o test/testmathlib.cpp test/testmemleak.o: test/testmemleak.cpp lib/tokenize.h lib/errorlogger.h lib/config.h lib/suppressions.h lib/tokenlist.h lib/checkmemoryleak.h lib/check.h lib/token.h lib/settings.h lib/library.h lib/standards.h test/testsuite.h test/redirect.h lib/symboldatabase.h lib/mathlib.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testmemleak.o test/testmemleak.cpp test/testnonreentrantfunctions.o: test/testnonreentrantfunctions.cpp lib/tokenize.h lib/errorlogger.h lib/config.h lib/suppressions.h lib/tokenlist.h lib/checknonreentrantfunctions.h lib/check.h lib/token.h lib/settings.h lib/library.h lib/standards.h test/testsuite.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testnonreentrantfunctions.o test/testnonreentrantfunctions.cpp test/testnullpointer.o: test/testnullpointer.cpp lib/tokenize.h lib/errorlogger.h lib/config.h lib/suppressions.h lib/tokenlist.h lib/checknullpointer.h lib/check.h lib/token.h lib/settings.h lib/library.h lib/standards.h test/testsuite.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testnullpointer.o test/testnullpointer.cpp test/testobsoletefunctions.o: test/testobsoletefunctions.cpp lib/tokenize.h lib/errorlogger.h lib/config.h lib/suppressions.h lib/tokenlist.h lib/checkobsoletefunctions.h lib/check.h lib/token.h lib/settings.h lib/library.h lib/standards.h test/testsuite.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testobsoletefunctions.o test/testobsoletefunctions.cpp test/testoptions.o: test/testoptions.cpp test/options.h test/testsuite.h lib/errorlogger.h lib/config.h lib/suppressions.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testoptions.o test/testoptions.cpp test/testother.o: test/testother.cpp lib/preprocessor.h lib/config.h lib/tokenize.h lib/errorlogger.h lib/suppressions.h lib/tokenlist.h lib/checkother.h lib/check.h lib/token.h lib/settings.h lib/library.h lib/standards.h test/testsuite.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testother.o test/testother.cpp test/testpath.o: test/testpath.cpp test/testsuite.h lib/errorlogger.h lib/config.h lib/suppressions.h test/redirect.h lib/path.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testpath.o test/testpath.cpp test/testpathmatch.o: test/testpathmatch.cpp test/testsuite.h lib/errorlogger.h lib/config.h lib/suppressions.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testpathmatch.o test/testpathmatch.cpp test/testpostfixoperator.o: test/testpostfixoperator.cpp lib/tokenize.h lib/errorlogger.h lib/config.h lib/suppressions.h lib/tokenlist.h lib/checkpostfixoperator.h lib/check.h lib/token.h lib/settings.h lib/library.h lib/standards.h test/testsuite.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testpostfixoperator.o test/testpostfixoperator.cpp test/testpreprocessor.o: test/testpreprocessor.cpp test/testsuite.h lib/errorlogger.h lib/config.h lib/suppressions.h test/redirect.h lib/preprocessor.h lib/tokenize.h lib/tokenlist.h lib/token.h lib/settings.h lib/library.h lib/standards.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testpreprocessor.o test/testpreprocessor.cpp test/testrunner.o: test/testrunner.cpp test/testsuite.h lib/errorlogger.h lib/config.h lib/suppressions.h test/redirect.h test/options.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testrunner.o test/testrunner.cpp test/testsimplifytokens.o: test/testsimplifytokens.cpp test/testsuite.h lib/errorlogger.h lib/config.h lib/suppressions.h test/redirect.h lib/tokenize.h lib/tokenlist.h lib/token.h lib/settings.h lib/library.h lib/standards.h lib/templatesimplifier.h lib/path.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testsimplifytokens.o test/testsimplifytokens.cpp test/testsizeof.o: test/testsizeof.cpp lib/tokenize.h lib/errorlogger.h lib/config.h lib/suppressions.h lib/tokenlist.h lib/checksizeof.h lib/check.h lib/token.h lib/settings.h lib/library.h lib/standards.h test/testsuite.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testsizeof.o test/testsizeof.cpp test/teststl.o: test/teststl.cpp lib/tokenize.h lib/errorlogger.h lib/config.h lib/suppressions.h lib/tokenlist.h lib/checkstl.h lib/check.h lib/token.h lib/settings.h lib/library.h lib/standards.h test/testsuite.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/teststl.o test/teststl.cpp test/testsuite.o: test/testsuite.cpp test/testsuite.h lib/errorlogger.h lib/config.h lib/suppressions.h test/redirect.h test/options.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testsuite.o test/testsuite.cpp test/testsuppressions.o: test/testsuppressions.cpp lib/cppcheck.h lib/config.h lib/settings.h lib/library.h lib/suppressions.h lib/standards.h lib/errorlogger.h lib/checkunusedfunctions.h lib/check.h lib/token.h lib/tokenize.h lib/tokenlist.h test/testsuite.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testsuppressions.o test/testsuppressions.cpp test/testsymboldatabase.o: test/testsymboldatabase.cpp test/testsuite.h lib/errorlogger.h lib/config.h lib/suppressions.h test/redirect.h test/testutils.h lib/settings.h lib/library.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/symboldatabase.h lib/token.h lib/mathlib.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testsymboldatabase.o test/testsymboldatabase.cpp test/testthreadexecutor.o: test/testthreadexecutor.cpp lib/cppcheck.h lib/config.h lib/settings.h lib/library.h lib/suppressions.h lib/standards.h lib/errorlogger.h lib/checkunusedfunctions.h lib/check.h lib/token.h lib/tokenize.h lib/tokenlist.h test/testsuite.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testthreadexecutor.o test/testthreadexecutor.cpp test/testtimer.o: test/testtimer.cpp lib/timer.h lib/config.h test/testsuite.h lib/errorlogger.h lib/suppressions.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testtimer.o test/testtimer.cpp test/testtoken.o: test/testtoken.cpp test/testsuite.h lib/errorlogger.h lib/config.h lib/suppressions.h test/redirect.h test/testutils.h lib/settings.h lib/library.h lib/standards.h lib/tokenize.h lib/tokenlist.h lib/token.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testtoken.o test/testtoken.cpp test/testtokenize.o: test/testtokenize.cpp test/testsuite.h lib/errorlogger.h lib/config.h lib/suppressions.h test/redirect.h lib/tokenize.h lib/tokenlist.h lib/token.h lib/settings.h lib/library.h lib/standards.h lib/path.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testtokenize.o test/testtokenize.cpp test/testuninitvar.o: test/testuninitvar.cpp lib/tokenize.h lib/errorlogger.h lib/config.h lib/suppressions.h lib/tokenlist.h lib/checkuninitvar.h lib/check.h lib/token.h lib/settings.h lib/library.h lib/standards.h test/testsuite.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testuninitvar.o test/testuninitvar.cpp test/testunusedfunctions.o: test/testunusedfunctions.cpp lib/tokenize.h lib/errorlogger.h lib/config.h lib/suppressions.h lib/tokenlist.h test/testsuite.h test/redirect.h lib/checkunusedfunctions.h lib/check.h lib/token.h lib/settings.h lib/library.h lib/standards.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testunusedfunctions.o test/testunusedfunctions.cpp test/testunusedprivfunc.o: test/testunusedprivfunc.cpp lib/tokenize.h lib/errorlogger.h lib/config.h lib/suppressions.h lib/tokenlist.h lib/checkclass.h lib/check.h lib/token.h lib/settings.h lib/library.h lib/standards.h test/testsuite.h test/redirect.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testunusedprivfunc.o test/testunusedprivfunc.cpp test/testunusedvar.o: test/testunusedvar.cpp test/testsuite.h lib/errorlogger.h lib/config.h lib/suppressions.h test/redirect.h lib/tokenize.h lib/tokenlist.h lib/checkunusedvar.h lib/check.h lib/token.h lib/settings.h lib/library.h lib/standards.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CXXFLAGS) -c -o test/testunusedvar.o test/testunusedvar.cpp cppcheck-1.61/build-pcre.txt000066400000000000000000000031131217722632100160110ustar00rootroot00000000000000PCRE is a library that is used by the optional "rules" feature. (It adds some additional features to the command line client.) It's readily available on Linux and Mac OS X, but must be obtained separately for Windows. If you're using qmake to generate makefiles, the following behavior applies: - If you're not on Windows, it assumes by default that you have PCRE and want to enable rules support. - If you're not on Windows, you can disable rules support (removing the PCRE dependency) by passing HAVE_RULES=no to qmake. - If you are on Windows, but have PCRE available, you can enable rules support by passing HAVE_RULES=yes to qmake. - Note: This includes using build.bat since it calls qmake - to use PCRE and build.bat, you need to run set HAVE_RULES=yes before each run of build.bat Some temporary build instructions. This is work in progress. Windows Visual Studio To build pcre I downloaded the sourcecode from www.pcre.org. I downloaded cmake 2.8. Then I built the lib with: cmake . nmake The resulting files can be downloaded here (please try if it works): http://cppcheck.sourceforge.net/pcre-8.10-vs.zip MINGW (Qt 4.7 SDK) I downloaded pcre-8.0-lib.zip from here: http://software-download.name/pcre-library-windows/ Linux The normal Makefile should work Install pcre on ubuntu might be needed: sudo apt-get install libpcre3 libpcre3-dev Mac OSX Install pcre: sudo port install pcre Ensure /path/to/pcre.h is in CXXFLAGS, e.g: export CXXFLAGS=${CXXFLAGS}:/opt/local/include cppcheck-1.61/build.bat000066400000000000000000000031311217722632100150110ustar00rootroot00000000000000@echo off REM A simple script to build different cppcheck targets from project root REM folder. This script can be run from VS prompt or Qt prompt. REM REM Usage: build [release|debug] REM where is any of cppcheck/gui/tests/all REM release or debug is the configuration REM all-target builds both cppcheck and gui. REM REM Run the command before build.bat to enable rules using pcre: REM set HAVE_RULES=yes REM REM TODO: REM - run tests too pushd %~dp0 if "%1" == "" goto help REM Qt prompt sets QMAKESPEC if "%QMAKESPEC%" == "" ( REM parse qmakespec to see if it's some msvc if "%QMAKESPEC:~6,4%" == "msvc" ( set MAKE=nmake ) else ( set MAKE=mingw32-make ) ) else ( set MAKE=nmake ) if "%2" == "" set TARGET=release if "%2" == "debug" set TARGET=debug if "%2" == "release" set TARGET=release if "%1" == "all" goto cppcheck if "%1" == "cppcheck" goto cppcheck if "%1" == "gui" goto gui if "%1" == "tests" goto tests goto help :cppcheck pushd cli qmake -config %TARGET% HAVE_RULES=%HAVE_RULES% %MAKE% popd if "%1" == "all" goto gui goto end :gui pushd gui qmake -config %TARGET% HAVE_RULES=%HAVE_RULES% %MAKE% lupdate -no-obsolete gui.pro lrelease gui.pro popd goto end :tests pushd test qmake -config %TARGET% HAVE_RULES=%HAVE_RULES% %MAKE% popd goto end :help echo Syntax: build ^ [debug^|release] echo where ^ is any of cppcheck/gui/tests/all echo debug or release define used configuration echo all- target builds both cppcheck and gui. :end cppcheck-1.61/cfg/000077500000000000000000000000001217722632100137635ustar00rootroot00000000000000cppcheck-1.61/cfg/gtk.cfg000066400000000000000000000011441217722632100152310ustar00rootroot00000000000000 g_free g_new g_new0 g_try_new g_try_new0 g_malloc g_malloc0 g_try_malloc g_try_malloc0 g_strdup g_strndup g_strdup_printf g_register_data false true cppcheck-1.61/cfg/std.cfg000066400000000000000000000005221217722632100152350ustar00rootroot00000000000000 free malloc calloc strdup strndup fclose fopen cppcheck-1.61/cli/000077500000000000000000000000001217722632100137735ustar00rootroot00000000000000cppcheck-1.61/cli/cli.pro000066400000000000000000000015201217722632100152620ustar00rootroot00000000000000TEMPLATE = app TARGET = cppcheck DEPENDPATH += . INCLUDEPATH += . ../lib OBJECTS_DIR = temp CONFIG += warn_on CONFIG -= qt app_bundle include(../console_common.pri) BASEPATH = ../externals/tinyxml/ include($$PWD/../externals/tinyxml/tinyxml.pri) BASEPATH = ../lib/ include($$PWD/../lib/lib.pri) SOURCES += main.cpp \ cppcheckexecutor.cpp \ cmdlineparser.cpp \ filelister.cpp \ pathmatch.cpp \ threadexecutor.cpp HEADERS += cppcheckexecutor.h \ cmdlineparser.h \ filelister.h \ pathmatch.h \ threadexecutor.h win32 { RC_FILE = version.rc HEADERS += ../lib/version.h } # Enable STL checking in GCC debug builds contains(QMAKE_CXX, g++) { CONFIG(debug, debug|release) { # checked STL DEFINES += _GLIBCXX_DEBUG } } cppcheck-1.61/cli/cli.vcxproj000066400000000000000000000601631217722632100161650ustar00rootroot00000000000000 Debug-PCRE Win32 Debug-PCRE x64 Debug Win32 Debug x64 Release-PCRE Win32 Release-PCRE x64 Release Win32 Release x64 {35CBDF51-2456-3EC3-99ED-113C30858883} cli Application Unicode false Application Unicode false Application Unicode false Application Unicode false Application Unicode false Application Unicode false Application Unicode false Application Unicode false ..\bin\debug\ ..\bin\debug\ ..\bin\debug\ ..\bin\debug\ temp\$(Configuration)_$(PlatformName)\ temp\$(Configuration)_$(PlatformName)\ temp\$(Configuration)_$(PlatformName)\ temp\$(Configuration)_$(PlatformName)\ cppcheck cppcheck cppcheck cppcheck true true true true ..\bin\ ..\bin\ ..\bin\ ..\bin\ temp\$(Configuration)_$(PlatformName)\ temp\$(Configuration)_$(PlatformName)\ temp\$(Configuration)_$(PlatformName)\ temp\$(Configuration)_$(PlatformName)\ cppcheck cppcheck cppcheck cppcheck true true true true true true true true ..\lib;..\externals;..\externals\tinyxml;%(AdditionalIncludeDirectories) false true ProgramDatabase Disabled CPPCHECKLIB_IMPORT;WIN32;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions) MultiThreadedDebugDLL true Level4 4251;4512 true shlwapi.lib;%(AdditionalDependencies) ../externals;%(AdditionalLibraryDirectories) true Console true $(TargetDir)cli.pdb ..\lib;..\externals;..\externals\tinyxml;%(AdditionalIncludeDirectories) false true ProgramDatabase Disabled CPPCHECKLIB_IMPORT;WIN32;HAVE_RULES;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;TIXML_USE_STL;%(PreprocessorDefinitions) MultiThreadedDebugDLL true Level4 4251;4512 true shlwapi.lib;%(AdditionalDependencies) ../externals;%(AdditionalLibraryDirectories) true Console true ..\lib;..\externals;..\externals\tinyxml;%(AdditionalIncludeDirectories) true ProgramDatabase Disabled CPPCHECKLIB_IMPORT;WIN32;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_WIN64;%(PreprocessorDefinitions) MultiThreadedDebugDLL true Level4 4251;4512 true shlwapi.lib;%(AdditionalDependencies) ../externals;%(AdditionalLibraryDirectories) true Console true ..\lib;..\externals;..\externals\tinyxml;%(AdditionalIncludeDirectories) true ProgramDatabase Disabled CPPCHECKLIB_IMPORT;WIN32;HAVE_RULES;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_WIN64;%(PreprocessorDefinitions) MultiThreadedDebugDLL true Level4 4251;4512 true shlwapi.lib;%(AdditionalDependencies) ../externals;%(AdditionalLibraryDirectories) true Console true ..\lib;..\externals;..\externals\tinyxml;%(AdditionalIncludeDirectories) false MaxSpeed CPPCHECKLIB_IMPORT;NDEBUG;WIN32;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;%(PreprocessorDefinitions) MultiThreadedDLL true Level4 AnySuitable true Speed true true 4251;4512 true shlwapi.lib;%(AdditionalDependencies) ../externals;%(AdditionalLibraryDirectories) false Console true true true true ..\lib;..\externals;..\externals\tinyxml;%(AdditionalIncludeDirectories) false MaxSpeed CPPCHECKLIB_IMPORT;NDEBUG;WIN32;HAVE_RULES;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;TIXML_USE_STL;%(PreprocessorDefinitions) MultiThreadedDLL true Level4 AnySuitable true Speed true true 4251;4512 true shlwapi.lib;%(AdditionalDependencies) ../externals;%(AdditionalLibraryDirectories) false Console true true true true ..\lib;..\externals;..\externals\tinyxml;%(AdditionalIncludeDirectories) false MaxSpeed CPPCHECKLIB_IMPORT;NDEBUG;WIN32;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_WIN64;%(PreprocessorDefinitions) MultiThreadedDLL true Level4 AnySuitable true Speed true true true 4251;4512 true shlwapi.lib;%(AdditionalDependencies) ../externals;%(AdditionalLibraryDirectories) false Console true true true true ..\lib;..\externals;..\externals\tinyxml;%(AdditionalIncludeDirectories) false MaxSpeed CPPCHECKLIB_IMPORT;NDEBUG;WIN32;HAVE_RULES;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_WIN64;%(PreprocessorDefinitions) MultiThreadedDLL true Level4 AnySuitable true Speed true true true 4251;4512 true shlwapi.lib;%(AdditionalDependencies) ../externals;%(AdditionalLibraryDirectories) false Console true true true true true true true true {c183db5b-ad6c-423d-80ca-1f9549555a1a} true true true true cppcheck-1.61/cli/cli.vcxproj.filters000066400000000000000000000044101217722632100176250ustar00rootroot00000000000000 {93995380-89BD-4b04-88EB-625FBE52EBFB} h;hpp;hxx;hm;inl;inc;xsd {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx {6d3be647-edb6-43e6-a7eb-3031a2c7b655} Header Files Header Files Header Files Header Files Header Files Header Files Header Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Resource Files cppcheck-1.61/cli/cmdlineparser.cpp000066400000000000000000001176521217722632100173430ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include #include #include #include #include #include // EXIT_FAILURE #include "cppcheck.h" #include "timer.h" #include "settings.h" #include "cmdlineparser.h" #include "path.h" #include "filelister.h" #ifdef HAVE_RULES // xml is used in rules #include #endif static void AddFilesToList(const std::string& FileList, std::vector& PathNames) { // to keep things initially simple, if the file can't be opened, just be // silent and move on // ideas : we could also require this should be an xml file, with the filenames // specified in an xml structure // we could elaborate this then, to also include the I-paths, ... // basically for everything that makes the command line very long // xml is a bonus then, since we can easily extend it // we need a good parser then -> suggestion : TinyXml // drawback : creates a dependency std::istream *Files; std::ifstream Infile; if (FileList.compare("-") == 0) { // read from stdin Files = &std::cin; } else { Infile.open(FileList.c_str()); Files = &Infile; } if (Files) { std::string FileName; while (std::getline(*Files, FileName)) { // next line if (!FileName.empty()) { PathNames.push_back(FileName); } } } } static void AddInclPathsToList(const std::string& FileList, std::list& PathNames) { // to keep things initially simple, if the file can't be opened, just be // silent and move on std::ifstream Files(FileList.c_str()); if (Files) { std::string PathName; while (std::getline(Files, PathName)) { // next line if (!PathName.empty()) { PathName = Path::fromNativeSeparators(PathName); PathName = Path::removeQuotationMarks(PathName); // If path doesn't end with / or \, add it if (PathName[PathName.length()-1] != '/') PathName += '/'; PathNames.push_back(PathName); } } } } CmdLineParser::CmdLineParser(Settings *settings) : _settings(settings) , _showHelp(false) , _showVersion(false) , _showErrorMessages(false) , _exitAfterPrint(false) { } void CmdLineParser::PrintMessage(const std::string &message) { std::cout << message << std::endl; } bool CmdLineParser::ParseFromArgs(int argc, const char* const argv[]) { bool def = false; bool maxconfigs = false; for (int i = 1; i < argc; i++) { if (std::strcmp(argv[i], "--version") == 0) { _showVersion = true; _exitAfterPrint = true; return true; } // Flag used for various purposes during debugging else if (std::strcmp(argv[i], "--debug") == 0) _settings->debug = _settings->debugwarnings = true; // Show debug warnings else if (std::strcmp(argv[i], "--debug-warnings") == 0) _settings->debugwarnings = true; // Print out code that triggers false positive else if (std::strcmp(argv[i], "--debug-fp") == 0) _settings->debugFalsePositive = true; // Inconclusive checking (still in testing phase) else if (std::strcmp(argv[i], "--inconclusive") == 0) _settings->inconclusive = true; // Enforce language (--language=, -x) else if (std::strncmp(argv[i], "--language=", 11) == 0 || std::strcmp(argv[i], "-x") == 0) { std::string str; if (argv[i][2]) { str = argv[i]+11; } else { i++; if (i >= argc || argv[i][0] == '-') { PrintMessage("cppcheck: No language given to '-x' option."); return false; } str = argv[i]; } if (str == "c") _settings->enforcedLang = Settings::C; else if (str == "c++") _settings->enforcedLang = Settings::CPP; else { PrintMessage("cppcheck: Unknown language '" + str + "' enforced."); return false; } } // Filter errors else if (std::strncmp(argv[i], "--exitcode-suppressions", 23) == 0) { std::string filename; // exitcode-suppressions filename.txt // Deprecated if (std::strcmp(argv[i], "--exitcode-suppressions") == 0) { ++i; if (i >= argc || std::strncmp(argv[i], "-", 1) == 0 || std::strncmp(argv[i], "--", 2) == 0) { PrintMessage("cppcheck: No filename specified for the '--exitcode-suppressions' option."); return false; } filename = argv[i]; } // exitcode-suppressions=filename.txt else { filename = 24 + argv[i]; } std::ifstream f(filename.c_str()); if (!f.is_open()) { PrintMessage("cppcheck: Couldn't open the file: \"" + filename + "\"."); return false; } const std::string errmsg(_settings->nofail.parseFile(f)); if (!errmsg.empty()) { PrintMessage(errmsg); return false; } } // Filter errors else if (std::strncmp(argv[i], "--suppressions-list=", 20) == 0) { std::string filename = argv[i]+20; std::ifstream f(filename.c_str()); if (!f.is_open()) { std::string message("cppcheck: Couldn't open the file: \""); message += filename; message += "\"."; if (std::count(filename.begin(), filename.end(), ',') > 0 || std::count(filename.begin(), filename.end(), '.') > 1) { // If user tried to pass multiple files (we can only guess that) // e.g. like this: --suppressions-list=a.txt,b.txt // print more detailed error message to tell user how he can solve the problem message += "\nIf you want to pass two files, you can do it e.g. like this:"; message += "\n cppcheck --suppressions-list=a.txt --suppressions-list=b.txt file.cpp"; } PrintMessage(message); return false; } const std::string errmsg(_settings->nomsg.parseFile(f)); if (!errmsg.empty()) { PrintMessage(errmsg); return false; } } // Filter errors // This is deprecated, see --suppressions-list above else if (std::strcmp(argv[i], "--suppressions") == 0) { ++i; if (i >= argc) { PrintMessage("cppcheck: No file specified for the '--suppressions' option."); return false; } std::ifstream f(argv[i]); if (!f.is_open()) { std::string message("cppcheck: Couldn't open the file: \""); message += std::string(argv[i]); message += "\"."; PrintMessage(message); return false; } const std::string errmsg(_settings->nomsg.parseFile(f)); if (!errmsg.empty()) { PrintMessage(errmsg); return false; } } else if (std::strncmp(argv[i], "--suppress=", 11) == 0) { std::string suppression = argv[i]+11; const std::string errmsg(_settings->nomsg.addSuppressionLine(suppression)); if (!errmsg.empty()) { PrintMessage(errmsg); return false; } } // Enables inline suppressions. else if (std::strcmp(argv[i], "--inline-suppr") == 0) _settings->_inlineSuppressions = true; // Verbose error messages (configuration info) else if (std::strcmp(argv[i], "-v") == 0 || std::strcmp(argv[i], "--verbose") == 0) _settings->_verbose = true; // Force checking of files that have "too many" configurations else if (std::strcmp(argv[i], "-f") == 0 || std::strcmp(argv[i], "--force") == 0) _settings->_force = true; // Output relative paths else if (std::strcmp(argv[i], "-rp") == 0 || std::strcmp(argv[i], "--relative-paths") == 0) _settings->_relativePaths = true; else if (std::strncmp(argv[i], "-rp=", 4) == 0 || std::strncmp(argv[i], "--relative-paths=", 17) == 0) { _settings->_relativePaths = true; if (argv[i][argv[i][3]=='='?4:17] != 0) { std::string paths = argv[i]+(argv[i][3]=='='?4:17); std::string::size_type pos; do { pos = paths.find(';'); _settings->_basePaths.push_back(Path::fromNativeSeparators(paths.substr(0, pos))); paths.erase(0, pos+1); } while (pos != std::string::npos); } else { PrintMessage("cppcheck: No paths specified for the '" + std::string(argv[i]) + "' option."); return false; } } // Write results in results.xml else if (std::strcmp(argv[i], "--xml") == 0) _settings->_xml = true; // Define the XML file version (and enable XML output) else if (std::strncmp(argv[i], "--xml-version=", 14) == 0) { std::string numberString(argv[i]+14); std::istringstream iss(numberString); if (!(iss >> _settings->_xml_version)) { PrintMessage("cppcheck: argument to '--xml-version' is not a number."); return false; } if (_settings->_xml_version < 0 || _settings->_xml_version > 2) { // We only have xml versions 1 and 2 PrintMessage("cppcheck: '--xml-version' can only be 1 or 2."); return false; } // Enable also XML if version is set _settings->_xml = true; } // Only print something when there are errors else if (std::strcmp(argv[i], "-q") == 0 || std::strcmp(argv[i], "--quiet") == 0) _settings->_errorsOnly = true; // Append userdefined code to checked source code else if (std::strncmp(argv[i], "--append=", 9) == 0) { const std::string filename = 9 + argv[i]; if (!_settings->append(filename)) { PrintMessage("cppcheck: Couldn't open the file: \"" + filename + "\"."); return false; } } // Check configuration else if (std::strcmp(argv[i], "--check-config") == 0) { _settings->checkConfiguration = true; } // Check library definitions else if (std::strcmp(argv[i], "--check-library") == 0) { _settings->checkLibrary = true; } else if (std::strncmp(argv[i], "--enable=", 9) == 0) { const std::string errmsg = _settings->addEnabled(argv[i] + 9); if (!errmsg.empty()) { PrintMessage(errmsg); return false; } // when "style" is enabled, also enable "warning", "performance" and "portability" if (_settings->isEnabled("style")) { _settings->addEnabled("warning"); _settings->addEnabled("performance"); _settings->addEnabled("portability"); } } // --error-exitcode=1 else if (std::strncmp(argv[i], "--error-exitcode=", 17) == 0) { std::string temp = argv[i]+17; std::istringstream iss(temp); if (!(iss >> _settings->_exitCode)) { _settings->_exitCode = 0; PrintMessage("cppcheck: Argument must be an integer. Try something like '--error-exitcode=1'."); return false; } } // User define else if (std::strncmp(argv[i], "-D", 2) == 0) { std::string define; // "-D define" if (std::strcmp(argv[i], "-D") == 0) { ++i; if (i >= argc || argv[i][0] == '-') { PrintMessage("cppcheck: argument to '-D' is missing."); return false; } define = argv[i]; } // "-Ddefine" else { define = 2 + argv[i]; } // No "=", append a "=1" if (define.find("=") == std::string::npos) define += "=1"; // DEF= => empty define else if (define.find("=") + 1U == define.size()) define.erase(define.size() - 1U); if (!_settings->userDefines.empty()) _settings->userDefines += ";"; _settings->userDefines += define; def = true; } // User undef else if (std::strncmp(argv[i], "-U", 2) == 0) { std::string undef; // "-U undef" if (std::strcmp(argv[i], "-U") == 0) { ++i; if (i >= argc || argv[i][0] == '-') { PrintMessage("cppcheck: argument to '-U' is missing."); return false; } undef = argv[i]; } // "-Uundef" else { undef = 2 + argv[i]; } _settings->userUndefs.insert(undef); } // Include paths else if (std::strncmp(argv[i], "-I", 2) == 0) { std::string path; // "-I path/" if (std::strcmp(argv[i], "-I") == 0) { ++i; if (i >= argc || argv[i][0] == '-') { PrintMessage("cppcheck: argument to '-I' is missing."); return false; } path = argv[i]; } // "-Ipath/" else { path = 2 + argv[i]; } path = Path::fromNativeSeparators(path); path = Path::removeQuotationMarks(path); // If path doesn't end with / or \, add it if (path[path.length()-1] != '/') path += '/'; _settings->_includePaths.push_back(path); } else if (std::strncmp(argv[i], "--include=", 10) == 0) { std::string path = argv[i] + 10; path = Path::fromNativeSeparators(path); _settings->userIncludes.push_back(path); } else if (std::strncmp(argv[i], "--includes-file=", 16) == 0) { // open this file and read every input file (1 file name per line) AddInclPathsToList(16 + argv[i], _settings->_includePaths); } // file list specified else if (std::strncmp(argv[i], "--file-list=", 12) == 0) { // open this file and read every input file (1 file name per line) AddFilesToList(12 + argv[i], _pathnames); } // Ignored paths else if (std::strncmp(argv[i], "-i", 2) == 0) { std::string path; // "-i path/" if (std::strcmp(argv[i], "-i") == 0) { ++i; if (i >= argc || argv[i][0] == '-') { PrintMessage("cppcheck: argument to '-i' is missing."); return false; } path = argv[i]; } // "-ipath/" else { path = 2 + argv[i]; } if (!path.empty()) { path = Path::fromNativeSeparators(path); path = Path::simplifyPath(path.c_str()); path = Path::removeQuotationMarks(path); if (FileLister::isDirectory(path)) { // If directory name doesn't end with / or \, add it if (path[path.length()-1] != '/') path += '/'; } _ignoredPaths.push_back(path); } } // --library else if (std::strncmp(argv[i], "--library=", 10) == 0) { if (!_settings->library.load(argv[0], argv[i]+10)) { PrintMessage("cppcheck: Failed to load library configuration file '" + std::string(argv[i]+10) + "'"); return false; } } // Report progress else if (std::strcmp(argv[i], "--report-progress") == 0) { _settings->reportProgress = true; } // --std else if (std::strcmp(argv[i], "--std=posix") == 0) { _settings->standards.posix = true; } else if (std::strcmp(argv[i], "--std=c89") == 0) { _settings->standards.c = Standards::C89; } else if (std::strcmp(argv[i], "--std=c99") == 0) { _settings->standards.c = Standards::C99; } else if (std::strcmp(argv[i], "--std=c11") == 0) { _settings->standards.c = Standards::C11; } else if (std::strcmp(argv[i], "--std=c++03") == 0) { _settings->standards.cpp = Standards::CPP03; } else if (std::strcmp(argv[i], "--std=c++11") == 0) { _settings->standards.cpp = Standards::CPP11; } // Output formatter else if (std::strcmp(argv[i], "--template") == 0 || std::strncmp(argv[i], "--template=", 11) == 0) { // "--template path/" if (argv[i][10] == '=') _settings->_outputFormat = argv[i] + 11; else if ((i+1) < argc && argv[i+1][0] != '-') { ++i; _settings->_outputFormat = argv[i]; } else { PrintMessage("cppcheck: argument to '--template' is missing."); return false; } if (_settings->_outputFormat == "gcc") _settings->_outputFormat = "{file}:{line}: {severity}: {message}"; else if (_settings->_outputFormat == "vs") _settings->_outputFormat = "{file}({line}): {severity}: {message}"; else if (_settings->_outputFormat == "edit") _settings->_outputFormat = "{file} +{line}: {severity}: {message}"; } // Checking threads else if (std::strncmp(argv[i], "-j", 2) == 0) { std::string numberString; // "-j 3" if (std::strcmp(argv[i], "-j") == 0) { ++i; if (i >= argc || argv[i][0] == '-') { PrintMessage("cppcheck: argument to '-j' is missing."); return false; } numberString = argv[i]; } // "-j3" else numberString = argv[i]+2; std::istringstream iss(numberString); if (!(iss >> _settings->_jobs)) { PrintMessage("cppcheck: argument to '-j' is not a number."); return false; } if (_settings->_jobs > 10000) { // This limit is here just to catch typos. If someone has // need for more jobs, this value should be increased. PrintMessage("cppcheck: argument for '-j' is allowed to be 10000 at max."); return false; } } // print all possible error messages.. else if (std::strcmp(argv[i], "--errorlist") == 0) { _showErrorMessages = true; _settings->_xml = true; _exitAfterPrint = true; } // documentation.. else if (std::strcmp(argv[i], "--doc") == 0) { std::ostringstream doc; // Get documentation.. for (std::list::iterator it = Check::instances().begin(); it != Check::instances().end(); ++it) { const std::string& name((*it)->name()); const std::string info((*it)->classInfo()); if (!name.empty() && !info.empty()) doc << "===" << name << "===\n" << info << "\n"; } std::cout << doc.str(); _exitAfterPrint = true; return true; } // show timing information.. else if (std::strncmp(argv[i], "--showtime=", 11) == 0) { const std::string showtimeMode = argv[i] + 11; if (showtimeMode == "file") _settings->_showtime = SHOWTIME_FILE; else if (showtimeMode == "summary") _settings->_showtime = SHOWTIME_SUMMARY; else if (showtimeMode == "top5") _settings->_showtime = SHOWTIME_TOP5; else _settings->_showtime = SHOWTIME_NONE; } #ifdef HAVE_RULES // Rule given at command line else if (std::strncmp(argv[i], "--rule=", 7) == 0) { Settings::Rule rule; rule.pattern = 7 + argv[i]; _settings->rules.push_back(rule); } // Rule file else if (std::strncmp(argv[i], "--rule-file=", 12) == 0) { tinyxml2::XMLDocument doc; if (doc.LoadFile(12+argv[i]) == tinyxml2::XML_NO_ERROR) { tinyxml2::XMLElement *node = doc.FirstChildElement(); for (; node && strcmp(node->Value(), "rule") == 0; node = node->NextSiblingElement()) { Settings::Rule rule; tinyxml2::XMLElement *tokenlist = node->FirstChildElement("tokenlist"); if (tokenlist) rule.tokenlist = tokenlist->GetText(); tinyxml2::XMLElement *pattern = node->FirstChildElement("pattern"); if (pattern) { rule.pattern = pattern->GetText(); } tinyxml2::XMLElement *message = node->FirstChildElement("message"); if (message) { tinyxml2::XMLElement *severity = message->FirstChildElement("severity"); if (severity) rule.severity = severity->GetText(); tinyxml2::XMLElement *id = message->FirstChildElement("id"); if (id) rule.id = id->GetText(); tinyxml2::XMLElement *summary = message->FirstChildElement("summary"); if (summary) rule.summary = summary->GetText() ? summary->GetText() : ""; } if (!rule.pattern.empty()) _settings->rules.push_back(rule); } } } #endif // Specify platform else if (std::strncmp(argv[i], "--platform=", 11) == 0) { std::string platform(11+argv[i]); if (platform == "win32A") _settings->platform(Settings::Win32A); else if (platform == "win32W") _settings->platform(Settings::Win32W); else if (platform == "win64") _settings->platform(Settings::Win64); else if (platform == "unix32") _settings->platform(Settings::Unix32); else if (platform == "unix64") _settings->platform(Settings::Unix64); else { std::string message("cppcheck: error: unrecognized platform: \""); message += platform; message += "\"."; PrintMessage(message); return false; } } // Set maximum number of #ifdef configurations to check else if (std::strncmp(argv[i], "--max-configs=", 14) == 0) { _settings->_force = false; std::istringstream iss(14+argv[i]); if (!(iss >> _settings->_maxConfigs)) { PrintMessage("cppcheck: argument to '--max-configs=' is not a number."); return false; } if (_settings->_maxConfigs < 1) { PrintMessage("cppcheck: argument to '--max-configs=' must be greater than 0."); return false; } maxconfigs = true; } // Print help else if (std::strcmp(argv[i], "-h") == 0 || std::strcmp(argv[i], "--help") == 0) { _pathnames.clear(); _showHelp = true; _exitAfterPrint = true; break; } else if (std::strncmp(argv[i], "-", 1) == 0 || std::strncmp(argv[i], "--", 2) == 0) { std::string message("cppcheck: error: unrecognized command line option: \""); message += argv[i]; message += "\"."; PrintMessage(message); return false; } else { std::string path = Path::fromNativeSeparators(argv[i]); path = Path::removeQuotationMarks(path); _pathnames.push_back(path); } } if (def && !_settings->_force && !maxconfigs) _settings->_maxConfigs = 1U; if (_settings->_force) _settings->_maxConfigs = ~0U; if (_settings->isEnabled("unusedFunction") && _settings->_jobs > 1) { PrintMessage("cppcheck: unusedFunction check can't be used with '-j' option, so it's disabled."); } if (_settings->inconclusive && _settings->_xml && _settings->_xml_version == 1U) { PrintMessage("cppcheck: inconclusive messages will not be shown, because the old xml format is not compatible. It's recommended to use the new xml format (use --xml-version=2)."); } if (argc <= 1) _showHelp = true; if (_showHelp) { PrintHelp(); return true; } // Print error only if we have "real" command and expect files if (!_exitAfterPrint && _pathnames.empty()) { PrintMessage("cppcheck: No C or C++ source files found."); return false; } // Use paths _pathnames if no base paths for relative path output are given if (_settings->_basePaths.empty() && _settings->_relativePaths) _settings->_basePaths = _pathnames; return true; } void CmdLineParser::PrintHelp() { std::cout << "Cppcheck - A tool for static C/C++ code analysis\n" "\n" "Syntax:\n" " cppcheck [OPTIONS] [files or paths]\n" "\n" "If a directory is given instead of a filename, *.cpp, *.cxx, *.cc, *.c++, *.c,\n" "*.tpp, and *.txx files are checked recursively from the given directory.\n\n" "Options:\n" " --append= This allows you to provide information about functions\n" " by providing an implementation for them.\n" " --check-config Check cppcheck configuration. The normal code\n" " analysis is disabled by this flag.\n" " --check-library Show information messages when library files have\n" " incomplete info.\n" " -D Define preprocessor symbol. Unless --max-configs or\n" " --force is used, Cppcheck will only check the given\n" " configuration when -D is used.\n" " Example: '-DDEBUG=1 -D__cplusplus'.\n" " -U Undefine preprocessor symbol. Use -U to explicitly\n" " hide certain #ifdef code paths from checking.\n" " Example: '-UDEBUG'\n" " --enable= Enable additional checks. The available ids are:\n" " * all\n" " Enable all checks. It is recommended to only\n" " use --enable=all when the whole program is\n" " scanned, because this enables unusedFunction.\n" " * warning\n" " Enable warning messages\n" " * style\n" " Enable all coding style checks. All messages\n" " with the severities 'style', 'performance' and\n" " 'portability' are enabled.\n" " * performance\n" " Enable performance messages\n" " * portability\n" " Enable portability messages\n" " * information\n" " Enable information messages\n" " * unusedFunction\n" " Check for unused functions. It is recommend\n" " to only enable this when the whole program is\n" " scanned.\n" " * missingInclude\n" " Warn if there are missing includes. For\n" " detailed information, use '--check-config'.\n" " Several ids can be given if you separate them with\n" " commas. See also --std\n" " --error-exitcode= If errors are found, integer [n] is returned instead of\n" " the default '0'. '" << EXIT_FAILURE << "' is returned\n" " if arguments are not valid or if no input files are\n" " provided. Note that your operating system can modify\n" " this value, e.g. '256' can become '0'.\n" " --errorlist Print a list of all the error messages in XML format.\n" " --exitcode-suppressions=\n" " Used when certain messages should be displayed but\n" " should not cause a non-zero exitcode.\n" " --file-list= Specify the files to check in a text file. Add one\n" " filename per line. When file is '-,' the file list will\n" " be read from standard input.\n" " -f, --force Force checking of all configurations in files. If used\n" " together with '--max-configs=', the last option is the\n" " one that is effective.\n" " -h, --help Print this help.\n" " -I Give path to search for include files. Give several -I\n" " parameters to give several paths. First given path is\n" " searched for contained header files first. If paths are\n" " relative to source files, this is not needed.\n" " --includes-file=\n" " Specify directory paths to search for included header\n" " files in a text file. Add one include path per line.\n" " First given path is searched for contained header\n" " files first. If paths are relative to source files,\n" " this is not needed.\n" " --include=\n" " Force inclusion of a file before the checked file. Can\n" " be used for example when checking the Linux kernel,\n" " where autoconf.h needs to be included for every file\n" " compiled. Works the same way as the GCC -include\n" " option.\n" " -i Give a source file or source file directory to exclude\n" " from the check. This applies only to source files so\n" " header files included by source files are not matched.\n" " Directory name is matched to all parts of the path.\n" " --inconclusive Allow that Cppcheck reports even though the analysis is\n" " inconclusive.\n" " There are false positives with this option. Each result\n" " must be carefully investigated before you know if it is\n" " good or bad.\n" " --inline-suppr Enable inline suppressions. Use them by placing one or\n" " more comments, like: '// cppcheck-suppress warningId'\n" " on the lines before the warning to suppress.\n" " -j Start [jobs] threads to do the checking simultaneously.\n" " --language=, -x \n" " Forces cppcheck to check all files as the given\n" " language. Valid values are: c, c++\n" " --library=\n" " Use library configuration.\n" " --max-configs=\n" " Maximum number of configurations to check in a file\n" " before skipping it. Default is '12'. If used together\n" " with '--force', the last option is the one that is\n" " effective.\n" " --platform= Specifies platform specific types and sizes. The\n" " available platforms are:\n" " * unix32\n" " 32 bit unix variant\n" " * unix64\n" " 64 bit unix variant\n" " * win32A\n" " 32 bit Windows ASCII character encoding\n" " * win32W\n" " 32 bit Windows UNICODE character encoding\n" " * win64\n" " 64 bit Windows\n" " -q, --quiet Only print error messages.\n" " -rp, --relative-paths\n" " -rp=, --relative-paths=\n" " Use relative paths in output. When given, are\n" " used as base. You can separate multiple paths by ';'.\n" " Otherwise path where source files are searched is used.\n" " We use string comparison to create relative paths, so\n" " using e.g. ~ for home folder does not work. It is\n" " currently only possible to apply the base paths to\n" " files that are on a lower level in the directory tree.\n" " --report-progress Report progress messages while checking a file.\n" #ifdef HAVE_RULES " --rule= Match regular expression.\n" " --rule-file= Use given rule file. For more information, see: \n" " https://sourceforge.net/projects/cppcheck/files/Articles/\n" #endif " --std= Set standard.\n" " The available options are:\n" " * posix\n" " POSIX compatible code\n" " * c89\n" " C code is C89 compatible\n" " * c99\n" " C code is C99 compatible\n" " * c11\n" " C code is C11 compatible (default)\n" " * c++03\n" " C++ code is C++03 compatible\n" " * c++11\n" " C++ code is C++11 compatible (default)\n" " More than one --std can be used:\n" " 'cppcheck --std=c99 --std=posix file.c'\n" " --suppress= Suppress warnings that match . The format of\n" " is:\n" " [error id]:[filename]:[line]\n" " The [filename] and [line] are optional. If [error id]\n" " is a wildcard '*', all error ids match.\n" " --suppressions-list=\n" " Suppress warnings listed in the file. Each suppression\n" " is in the same format as above.\n" " --template='' Format the error messages. E.g.\n" " '{file}:{line},{severity},{id},{message}' or\n" " '{file}({line}):({severity}) {message}' or\n" " '{callstack} {message}'\n" " Pre-defined templates: gcc, vs, edit.\n" " -v, --verbose Output more detailed error information.\n" " --version Print out version number.\n" " --xml Write results in xml format to error stream (stderr).\n" " --xml-version=\n" " Select the XML file version. Currently versions 1 and\n" " 2 are available. The default version is 1." "\n" "Example usage:\n" " # Recursively check the current folder. Print the progress on the screen and\n" " # write errors to a file:\n" " cppcheck . 2> err.txt\n" "\n" " # Recursively check ../myproject/ and don't print progress:\n" " cppcheck --quiet ../myproject/\n" "\n" " # Check test.cpp, enable all checks:\n" " cppcheck --enable=all --inconclusive --std=posix test.cpp\n" "\n" " # Check f.cpp and search include files from inc1/ and inc2/:\n" " cppcheck -I inc1/ -I inc2/ f.cpp\n" "\n" "For more information:\n" " http://cppcheck.sourceforge.net/manual.pdf\n"; } cppcheck-1.61/cli/cmdlineparser.h000066400000000000000000000056651217722632100170100ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #ifndef CMDLINE_PARSER_H #define CMDLINE_PARSER_H #include #include class Settings; /// @addtogroup CLI /// @{ /** * @brief The command line parser. * The command line parser parses options and parameters user gives to * cppcheck command line. * * The parser takes a pointer to Settings instance which it will update * based on options user has given. Couple of options are handled as * class internal options. */ class CmdLineParser { public: /** * The constructor. * @param settings Settings instance that will be modified according to * options user has given. */ explicit CmdLineParser(Settings *settings); /** * Parse given command line. * @return true if command line was ok, false if there was an error. */ bool ParseFromArgs(int argc, const char* const argv[]); /** * Return if user wanted to see program version. */ bool GetShowVersion() const { return _showVersion; } /** * Return if user wanted to see list of error messages. */ bool GetShowErrorMessages() const { return _showErrorMessages; } /** * Return the path names user gave to command line. */ const std::vector& GetPathNames() const { return _pathnames; } /** * Return if help is shown to user. */ bool GetShowHelp() const { return _showHelp; } /** * Return if we should exit after printing version, help etc. */ bool ExitAfterPrinting() const { return _exitAfterPrint; } /** * Return a list of paths user wants to ignore. */ const std::vector& GetIgnoredPaths() const { return _ignoredPaths; } protected: /** * Print help text to the console. */ static void PrintHelp(); /** * Print message (to console?). */ static void PrintMessage(const std::string &message); private: std::vector _pathnames; std::vector _ignoredPaths; Settings *_settings; bool _showHelp; bool _showVersion; bool _showErrorMessages; bool _exitAfterPrint; }; /// @} #endif // CMDLINE_PARSER_H cppcheck-1.61/cli/cppcheck.vcproj000077500000000000000000000230611217722632100170050ustar00rootroot00000000000000 cppcheck-1.61/cli/cppcheckexecutor.cpp000066400000000000000000000237201217722632100200420ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include "cppcheckexecutor.h" #include "cppcheck.h" #include "threadexecutor.h" #include "preprocessor.h" #include "errorlogger.h" #include #include #include // EXIT_SUCCESS and EXIT_FAILURE #include #include #include #include "cmdlineparser.h" #include "filelister.h" #include "path.h" #include "pathmatch.h" CppCheckExecutor::CppCheckExecutor() : _settings(0), time1(0), errorlist(false) { } CppCheckExecutor::~CppCheckExecutor() { } bool CppCheckExecutor::parseFromArgs(CppCheck *cppcheck, int argc, const char* const argv[]) { Settings& settings = cppcheck->settings(); CmdLineParser parser(&settings); bool success = parser.ParseFromArgs(argc, argv); if (success) { if (parser.GetShowVersion() && !parser.GetShowErrorMessages()) { const char * extraVersion = cppcheck->extraVersion(); if (*extraVersion != 0) std::cout << "Cppcheck " << cppcheck->version() << " (" << extraVersion << ')' << std::endl; else std::cout << "Cppcheck " << cppcheck->version() << std::endl; } if (parser.GetShowErrorMessages()) { errorlist = true; std::cout << ErrorLogger::ErrorMessage::getXMLHeader(settings._xml_version); cppcheck->getErrorMessages(); std::cout << ErrorLogger::ErrorMessage::getXMLFooter(settings._xml_version) << std::endl; } if (parser.ExitAfterPrinting()) std::exit(EXIT_SUCCESS); } else { std::exit(EXIT_FAILURE); } // Check that all include paths exist { std::list::iterator iter; for (iter = settings._includePaths.begin(); iter != settings._includePaths.end(); ) { const std::string path(Path::toNativeSeparators(*iter)); if (FileLister::isDirectory(path)) ++iter; else { // If the include path is not found, warn user and remove the // non-existing path from the list. std::cout << "cppcheck: warning: Couldn't find path given by -I '" << path << '\'' << std::endl; iter = settings._includePaths.erase(iter); } } } const std::vector& pathnames = parser.GetPathNames(); if (!pathnames.empty()) { // Execute recursiveAddFiles() to each given file parameter std::vector::const_iterator iter; for (iter = pathnames.begin(); iter != pathnames.end(); ++iter) FileLister::recursiveAddFiles(_files, Path::toNativeSeparators(*iter)); } if (!_files.empty()) { // Remove header files from the list of ignored files. // Also output a warning for the user. // TODO: Remove all unknown files? (use FileLister::acceptFile()) bool warn = false; std::vector ignored = parser.GetIgnoredPaths(); for (std::vector::iterator i = ignored.begin(); i != ignored.end();) { const std::string extension = Path::getFilenameExtension(*i); if (extension == ".h" || extension == ".hpp") { i = ignored.erase(i); warn = true; } else ++i; } if (warn) { std::cout << "cppcheck: filename exclusion does not apply to header (.h and .hpp) files." << std::endl; std::cout << "cppcheck: Please use --suppress for ignoring results from the header files." << std::endl; } #if defined(_WIN32) // For Windows we want case-insensitive path matching const bool caseSensitive = false; #else const bool caseSensitive = true; #endif PathMatch matcher(parser.GetIgnoredPaths(), caseSensitive); for (std::map::iterator i = _files.begin(); i != _files.end();) { if (matcher.Match(i->first)) _files.erase(i++); else ++i; } } else { std::cout << "cppcheck: error: could not find or open any of the paths given." << std::endl; return false; } if (!_files.empty()) { return true; } else { std::cout << "cppcheck: error: no files to check - all paths ignored." << std::endl; return false; } } int CppCheckExecutor::check(int argc, const char* const argv[]) { Preprocessor::missingIncludeFlag = false; CppCheck cppCheck(*this, true); Settings& settings = cppCheck.settings(); _settings = &settings; settings.library.load(argv[0], "std"); if (!parseFromArgs(&cppCheck, argc, argv)) { return EXIT_FAILURE; } if (settings.reportProgress) time1 = std::time(0); if (settings._xml) { reportErr(ErrorLogger::ErrorMessage::getXMLHeader(settings._xml_version)); } unsigned int returnValue = 0; if (settings._jobs == 1) { // Single process std::size_t totalfilesize = 0; for (std::map::const_iterator i = _files.begin(); i != _files.end(); ++i) { totalfilesize += i->second; } std::size_t processedsize = 0; unsigned int c = 0; for (std::map::const_iterator i = _files.begin(); i != _files.end(); ++i) { returnValue += cppCheck.check(i->first); processedsize += i->second; if (!settings._errorsOnly) reportStatus(c + 1, _files.size(), processedsize, totalfilesize); c++; } cppCheck.checkFunctionUsage(); } else if (!ThreadExecutor::isEnabled()) { std::cout << "No thread support yet implemented for this platform." << std::endl; } else { // Multiple processes ThreadExecutor executor(_files, settings, *this); returnValue = executor.check(); } if (settings.isEnabled("information") || settings.checkConfiguration) reportUnmatchedSuppressions(settings.nomsg.getUnmatchedGlobalSuppressions()); if (!settings.checkConfiguration) { cppCheck.tooManyConfigsError("",0U); if (settings.isEnabled("missingInclude") && Preprocessor::missingIncludeFlag) { const std::list callStack; ErrorLogger::ErrorMessage msg(callStack, Severity::information, "Cppcheck cannot find all the include files (use --check-config for details)\n" "Cppcheck cannot find all the include files. Cppcheck can check the code without the " "include files found. But the results will probably be more accurate if all the include " "files are found. Please check your project's include directories and add all of them " "as include directories for Cppcheck. To see what files Cppcheck cannot find use " "--check-config.", "missingInclude", false); reportInfo(msg); } } if (settings._xml) { reportErr(ErrorLogger::ErrorMessage::getXMLFooter(settings._xml_version)); } _settings = 0; if (returnValue) return settings._exitCode; else return 0; } void CppCheckExecutor::reportErr(const std::string &errmsg) { // Alert only about unique errors if (_errorList.find(errmsg) != _errorList.end()) return; _errorList.insert(errmsg); std::cerr << errmsg << std::endl; } void CppCheckExecutor::reportOut(const std::string &outmsg) { std::cout << outmsg << std::endl; } void CppCheckExecutor::reportProgress(const std::string &filename, const char stage[], const std::size_t value) { (void)filename; if (!time1) return; // Report progress messages every 10 seconds const std::time_t time2 = std::time(NULL); if (time2 >= (time1 + 10)) { time1 = time2; // format a progress message std::ostringstream ostr; ostr << "progress: " << stage << ' ' << value << '%'; // Report progress message reportOut(ostr.str()); } } void CppCheckExecutor::reportInfo(const ErrorLogger::ErrorMessage &msg) { reportErr(msg); } void CppCheckExecutor::reportStatus(std::size_t fileindex, std::size_t filecount, std::size_t sizedone, std::size_t sizetotal) { if (filecount > 1) { std::ostringstream oss; oss << fileindex << '/' << filecount << " files checked " << (sizetotal > 0 ? static_cast(static_cast(sizedone) / sizetotal*100) : 0) << "% done"; std::cout << oss.str() << std::endl; } } void CppCheckExecutor::reportErr(const ErrorLogger::ErrorMessage &msg) { if (errorlist) { reportOut(msg.toXML(false, _settings->_xml_version)); } else if (_settings->_xml) { reportErr(msg.toXML(_settings->_verbose, _settings->_xml_version)); } else { reportErr(msg.toString(_settings->_verbose, _settings->_outputFormat)); } } cppcheck-1.61/cli/cppcheckexecutor.h000066400000000000000000000076251217722632100175150ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #ifndef CPPCHECKEXECUTOR_H #define CPPCHECKEXECUTOR_H #include "errorlogger.h" #include #include #include class CppCheck; class Settings; /** * This class works as an example of how CppCheck can be used in external * programs without very little knowledge of the internal parts of the * program itself. If you wish to use cppcheck e.g. as a part of IDE, * just rewrite this class for your needs and possibly use other methods * from CppCheck class instead the ones used here. */ class CppCheckExecutor : public ErrorLogger { public: /** * Constructor */ CppCheckExecutor(); /** * Destructor */ virtual ~CppCheckExecutor(); /** * Starts the checking. * * @param argc from main() * @param argv from main() * @return EXIT_FAILURE if arguments are invalid or no input files * were found. * If errors are found and --error-exitcode is used, * given value is returned instead of default 0. * If no errors are found, 0 is returned. */ int check(int argc, const char* const argv[]); /** * Information about progress is directed here. This should be * called by the CppCheck class only. * * @param outmsg Progress message e.g. "Checking main.cpp..." */ virtual void reportOut(const std::string &outmsg); /** xml output of errors */ virtual void reportErr(const ErrorLogger::ErrorMessage &msg); void reportProgress(const std::string &filename, const char stage[], const std::size_t value); /** * Output information messages. */ virtual void reportInfo(const ErrorLogger::ErrorMessage &msg); /** * Information about how many files have been checked * * @param fileindex This many files have been checked. * @param filecount This many files there are in total. * @param sizedone The sum of sizes of the files checked. * @param sizetotal The total sizes of the files. */ static void reportStatus(std::size_t fileindex, std::size_t filecount, std::size_t sizedone, std::size_t sizetotal); protected: /** * Helper function to print out errors. Appends a line change. * @param errmsg String printed to error stream */ void reportErr(const std::string &errmsg); /** * @brief Parse command line args and get settings and file lists * from there. * * @param cppcheck cppcheck instance * @param argc argc from main() * @param argv argv from main() * @return false when errors are found in the input */ bool parseFromArgs(CppCheck *cppcheck, int argc, const char* const argv[]); private: /** * Pointer to current settings; set while check() is running. */ const Settings* _settings; /** * Used to filter out duplicate error messages. */ std::set _errorList; /** * Filename associated with size of file */ std::map _files; /** * Report progress time */ std::time_t time1; /** * Has --errorlist been given? */ bool errorlist; }; #endif // CPPCHECKEXECUTOR_H cppcheck-1.61/cli/filelister.cpp000066400000000000000000000202701217722632100166420ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include #include #include "filelister.h" #include "path.h" #ifdef _WIN32 /////////////////////////////////////////////////////////////////////////////// ////// This code is WIN32 systems ///////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// #include #ifndef __BORLANDC__ #include #endif // Here is the catch: cppcheck core is Ansi code (using char type). // When compiling Unicode targets WinAPI automatically uses *W Unicode versions // of called functions. Thus, we explicitly call *A versions of the functions. static BOOL MyIsDirectory(const std::string& path) { #ifdef __BORLANDC__ return (GetFileAttributes(path.c_str()) & FILE_ATTRIBUTE_DIRECTORY); #else // See http://msdn.microsoft.com/en-us/library/bb773621(VS.85).aspx return PathIsDirectoryA(path.c_str()); #endif } static HANDLE MyFindFirstFile(const std::string& path, LPWIN32_FIND_DATAA findData) { HANDLE hFind = FindFirstFileA(path.c_str(), findData); return hFind; } static BOOL MyFileExists(const std::string& path) { #ifdef __BORLANDC__ DWORD fa = GetFileAttributes(path.c_str()); BOOL result = FALSE; if (fa != INVALID_FILE_ATTRIBUTES && !(fa & FILE_ATTRIBUTE_DIRECTORY)) result = TRUE; #else BOOL result = PathFileExistsA(path.c_str()); #endif return result; } void FileLister::recursiveAddFiles(std::map &files, const std::string &path) { const std::string cleanedPath = Path::toNativeSeparators(path); // basedir is the base directory which is used to form pathnames. // It always has a trailing backslash available for concatenation. std::string basedir; // searchPattern is the search string passed into FindFirst and FindNext. std::string searchPattern = cleanedPath; // The user wants to check all files in a dir const bool checkAllFilesInDir = (MyIsDirectory(cleanedPath) != FALSE); if (checkAllFilesInDir) { char c = cleanedPath[ cleanedPath.size()-1 ]; switch (c) { case '\\': searchPattern += '*'; basedir = cleanedPath; break; case '*': basedir = cleanedPath.substr(0, cleanedPath.length() - 1); break; default: searchPattern += "\\*"; if (cleanedPath != ".") basedir = cleanedPath + '\\'; } } else { std::string::size_type pos = cleanedPath.find_last_of('\\'); if (std::string::npos != pos) { basedir = cleanedPath.substr(0, pos + 1); } } WIN32_FIND_DATAA ffd; HANDLE hFind = MyFindFirstFile(searchPattern, &ffd); if (INVALID_HANDLE_VALUE == hFind) return; do { if (ffd.cFileName[0] == '.' || ffd.cFileName[0] == '\0') continue; const char* ansiFfd = ffd.cFileName; if (strchr(ansiFfd,'?')) { ansiFfd = ffd.cAlternateFileName; } const std::string fname(basedir + ansiFfd); if ((ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { // File const std::string nativename = Path::fromNativeSeparators(fname); if (!checkAllFilesInDir || Path::acceptFile(fname)) { // Limitation: file sizes are assumed to fit in a 'size_t' #ifdef _WIN64 files[nativename] = (static_cast(ffd.nFileSizeHigh) << 32) | ffd.nFileSizeLow; #else files[nativename] = ffd.nFileSizeLow; #endif } } else { // Directory FileLister::recursiveAddFiles(files, fname); } } while (FindNextFileA(hFind, &ffd) != FALSE); if (INVALID_HANDLE_VALUE != hFind) { FindClose(hFind); } } bool FileLister::isDirectory(const std::string &path) { return (MyIsDirectory(path) != FALSE); } bool FileLister::fileExists(const std::string &path) { return (MyFileExists(path) == TRUE); } #else /////////////////////////////////////////////////////////////////////////////// ////// This code is POSIX-style systems /////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// #include #include #include #include #include // Get absolute path. Returns empty string if path does not exist or other error. std::string FileLister::getAbsolutePath(const std::string& path) { std::string absolute_path; #ifdef PATH_MAX char buf[PATH_MAX]; if (realpath(path.c_str(), buf) != NULL) absolute_path = buf; #else char *dynamic_buf; if ((dynamic_buf = realpath(path.c_str(), NULL)) != NULL) { absolute_path = dynamic_buf; free(dynamic_buf); } #endif return absolute_path; } void FileLister::recursiveAddFiles2(std::set &seen_paths, std::map &files, const std::string &path) { std::ostringstream oss; oss << path; if (path.length() > 0 && path[path.length()-1] == '/') oss << "*"; glob_t glob_results; glob(oss.str().c_str(), GLOB_MARK, 0, &glob_results); for (unsigned int i = 0; i < glob_results.gl_pathc; i++) { const std::string filename = glob_results.gl_pathv[i]; if (filename == "." || filename == ".." || filename.length() == 0) continue; // Determine absolute path. Empty filename if path does not exist const std::string absolute_path = getAbsolutePath(filename); if (absolute_path.empty()) continue; // Did we already process this entry? if (seen_paths.find(absolute_path) != seen_paths.end()) continue; if (filename[filename.length()-1] != '/') { // File if (Path::sameFileName(path,filename) || Path::acceptFile(filename)) { seen_paths.insert(absolute_path); struct stat sb; if (stat(absolute_path.c_str(), &sb) == 0) { // Limitation: file sizes are assumed to fit in a 'size_t' files[filename] = static_cast(sb.st_size); } else files[filename] = 0; } } else { // Directory seen_paths.insert(absolute_path); recursiveAddFiles2(seen_paths, files, filename); } } globfree(&glob_results); } void FileLister::recursiveAddFiles(std::map &files, const std::string &path) { std::set seen_paths; recursiveAddFiles2(seen_paths, files, path); } bool FileLister::isDirectory(const std::string &path) { bool ret = false; glob_t glob_results; glob(path.c_str(), GLOB_MARK, 0, &glob_results); if (glob_results.gl_pathc == 1) { const std::string glob_path = glob_results.gl_pathv[0]; if (!glob_path.empty() && glob_path[glob_path.size() - 1] == '/') { ret = true; } } globfree(&glob_results); return ret; } bool FileLister::fileExists(const std::string &path) { struct stat statinfo; int result = stat(path.c_str(), &statinfo); if (result < 0) { // Todo: should check errno == ENOENT? // File not found return false; } // Check if file is regular file if ((statinfo.st_mode & S_IFMT) == S_IFREG) return true; return false; } #endif cppcheck-1.61/cli/filelister.h000066400000000000000000000041251217722632100163100ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #ifndef filelisterH #define filelisterH #include #include #include /// @addtogroup CLI /// @{ /** @brief Cross-platform FileLister */ class FileLister { public: /** * @brief Recursively add source files to a map. * Add source files from given directory and all subdirectries to the * given map. Only files with accepted extensions * (*.c;*.cpp;*.cxx;*.c++;*.cc;*.txx) are added. * @param files output map that associates the size of each file with its name * @param path root path */ static void recursiveAddFiles(std::map &files, const std::string &path); /** * @brief Is given path a directory? * @return returns true if the path is a directory */ static bool isDirectory(const std::string &path); /** * @brief Check if the given path is a file and if it exists? * @return true if path points to file and the file exists. */ static bool fileExists(const std::string &path); #ifndef _WIN32 static std::string getAbsolutePath(const std::string& path); static void recursiveAddFiles2(std::set &seen_paths, std::map &files, const std::string &path); #endif }; /// @} #endif // #ifndef filelisterH cppcheck-1.61/cli/main.cpp000066400000000000000000000071151217722632100154270ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ /** * * @mainpage Cppcheck * @version 1.61 * * @section overview_sec Overview * Cppcheck is a simple tool for static analysis of C/C++ code. * * The method used is to first tokenize the source code and then analyse the token list. * In the token list, the tokens are stored in plain text. * * The checks are written in C++. The checks are addons that can be easily added/removed. * * @section writing_checks_sec Writing a check * Below is a simple example of a check that detect division with zero: * @code void CheckOther::checkZeroDivision() { // Iterate through all tokens in the token list for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { if (Token::Match(tok, "/ 0")) reportError(tok, Severity::error, "zerodiv", "Division by zero"); } } @endcode * * The function Token::Match is often used in the checks. Through it * you can match tokens against patterns. * * * @section checkclass_sec Creating a new check class from scratch * %Check classes inherit from the Check class. The Check class specifies the interface that you must use. * To integrate a check class into cppcheck all you need to do is: * - Add your source file(s) so they are compiled into the executable. * - Create an instance of the class (the Check::Check() constructor registers the class as an addon that Cppcheck then can use). * * * @section embedding_sec Embedding Cppcheck * Cppcheck is designed to be easily embeddable into other programs. * * The "cli/main.cpp" and "cli/cppcheckexecutor.*" files illustrate how cppcheck * can be embedded into an application. * * * @section detailed_overview_sec Detailed overview * This happens when you execute cppcheck from the command line: * -# CppCheckExecutor::check this function executes the Cppcheck * -# CppCheck::parseFromArgs parse command line arguments * - The Settings class is used to maintain settings * - Use FileLister and command line arguments to get files to check * -# ThreadExecutor create more instances of CppCheck if needed * -# CppCheck::check is called for each file. It checks a single file * -# Preprocess the file (through Preprocessor) * - Comments are removed * - Macros are expanded * -# Tokenize the file (see Tokenizer) * -# Run the runChecks of all check classes. * -# Simplify the tokenlist (Tokenizer::simplifyTokenList) * -# Run the runSimplifiedChecks of all check classes * * When errors are found, they are reported back to the CppCheckExecutor through the ErrorLogger interface */ #include "cppcheckexecutor.h" /** * Main function of cppcheck * * @param argc Passed to CppCheck::parseFromArgs() * @param argv Passed to CppCheck::parseFromArgs() * @return What CppCheckExecutor::check() returns. */ int main(int argc, char* argv[]) { CppCheckExecutor exec; return exec.check(argc, argv); } cppcheck-1.61/cli/pathmatch.cpp000066400000000000000000000056531217722632100164610ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include "pathmatch.h" #include #include // Borland: tolower PathMatch::PathMatch(const std::vector &masks, bool caseSensitive) : _masks(masks), _caseSensitive(caseSensitive) { if (!_caseSensitive) for (std::vector::iterator i = _masks.begin(); i != _masks.end(); ++i) std::transform(i->begin(), i->end(), i->begin(), ::tolower); } bool PathMatch::Match(const std::string &path) const { if (path.empty()) return false; for (std::vector::const_iterator iterMask = _masks.begin(); iterMask != _masks.end(); ++iterMask) { const std::string& mask(*iterMask); std::string findpath(path); if (!_caseSensitive) std::transform(findpath.begin(), findpath.end(), findpath.begin(), ::tolower); // Filtering directory name if (mask[mask.length() - 1] == '/') { if (findpath[findpath.length() - 1] != '/') findpath = RemoveFilename(findpath); if (mask.length() > findpath.length()) continue; // Match relative paths starting with mask // -isrc matches src/foo.cpp if (findpath.compare(0, mask.size(), mask) == 0) return true; // Match only full directory name in middle or end of the path // -isrc matches myproject/src/ but does not match // myproject/srcfiles/ or myproject/mysrc/ if (findpath.find("/" + mask) != std::string::npos) return true; } // Filtering filename else { if (mask.length() > findpath.length()) continue; // Check if path ends with mask // -ifoo.cpp matches (./)foo.c, src/foo.cpp and proj/src/foo.cpp // -isrc/file.cpp matches src/foo.cpp and proj/src/foo.cpp if (findpath.compare(findpath.size() - mask.size(), findpath.size(), mask) == 0) return true; } } return false; } std::string PathMatch::RemoveFilename(const std::string &path) { const std::size_t ind = path.find_last_of('/'); return path.substr(0, ind + 1); } cppcheck-1.61/cli/pathmatch.h000066400000000000000000000033431217722632100161200ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #ifndef PATHMATCH_H #define PATHMATCH_H #include #include /// @addtogroup CLI /// @{ /** * @brief Simple path matching for ignoring paths in CLI. */ class PathMatch { public: /** * The constructor. * @param masks List of masks. * @param caseSensitive Match the case of the characters when * matching paths? */ PathMatch(const std::vector &masks, bool caseSensitive = true); /** * @brief Match path against list of masks. * @param path Path to match. * @return true if any of the masks match the path, false otherwise. */ bool Match(const std::string &path) const; protected: /** * @brief Remove filename part from the path. * @param path Path to edit. * @return path without filename part. */ static std::string RemoveFilename(const std::string &path); private: std::vector _masks; bool _caseSensitive; }; /// @} #endif // PATHMATCH_H cppcheck-1.61/cli/threadexecutor.cpp000066400000000000000000000406601217722632100175330ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include "cppcheckexecutor.h" #include "threadexecutor.h" #include "cppcheck.h" #ifdef THREADING_MODEL_FORK #include #include #include #include #include #include #include #include #include #include #include #include #endif #ifdef THREADING_MODEL_WIN #include #include #include #include #include #endif // required for FD_ZERO using std::memset; ThreadExecutor::ThreadExecutor(const std::map &files, Settings &settings, ErrorLogger &errorLogger) : _files(files), _settings(settings), _errorLogger(errorLogger), _fileCount(0) { #if defined(THREADING_MODEL_FORK) _wpipe = 0; #elif defined(THREADING_MODEL_WIN) _processedFiles = 0; _totalFiles = 0; _processedSize = 0; _totalFileSize = 0; #endif } ThreadExecutor::~ThreadExecutor() { //dtor } /////////////////////////////////////////////////////////////////////////////// ////// This code is for platforms that support fork() only //////////////////// /////////////////////////////////////////////////////////////////////////////// #if defined(THREADING_MODEL_FORK) void ThreadExecutor::addFileContent(const std::string &path, const std::string &content) { _fileContents[ path ] = content; } int ThreadExecutor::handleRead(int rpipe, unsigned int &result) { char type = 0; if (read(rpipe, &type, 1) <= 0) { if (errno == EAGAIN) return 0; return -1; } if (type != REPORT_OUT && type != REPORT_ERROR && type != REPORT_INFO && type != CHILD_END) { std::cerr << "#### You found a bug from cppcheck.\nThreadExecutor::handleRead error, type was:" << type << std::endl; std::exit(0); } unsigned int len = 0; if (read(rpipe, &len, sizeof(len)) <= 0) { std::cerr << "#### You found a bug from cppcheck.\nThreadExecutor::handleRead error, type was:" << type << std::endl; std::exit(0); } char *buf = new char[len]; if (read(rpipe, buf, len) <= 0) { std::cerr << "#### You found a bug from cppcheck.\nThreadExecutor::handleRead error, type was:" << type << std::endl; std::exit(0); } if (type == REPORT_OUT) { _errorLogger.reportOut(buf); } else if (type == REPORT_ERROR || type == REPORT_INFO) { ErrorLogger::ErrorMessage msg; msg.deserialize(buf); std::string file; unsigned int line(0); if (!msg._callStack.empty()) { file = msg._callStack.back().getfile(false); line = msg._callStack.back().line; } if (!_settings.nomsg.isSuppressed(msg._id, file, line)) { // Alert only about unique errors std::string errmsg = msg.toString(_settings._verbose); if (std::find(_errorList.begin(), _errorList.end(), errmsg) == _errorList.end()) { _errorList.push_back(errmsg); if (type == REPORT_ERROR) _errorLogger.reportErr(msg); else _errorLogger.reportInfo(msg); } } } else if (type == CHILD_END) { std::istringstream iss(buf); unsigned int fileResult = 0; iss >> fileResult; result += fileResult; delete [] buf; return -1; } delete [] buf; return 1; } unsigned int ThreadExecutor::check() { _fileCount = 0; unsigned int result = 0; std::size_t totalfilesize = 0; for (std::map::const_iterator i = _files.begin(); i != _files.end(); ++i) { totalfilesize += i->second; } std::list rpipes; std::map childFile; std::map pipeFile; std::size_t processedsize = 0; std::map::const_iterator i = _files.begin(); for (;;) { // Start a new child if (i != _files.end() && rpipes.size() < _settings._jobs) { int pipes[2]; if (pipe(pipes) == -1) { std::cerr << "pipe() failed: "<< std::strerror(errno) << std::endl; std::exit(EXIT_FAILURE); } int flags = 0; if ((flags = fcntl(pipes[0], F_GETFL, 0)) < 0) { std::cerr << "fcntl(F_GETFL) failed: "<< std::strerror(errno) << std::endl; std::exit(EXIT_FAILURE); } if (fcntl(pipes[0], F_SETFL, flags | O_NONBLOCK) < 0) { std::cerr << "fcntl(F_SETFL) failed: "<< std::strerror(errno) << std::endl; std::exit(EXIT_FAILURE); } pid_t pid = fork(); if (pid < 0) { // Error std::cerr << "Failed to create child process: "<< std::strerror(errno) << std::endl; std::exit(EXIT_FAILURE); } else if (pid == 0) { close(pipes[0]); _wpipe = pipes[1]; CppCheck fileChecker(*this, false); fileChecker.settings() = _settings; unsigned int resultOfCheck = 0; if (!_fileContents.empty() && _fileContents.find(i->first) != _fileContents.end()) { // File content was given as a string resultOfCheck = fileChecker.check(i->first, _fileContents[ i->first ]); } else { // Read file from a file resultOfCheck = fileChecker.check(i->first); } std::ostringstream oss; oss << resultOfCheck; writeToPipe(CHILD_END, oss.str()); std::exit(0); } close(pipes[1]); rpipes.push_back(pipes[0]); childFile[pid] = i->first; pipeFile[pipes[0]] = i->first; ++i; } else if (!rpipes.empty()) { fd_set rfds; FD_ZERO(&rfds); for (std::list::const_iterator rp = rpipes.begin(); rp != rpipes.end(); ++rp) FD_SET(*rp, &rfds); int r = select(*std::max_element(rpipes.begin(), rpipes.end()) + 1, &rfds, NULL, NULL, NULL); if (r > 0) { std::list::iterator rp = rpipes.begin(); while (rp != rpipes.end()) { if (FD_ISSET(*rp, &rfds)) { int readRes = handleRead(*rp, result); if (readRes == -1) { std::size_t size = 0; std::map::iterator p = pipeFile.find(*rp); if (p != pipeFile.end()) { std::string name = p->second; pipeFile.erase(p); std::map::const_iterator fs = _files.find(name); if (fs != _files.end()) { size = fs->second; } } _fileCount++; processedsize += size; if (!_settings._errorsOnly) CppCheckExecutor::reportStatus(_fileCount, _files.size(), processedsize, totalfilesize); close(*rp); rp = rpipes.erase(rp); } else ++rp; } else ++rp; } } int stat = 0; pid_t child = waitpid(0, &stat, WNOHANG); if (child > 0) { std::string childname; std::map::iterator c = childFile.find(child); if (c != childFile.end()) { childname = c->second; childFile.erase(c); } if (WIFSIGNALED(stat)) { std::ostringstream oss; oss << "Internal error: Child process crashed with signal " << WTERMSIG(stat); std::list locations; locations.push_back(ErrorLogger::ErrorMessage::FileLocation(childname, 0)); const ErrorLogger::ErrorMessage errmsg(locations, Severity::error, oss.str(), "cppcheckError", false); if (!_settings.nomsg.isSuppressed(errmsg._id, childname, 0)) _errorLogger.reportErr(errmsg); } } } else { // All done break; } } return result; } void ThreadExecutor::writeToPipe(PipeSignal type, const std::string &data) { unsigned int len = static_cast(data.length() + 1); char *out = new char[ len + 1 + sizeof(len)]; out[0] = static_cast(type); std::memcpy(&(out[1]), &len, sizeof(len)); std::memcpy(&(out[1+sizeof(len)]), data.c_str(), len); if (write(_wpipe, out, len + 1 + sizeof(len)) <= 0) { delete [] out; out = 0; std::cerr << "#### ThreadExecutor::writeToPipe, Failed to write to pipe" << std::endl; std::exit(0); } delete [] out; } void ThreadExecutor::reportOut(const std::string &outmsg) { writeToPipe(REPORT_OUT, outmsg); } void ThreadExecutor::reportErr(const ErrorLogger::ErrorMessage &msg) { writeToPipe(REPORT_ERROR, msg.serialize()); } void ThreadExecutor::reportInfo(const ErrorLogger::ErrorMessage &msg) { writeToPipe(REPORT_INFO, msg.serialize()); } #elif defined(THREADING_MODEL_WIN) void ThreadExecutor::addFileContent(const std::string &path, const std::string &content) { _fileContents[path] = content; } unsigned int ThreadExecutor::check() { HANDLE *threadHandles = new HANDLE[_settings._jobs]; _itNextFile = _files.begin(); _processedFiles = 0; _processedSize = 0; _totalFiles = _files.size(); _totalFileSize = 0; for (std::map::const_iterator i = _files.begin(); i != _files.end(); ++i) { _totalFileSize += i->second; } InitializeCriticalSection(&_fileSync); InitializeCriticalSection(&_errorSync); InitializeCriticalSection(&_reportSync); for (unsigned int i = 0; i < _settings._jobs; ++i) { threadHandles[i] = (HANDLE)_beginthreadex(NULL, 0, threadProc, this, 0, NULL); if (!threadHandles[i]) { std::cerr << "#### .\nThreadExecutor::check error, errno :" << errno << std::endl; exit(EXIT_FAILURE); } } DWORD waitResult = WaitForMultipleObjects(_settings._jobs, threadHandles, TRUE, INFINITE); if (waitResult != WAIT_OBJECT_0) { if (waitResult == WAIT_FAILED) { std::cerr << "#### .\nThreadExecutor::check wait failed, result: " << waitResult << " error: " << GetLastError() << std::endl; exit(EXIT_FAILURE); } else { std::cerr << "#### .\nThreadExecutor::check wait failed, result: " << waitResult << std::endl; exit(EXIT_FAILURE); } } unsigned int result = 0; for (unsigned int i = 0; i < _settings._jobs; ++i) { DWORD exitCode; if (!GetExitCodeThread(threadHandles[i], &exitCode)) { std::cerr << "#### .\nThreadExecutor::check get exit code failed, error:" << GetLastError() << std::endl; exit(EXIT_FAILURE); } result += exitCode; if (!CloseHandle(threadHandles[i])) { std::cerr << "#### .\nThreadExecutor::check close handle failed, error:" << GetLastError() << std::endl; exit(EXIT_FAILURE); } } DeleteCriticalSection(&_fileSync); DeleteCriticalSection(&_errorSync); DeleteCriticalSection(&_reportSync); delete[] threadHandles; return result; } unsigned int __stdcall ThreadExecutor::threadProc(void *args) { unsigned int result = 0; ThreadExecutor *threadExecutor = static_cast(args); std::map::const_iterator &it = threadExecutor->_itNextFile; // guard static members of CppCheck against concurrent access EnterCriticalSection(&threadExecutor->_fileSync); CppCheck fileChecker(*threadExecutor, false); fileChecker.settings() = threadExecutor->_settings; LeaveCriticalSection(&threadExecutor->_fileSync); for (;;) { EnterCriticalSection(&threadExecutor->_fileSync); if (it == threadExecutor->_files.end()) { LeaveCriticalSection(&threadExecutor->_fileSync); return result; } const std::string &file = it->first; const std::size_t fileSize = it->second; ++it; LeaveCriticalSection(&threadExecutor->_fileSync); std::map::const_iterator fileContent = threadExecutor->_fileContents.find(file); if (fileContent != threadExecutor->_fileContents.end()) { // File content was given as a string result += fileChecker.check(file, fileContent->second); } else { // Read file from a file result += fileChecker.check(file); } EnterCriticalSection(&threadExecutor->_fileSync); threadExecutor->_processedSize += fileSize; threadExecutor->_processedFiles++; if (!threadExecutor->_settings._errorsOnly) { EnterCriticalSection(&threadExecutor->_reportSync); CppCheckExecutor::reportStatus(threadExecutor->_processedFiles, threadExecutor->_totalFiles, threadExecutor->_processedSize, threadExecutor->_totalFileSize); LeaveCriticalSection(&threadExecutor->_reportSync); } LeaveCriticalSection(&threadExecutor->_fileSync); }; return result; } void ThreadExecutor::reportOut(const std::string &outmsg) { EnterCriticalSection(&_reportSync); _errorLogger.reportOut(outmsg); LeaveCriticalSection(&_reportSync); } void ThreadExecutor::reportErr(const ErrorLogger::ErrorMessage &msg) { report(msg, REPORT_ERROR); } void ThreadExecutor::reportInfo(const ErrorLogger::ErrorMessage &msg) { report(msg, REPORT_INFO); } void ThreadExecutor::report(const ErrorLogger::ErrorMessage &msg, MessageType msgType) { std::string file; unsigned int line(0); if (!msg._callStack.empty()) { file = msg._callStack.back().getfile(false); line = msg._callStack.back().line; } if (_settings.nomsg.isSuppressed(msg._id, file, line)) return; // Alert only about unique errors bool reportError = false; std::string errmsg = msg.toString(_settings._verbose); EnterCriticalSection(&_errorSync); if (std::find(_errorList.begin(), _errorList.end(), errmsg) == _errorList.end()) { _errorList.push_back(errmsg); reportError = true; } LeaveCriticalSection(&_errorSync); if (reportError) { EnterCriticalSection(&_reportSync); switch (msgType) { case REPORT_ERROR: _errorLogger.reportErr(msg); break; case REPORT_INFO: _errorLogger.reportInfo(msg); break; } LeaveCriticalSection(&_reportSync); } } #else void ThreadExecutor::addFileContent(const std::string &/*path*/, const std::string &/*content*/) { } unsigned int ThreadExecutor::check() { return 0; } void ThreadExecutor::reportOut(const std::string &/*outmsg*/) { } void ThreadExecutor::reportErr(const ErrorLogger::ErrorMessage &/*msg*/) { } void ThreadExecutor::reportInfo(const ErrorLogger::ErrorMessage &/*msg*/) { } #endif cppcheck-1.61/cli/threadexecutor.h000066400000000000000000000100361217722632100171720ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #ifndef THREADEXECUTOR_H #define THREADEXECUTOR_H #include #include #include #include "errorlogger.h" #if (defined(__GNUC__) || defined(__sun)) && !defined(__MINGW32__) #define THREADING_MODEL_FORK #elif defined(_WIN32) #define THREADING_MODEL_WIN #include #endif class Settings; /// @addtogroup CLI /// @{ /** * This class will take a list of filenames and settings and check then * all files using threads. */ class ThreadExecutor : public ErrorLogger { public: ThreadExecutor(const std::map &files, Settings &settings, ErrorLogger &_errorLogger); virtual ~ThreadExecutor(); unsigned int check(); virtual void reportOut(const std::string &outmsg); virtual void reportErr(const ErrorLogger::ErrorMessage &msg); virtual void reportInfo(const ErrorLogger::ErrorMessage &msg); /** * @brief Add content to a file, to be used in unit testing. * * @param path File name (used as a key to link with real file). * @param content If the file would be a real file, this should be * the content of the file. */ void addFileContent(const std::string &path, const std::string &content); private: const std::map &_files; Settings &_settings; ErrorLogger &_errorLogger; unsigned int _fileCount; #if defined(THREADING_MODEL_FORK) /** @brief Key is file name, and value is the content of the file */ std::map _fileContents; private: enum PipeSignal {REPORT_OUT='1',REPORT_ERROR='2', REPORT_INFO='3', CHILD_END='4'}; /** * Read from the pipe, parse and handle what ever is in there. *@return -1 in case of error * 0 if there is nothing in the pipe to be read * 1 if we did read something */ int handleRead(int rpipe, unsigned int &result); void writeToPipe(PipeSignal type, const std::string &data); /** * Write end of status pipe, different for each child. * Not used in master process. */ std::list _errorList; int _wpipe; public: /** * @return true if support for threads exist. */ static bool isEnabled() { return true; } #elif defined(THREADING_MODEL_WIN) private: enum MessageType {REPORT_ERROR, REPORT_INFO}; std::map _fileContents; std::map::const_iterator _itNextFile; std::size_t _processedFiles; std::size_t _totalFiles; std::size_t _processedSize; std::size_t _totalFileSize; CRITICAL_SECTION _fileSync; std::list _errorList; CRITICAL_SECTION _errorSync; CRITICAL_SECTION _reportSync; void report(const ErrorLogger::ErrorMessage &msg, MessageType msgType); static unsigned __stdcall threadProc(void*); public: /** * @return true if support for threads exist. */ static bool isEnabled() { return true; } #else public: /** * @return true if support for threads exist. */ static bool isEnabled() { return false; } #endif private: /** disabled copy constructor */ ThreadExecutor(const ThreadExecutor &); /** disabled assignment operator */ void operator=(const ThreadExecutor &); }; /// @} #endif // THREADEXECUTOR_H cppcheck-1.61/cli/version.rc000066400000000000000000000016441217722632100160130ustar00rootroot00000000000000#include "../lib/version.h" #include "winresrc.h" VS_VERSION_INFO VERSIONINFO FILEVERSION CPPCHECK_VERSION PRODUCTVERSION CPPCHECK_VERSION FILEFLAGSMASK 0x17L #ifdef _DEBUG FILEFLAGS (0x1L|VS_FF_PRERELEASE) #else FILEFLAGS (0x0L|VS_FF_PRERELEASE) #endif FILEOS VOS__WINDOWS32 FILETYPE VFT_APP FILESUBTYPE VFT2_UNKNOWN BEGIN BLOCK "StringFileInfo" BEGIN BLOCK "040904b0" BEGIN VALUE "FileDescription", "cppcheck Application" VALUE "FileVersion", CPPCHECK_VERSION_STRING VALUE "InternalName", "cppcheck" VALUE "LegalCopyright", LEGALCOPYRIGHT VALUE "OriginalFilename", "cppcheck.exe" VALUE "ProductName", "cppcheck Application" VALUE "ProductVersion", CPPCHECK_VERSION_STRING END END BLOCK "VarFileInfo" BEGIN VALUE "Translation", 0x409, 1200 END END cppcheck-1.61/console_common.pri000066400000000000000000000010731217722632100167530ustar00rootroot00000000000000# console_common.pri # These are common definitions for console builds. win32 { CONFIG += embed_manifest_exe console DEFINES += _CRT_SECURE_NO_WARNINGS LIBS += -lshlwapi } # Add more strict compiling flags for GCC contains(QMAKE_CXX, g++) { QMAKE_CXXFLAGS_WARN_ON += -Wextra -pedantic -Wfloat-equal -Wcast-qual -Wlogical-op -Wno-long-long } # Change Visual Studio compiler (CL) warning level to W4 contains(QMAKE_CXX, cl) { QMAKE_CXXFLAGS_WARN_ON -= -W3 QMAKE_CXXFLAGS_WARN_ON += -W4 } CONFIG(release, debug|release) { DEFINES += NDEBUG } cppcheck-1.61/cppcheck.cbp000066400000000000000000000213671217722632100155030ustar00rootroot00000000000000 cppcheck-1.61/cppcheck.cppcheck000066400000000000000000000007731217722632100165150ustar00rootroot00000000000000 cppcheck-1.61/cppcheck.sln000066400000000000000000000041041217722632100155210ustar00rootroot00000000000000Microsoft Visual Studio Solution File, Format Version 10.00 # Visual Studio 2008 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cppcheck", "cli\cppcheck.vcproj", "{230A4467-25A6-3276-A1D0-CB521812CD43}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testrunner", "test\testrunner.vcproj", "{A1772A4C-E3F0-33FC-9A59-2189857FB799}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Debug-x64|Win32 = Debug-x64|Win32 Release|Win32 = Release|Win32 Release-x64|Win32 = Release-x64|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {230A4467-25A6-3276-A1D0-CB521812CD43}.Debug|Win32.ActiveCfg = Debug|Win32 {230A4467-25A6-3276-A1D0-CB521812CD43}.Debug|Win32.Build.0 = Debug|Win32 {230A4467-25A6-3276-A1D0-CB521812CD43}.Debug-x64|Win32.ActiveCfg = Debug-x64|Win32 {230A4467-25A6-3276-A1D0-CB521812CD43}.Debug-x64|Win32.Build.0 = Debug-x64|Win32 {230A4467-25A6-3276-A1D0-CB521812CD43}.Release|Win32.ActiveCfg = Release|Win32 {230A4467-25A6-3276-A1D0-CB521812CD43}.Release|Win32.Build.0 = Release|Win32 {230A4467-25A6-3276-A1D0-CB521812CD43}.Release-x64|Win32.ActiveCfg = Release-x64|Win32 {230A4467-25A6-3276-A1D0-CB521812CD43}.Release-x64|Win32.Build.0 = Release-x64|Win32 {A1772A4C-E3F0-33FC-9A59-2189857FB799}.Debug|Win32.ActiveCfg = Debug|Win32 {A1772A4C-E3F0-33FC-9A59-2189857FB799}.Debug|Win32.Build.0 = Debug|Win32 {A1772A4C-E3F0-33FC-9A59-2189857FB799}.Debug-x64|Win32.ActiveCfg = Debug-x64|Win32 {A1772A4C-E3F0-33FC-9A59-2189857FB799}.Debug-x64|Win32.Build.0 = Debug-x64|Win32 {A1772A4C-E3F0-33FC-9A59-2189857FB799}.Release|Win32.ActiveCfg = Release|Win32 {A1772A4C-E3F0-33FC-9A59-2189857FB799}.Release|Win32.Build.0 = Release|Win32 {A1772A4C-E3F0-33FC-9A59-2189857FB799}.Release-x64|Win32.ActiveCfg = Release-x64|Win32 {A1772A4C-E3F0-33FC-9A59-2189857FB799}.Release-x64|Win32.Build.0 = Release-x64|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal cppcheck-1.61/cppcheck_vs2010.sln000066400000000000000000000122261217722632100165400ustar00rootroot00000000000000 Microsoft Visual Studio Solution File, Format Version 11.00 # Visual C++ Express 2010 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cli", "cli\cli.vcxproj", "{35CBDF51-2456-3EC3-99ED-113C30858883}" ProjectSection(ProjectDependencies) = postProject {C183DB5B-AD6C-423D-80CA-1F9549555A1A} = {C183DB5B-AD6C-423D-80CA-1F9549555A1A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testrunner", "test\testrunner.vcxproj", "{4F7DCE5E-6CDE-38C4-9EA7-27AF3B25CEB4}" ProjectSection(ProjectDependencies) = postProject {C183DB5B-AD6C-423D-80CA-1F9549555A1A} = {C183DB5B-AD6C-423D-80CA-1F9549555A1A} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cppcheck", "lib\cppcheck.vcxproj", "{C183DB5B-AD6C-423D-80CA-1F9549555A1A}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Debug|x64 = Debug|x64 Debug-PCRE|Win32 = Debug-PCRE|Win32 Debug-PCRE|x64 = Debug-PCRE|x64 Release|Win32 = Release|Win32 Release|x64 = Release|x64 Release-PCRE|Win32 = Release-PCRE|Win32 Release-PCRE|x64 = Release-PCRE|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {35CBDF51-2456-3EC3-99ED-113C30858883}.Debug|Win32.ActiveCfg = Debug|Win32 {35CBDF51-2456-3EC3-99ED-113C30858883}.Debug|Win32.Build.0 = Debug|Win32 {35CBDF51-2456-3EC3-99ED-113C30858883}.Debug|x64.ActiveCfg = Debug|x64 {35CBDF51-2456-3EC3-99ED-113C30858883}.Debug|x64.Build.0 = Debug|x64 {35CBDF51-2456-3EC3-99ED-113C30858883}.Debug-PCRE|Win32.ActiveCfg = Debug-PCRE|Win32 {35CBDF51-2456-3EC3-99ED-113C30858883}.Debug-PCRE|Win32.Build.0 = Debug-PCRE|Win32 {35CBDF51-2456-3EC3-99ED-113C30858883}.Debug-PCRE|x64.ActiveCfg = Debug-PCRE|x64 {35CBDF51-2456-3EC3-99ED-113C30858883}.Debug-PCRE|x64.Build.0 = Debug-PCRE|x64 {35CBDF51-2456-3EC3-99ED-113C30858883}.Release|Win32.ActiveCfg = Release|Win32 {35CBDF51-2456-3EC3-99ED-113C30858883}.Release|Win32.Build.0 = Release|Win32 {35CBDF51-2456-3EC3-99ED-113C30858883}.Release|x64.ActiveCfg = Release|x64 {35CBDF51-2456-3EC3-99ED-113C30858883}.Release|x64.Build.0 = Release|x64 {35CBDF51-2456-3EC3-99ED-113C30858883}.Release-PCRE|Win32.ActiveCfg = Release-PCRE|Win32 {35CBDF51-2456-3EC3-99ED-113C30858883}.Release-PCRE|Win32.Build.0 = Release-PCRE|Win32 {35CBDF51-2456-3EC3-99ED-113C30858883}.Release-PCRE|x64.ActiveCfg = Release-PCRE|x64 {35CBDF51-2456-3EC3-99ED-113C30858883}.Release-PCRE|x64.Build.0 = Release-PCRE|x64 {4F7DCE5E-6CDE-38C4-9EA7-27AF3B25CEB4}.Debug|Win32.ActiveCfg = Debug|Win32 {4F7DCE5E-6CDE-38C4-9EA7-27AF3B25CEB4}.Debug|Win32.Build.0 = Debug|Win32 {4F7DCE5E-6CDE-38C4-9EA7-27AF3B25CEB4}.Debug|x64.ActiveCfg = Debug|x64 {4F7DCE5E-6CDE-38C4-9EA7-27AF3B25CEB4}.Debug|x64.Build.0 = Debug|x64 {4F7DCE5E-6CDE-38C4-9EA7-27AF3B25CEB4}.Debug-PCRE|Win32.ActiveCfg = Debug|Win32 {4F7DCE5E-6CDE-38C4-9EA7-27AF3B25CEB4}.Debug-PCRE|Win32.Build.0 = Debug|Win32 {4F7DCE5E-6CDE-38C4-9EA7-27AF3B25CEB4}.Debug-PCRE|x64.ActiveCfg = Debug|x64 {4F7DCE5E-6CDE-38C4-9EA7-27AF3B25CEB4}.Debug-PCRE|x64.Build.0 = Debug|x64 {4F7DCE5E-6CDE-38C4-9EA7-27AF3B25CEB4}.Release|Win32.ActiveCfg = Release|Win32 {4F7DCE5E-6CDE-38C4-9EA7-27AF3B25CEB4}.Release|Win32.Build.0 = Release|Win32 {4F7DCE5E-6CDE-38C4-9EA7-27AF3B25CEB4}.Release|x64.ActiveCfg = Release|x64 {4F7DCE5E-6CDE-38C4-9EA7-27AF3B25CEB4}.Release|x64.Build.0 = Release|x64 {4F7DCE5E-6CDE-38C4-9EA7-27AF3B25CEB4}.Release-PCRE|Win32.ActiveCfg = Release|Win32 {4F7DCE5E-6CDE-38C4-9EA7-27AF3B25CEB4}.Release-PCRE|Win32.Build.0 = Release|Win32 {4F7DCE5E-6CDE-38C4-9EA7-27AF3B25CEB4}.Release-PCRE|x64.ActiveCfg = Release|x64 {4F7DCE5E-6CDE-38C4-9EA7-27AF3B25CEB4}.Release-PCRE|x64.Build.0 = Release|x64 {C183DB5B-AD6C-423D-80CA-1F9549555A1A}.Debug|Win32.ActiveCfg = Debug|Win32 {C183DB5B-AD6C-423D-80CA-1F9549555A1A}.Debug|Win32.Build.0 = Debug|Win32 {C183DB5B-AD6C-423D-80CA-1F9549555A1A}.Debug|x64.ActiveCfg = Debug|x64 {C183DB5B-AD6C-423D-80CA-1F9549555A1A}.Debug|x64.Build.0 = Debug|x64 {C183DB5B-AD6C-423D-80CA-1F9549555A1A}.Debug-PCRE|Win32.ActiveCfg = Debug-PCRE|Win32 {C183DB5B-AD6C-423D-80CA-1F9549555A1A}.Debug-PCRE|Win32.Build.0 = Debug-PCRE|Win32 {C183DB5B-AD6C-423D-80CA-1F9549555A1A}.Debug-PCRE|x64.ActiveCfg = Debug-PCRE|x64 {C183DB5B-AD6C-423D-80CA-1F9549555A1A}.Debug-PCRE|x64.Build.0 = Debug-PCRE|x64 {C183DB5B-AD6C-423D-80CA-1F9549555A1A}.Release|Win32.ActiveCfg = Release|Win32 {C183DB5B-AD6C-423D-80CA-1F9549555A1A}.Release|Win32.Build.0 = Release|Win32 {C183DB5B-AD6C-423D-80CA-1F9549555A1A}.Release|x64.ActiveCfg = Release|x64 {C183DB5B-AD6C-423D-80CA-1F9549555A1A}.Release|x64.Build.0 = Release|x64 {C183DB5B-AD6C-423D-80CA-1F9549555A1A}.Release-PCRE|Win32.ActiveCfg = Release-PCRE|Win32 {C183DB5B-AD6C-423D-80CA-1F9549555A1A}.Release-PCRE|Win32.Build.0 = Release-PCRE|Win32 {C183DB5B-AD6C-423D-80CA-1F9549555A1A}.Release-PCRE|x64.ActiveCfg = Release-PCRE|x64 {C183DB5B-AD6C-423D-80CA-1F9549555A1A}.Release-PCRE|x64.Build.0 = Release-PCRE|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal cppcheck-1.61/createrelease000077500000000000000000000037661217722632100157720ustar00rootroot00000000000000#!/bin/bash # # A script for creating release packages. The release packages are create in the home directory. # # Test cppcheck on itself. # cppcheck -q -j2 --inconclusive --enable=all lib # # Make sure "cppcheck --errorlist" works. For example with: # make test # cppcheck --errorlist > errlist.xml # xmllint --noout errlist.xml # cppcheck --xml-version=2 --errorlist > errlist.xml # xmllint --noout errlist.xml # # Update AUTHORS using output from: # git log --format='%aN' | sort -u # # Update version numbers in: # - cli/main.cpp # - lib/cppcheck.cpp # - lib/version.h # - man/manual.docbook # - win_installer/productInfo.wxs # # Update the Changelog.. # wget http://josefsson.org/git2cl/git2cl # chmod 744 git2cl # ./git2cl > Changelog # git commit -a -m "1.43: Updated Changelog" # # Update the Makefile: # make dmake # ./dmake --release # git commit -a -m "1.43: Updated Makefile" # # Build and test the windows installer # # Tag: # git tag 1.43 # git push --tags # # Create release: # ./createrelease 1.43 # # Restore the Makefile: # ./dmake # git commit -a -m "Makefile: Set debug mode" # # Generate the manual.pdf, manual.html and version.txt # make # ./cppcheck --version > version.txt # docbook2pdf man/manual.docbook # xsltproc -o manual.html /usr/share/xml/docbook/stylesheet/nwalsh/xhtml/docbook.xsl man/manual.docbook # # Upload manual.pdf , manual.html and version.txt... # sftp danielmarjamaki,cppcheck@web.sourceforge.net # # save "cppcheck --doc" output on wiki # # compile new democlient: # ssh -t danielmarjamaki,cppcheck@shell.sourceforge.net # ./build.sh 1.43 # Tag to use tag=$1 # Name of release releasename=cppcheck-$tag # Create archives.. git archive --format=tar --prefix=$releasename/ $tag | gzip > ~/$releasename.tar.gz git archive --format=tar --prefix=$releasename/ $tag | bzip2 > ~/$releasename.tar.bz2 git archive --format=zip -9 --prefix=$releasename/ $tag > ~/$releasename.zip scp ../$releasename.* danielmarjamaki,cppcheck@frs.sourceforge.net:/home/frs/project/c/cp/cppcheck/cppcheck/$tag/ cppcheck-1.61/democlient/000077500000000000000000000000001217722632100153475ustar00rootroot00000000000000cppcheck-1.61/democlient/build.sh000077500000000000000000000013101217722632100170000ustar00rootroot00000000000000#!/bin/bash # this script downloads and builds the democlient # syntax: # ./build 1.60.1 # cppcheck lib folder cppchecklib=cppcheck-$1/lib echo Downloading... wget http://downloads.sourceforge.net/project/cppcheck/cppcheck/$1/cppcheck-$1.tar.bz2 echo Unpacking... tar xjvf cppcheck-$1.tar.bz2 rm cppcheck-$1.tar.bz2 rm cppcheck-$1/Changelog echo Building... g++ -O2 -o democlient-$1.cgi -I$cppchecklib -Icppcheck-$1/externals/tinyxml cppcheck-$1/democlient/democlient.cpp $cppchecklib/*.cpp cppcheck-$1/externals/tinyxml/tinyxml2.cpp echo Copy cgi to webspace... cp democlient-$1.cgi /home/project-web/cppcheck/cgi-bin/democlient.cgi chmod +rx /home/project-web/cppcheck/cgi-bin/democlient.cgi echo Done! cppcheck-1.61/democlient/democlient.cpp000066400000000000000000000046521217722632100202050ustar00rootroot00000000000000#include #include #include #include #include #include "cppcheck.h" static void unencode(const char *src, char *dest) { for (; *src; src++, dest++) { if (*src == '+') *dest = ' '; else if (*src == '%') { int code; if (sscanf(src+1, "%2x", &code) != 1) code = '?'; *dest = code; src += 2; } else *dest = *src; } *dest = '\0'; } class CppcheckExecutor : public ErrorLogger { private: const std::time_t stoptime; CppCheck cppcheck; public: CppcheckExecutor() : ErrorLogger() , stoptime(std::time(NULL)+2U) , cppcheck(*this,false) { cppcheck.settings().addEnabled("all"); cppcheck.settings().inconclusive = true; } void run(const char code[]) { printf("%s\n", ErrorLogger::ErrorMessage::getXMLHeader(2).c_str()); cppcheck.check("test.c", code); printf("%s\n", ErrorLogger::ErrorMessage::getXMLFooter(2).c_str()); printf("\n\n"); } void reportOut(const std::string &outmsg) { } void reportErr(const ErrorLogger::ErrorMessage &msg) { const std::string str(msg.toXML(true,2U)); printf("%s\n", str.c_str()); } void reportProgress(const std::string &filename, const char stage[], const unsigned int value) { if (std::time(NULL) >= stoptime) { printf("time to analyse the " "code is more than 1 " "second. terminating." "\n\n"); cppcheck.terminate(); } } }; int main() { char data[4096] = {0}; const char *lenstr = getenv("CONTENT_LENGTH"); if (lenstr) { int len = std::min(1 + atoi(lenstr), (int)(sizeof(data) - 2)); fgets(data, len, stdin); } else { const char *s = getenv("QUERY_STRING"); std::strncpy(data, s?s:"", sizeof(data)-2); } char code[4096] = {0}; unencode(data, code); FILE *logfile = fopen("democlient.log", "at"); if (logfile != NULL) { fprintf(logfile, "===========================================================\n%s\n", code); fclose(logfile); } printf("Content-type: text/plain\n\n"); CppcheckExecutor cppcheckExecutor; cppcheckExecutor.run(code); return EXIT_SUCCESS; } cppcheck-1.61/doxyfile000066400000000000000000002225521217722632100150020ustar00rootroot00000000000000# Doxyfile 1.7.5.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or sequence of words) that should # identify the project. Note that if you do not use Doxywizard you need # to put quotes around the project name if it contains spaces. PROJECT_NAME = Cppcheck # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer # a quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = # With the PROJECT_LOGO tag one can specify an logo or icon that is # included in the documentation. The maximum height of the logo should not # exceed 55 pixels and the maximum width should not exceed 200 pixels. # Doxygen will copy the logo to the output directory. PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = doxyoutput # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English # messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, # Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, # Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = NO # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful if your file system # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = YES # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given extension. # Doxygen has a built-in mapping, but you can override or extend it using this # tag. The format is ext=language, where ext is a file extension, and language # is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, # C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make # doxygen treat .inc files as Fortran files (default is PHP), and .f files as C # (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions # you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. EXTENSION_MAPPING = # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also makes the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate getter # and setter methods for a property. Setting this option to YES (the default) # will make doxygen replace the get and set methods by a property in the # documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and # unions are shown inside the group in which they are included (e.g. using # @ingroup) instead of on a separate page (for HTML and Man pages) or # section (for LaTeX and RTF). INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and # unions with only public data fields will be shown inline in the documentation # of the scope in which they are defined (i.e. file, namespace, or group # documentation), provided this scope is documented. If set to NO (the default), # structs, classes, and unions are shown on a separate page (for HTML and Man # pages) or section (for LaTeX and RTF). INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO # The SYMBOL_CACHE_SIZE determines the size of the internal cache use to # determine which symbols to keep in memory and which to flush to disk. # When the cache is full, less often used symbols will be written to disk. # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time # causing a significant performance penalty. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on # a logarithmic scale so increasing the size by one will roughly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols SYMBOL_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = YES # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespaces are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen # will list include files with double quotes in the documentation # rather than with sharp brackets. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen # will sort the (brief and detailed) documentation of class members so that # constructors and destructors are listed first. If set to NO (the default) # the constructors will appear in the respective orders defined by # SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. # This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO # and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to # do proper type resolution of all parameters of a function it will reject a # match between the prototype and the implementation of a member function even # if there is only one candidate or it is obvious which candidate to choose # by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen # will still accept a match between prototype and implementation in such cases. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or macro consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and macros in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = NO # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. The create the layout file # that represents doxygen's defaults, run doxygen with the -l option. # You can optionally specify a file name after the option, if omitted # DoxygenLayout.xml will be used as the name of the layout file. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files # containing the references data. This must be a list of .bib files. The # .bib extension is automatically appended if omitted. Using this command # requires the bibtex tool to be installed. See also # http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style # of the bibliography can be controlled using LATEX_BIB_STYLE. CITE_BIB_FILES = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # The WARN_NO_PARAMDOC option can be enabled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = cli/ \ gui/ \ lib/ # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh # *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py # *.f90 *.f *.for *.vhd *.vhdl FILE_PATTERNS = # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # Note that relative paths are relative to directory from which doxygen is run. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty or if # non of the patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) # and it is also possible to disable source filtering for a specific pattern # using *.ext= (so without naming a filter). This option only has effect when # FILTER_SOURCE_FILES is enabled. FILTER_SOURCE_PATTERNS = #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = NO # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = YES # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = YES # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = NO # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. Note that when using a custom header you are responsible # for the proper inclusion of any scripts and style sheets that doxygen # needs, which is dependent on the configuration options used. # It is adviced to generate a default header using "doxygen -w html # header.html footer.html stylesheet.css YourConfigFile" and then modify # that header. Note that the header is subject to change so you typically # have to redo this when upgrading to a newer version of doxygen or when # changing the value of configuration settings such as GENERATE_TREEVIEW! HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that # the files will be copied as-is; there are no commands or markers available. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. # Doxygen will adjust the colors in the stylesheet and background images # according to this color. Hue is specified as an angle on a colorwheel, # see http://en.wikipedia.org/wiki/Hue for more information. # For instance the value 0 represents red, 60 is yellow, 120 is green, # 180 is cyan, 240 is blue, 300 purple, and 360 is red again. # The allowed range is 0 to 359. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of # the colors in the HTML output. For a value of 0 the output will use # grayscales only. A value of 255 will produce the most vivid colors. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to # the luminance component of the colors in the HTML output. Values below # 100 gradually make the output lighter, whereas values above 100 make # the output darker. The value divided by 100 is the actual gamma applied, # so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, # and 100 does not change the gamma. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting # this to NO can help when comparing the output of multiple runs. HTML_TIMESTAMP = YES # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). HTML_DYNAMIC_SECTIONS = NO # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated # that can be used as input for Qt's qhelpgenerator to generate a # Qt Compressed Help (.qch) of the generated HTML documentation. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = doc # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to # add. For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see # # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's # filter section matches. # # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files # will be generated, which together with the HTML files, form an Eclipse help # plugin. To install this plugin and make it available under the help contents # menu in Eclipse, the contents of the directory containing the HTML and XML # files needs to be copied into the plugins directory of eclipse. The name of # the directory within the plugins directory should be the same as # the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before # the help appears. GENERATE_ECLIPSEHELP = NO # A unique identifier for the eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have # this name. ECLIPSE_DOC_ID = org.doxygen.Project # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values # (range [0,1..20]) that doxygen will group on one line in the generated HTML # documentation. Note that a value of 0 will completely suppress the enum # values from appearing in the overview section. ENUM_VALUES_PER_LINE = 4 # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to YES, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, # and Class Hierarchy pages using a tree view instead of an ordered list. USE_INLINE_TREES = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open # links to external symbols imported via tag files in a separate window. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are # not supported properly for IE 6.0, but are supported on all modern browsers. # Note that when changing this option you need to delete any form_*.png files # in the HTML output before the changes have effect. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax # (see http://www.mathjax.org) which uses client side Javascript for the # rendering instead of using prerendered bitmaps. Use this if you do not # have LaTeX installed or if you want to formulas look prettier in the HTML # output. When enabled you also need to install MathJax separately and # configure the path to it using the MATHJAX_RELPATH option. USE_MATHJAX = NO # When MathJax is enabled you need to specify the location relative to the # HTML output directory using the MATHJAX_RELPATH option. The destination # directory should contain the MathJax.js script. For instance, if the mathjax # directory is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to the # mathjax.org site, so you can quickly see the result without installing # MathJax, but it is strongly recommended to install a local copy of MathJax # before deployment. MATHJAX_RELPATH = http://www.mathjax.org/mathjax # The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension # names that should be enabled during MathJax rendering. MATHJAX_EXTENSIONS = # When the SEARCHENGINE tag is enabled doxygen will generate a search box # for the HTML output. The underlying search engine uses javascript # and DHTML and should work on any modern browser. Note that when using # HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets # (GENERATE_DOCSET) there is already a search function so this one should # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. SEARCHENGINE = NO # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a PHP enabled web server instead of at the web client # using Javascript. Doxygen will generate the search PHP script and index # file to put on the web server. The advantage of the server # based approach is that it scales better to large projects and allows # full text search. The disadvantages are that it is more difficult to setup # and does not have live searching capabilities. SERVER_BASED_SEARCH = NO #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. # Note that when enabling USE_PDFLATEX this option is only used for # generating bitmaps for formulas in the HTML output, but not in the # Makefile that is written to the output directory. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for # the generated latex document. The footer should contain everything after # the last chapter. If it is left blank doxygen will generate a # standard footer. Notice: only use this tag if you know what you are doing! LATEX_FOOTER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO # If LATEX_SOURCE_CODE is set to YES then doxygen will include # source code with syntax highlighting in the LaTeX output. # Note that which sources are shown also depends on other settings # such as SOURCE_BROWSER. LATEX_SOURCE_CODE = NO # The LATEX_BIB_STYLE tag can be used to specify the style to use for the # bibliography, e.g. plainnat, or ieeetr. The default style is "plain". See # http://en.wikipedia.org/wiki/BibTeX for more info. LATEX_BIB_STYLE = plain #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. This is useful # if you want to understand what is going on. On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # pointed to by INCLUDE_PATH will be searched when a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition that # overrules the definition found in the source code. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all references to function-like macros # that are alone on a line, have an all uppercase name, and do not end with a # semicolon, because these will confuse the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option also works with HAVE_DOT disabled, but it is recommended to # install and use dot, since it yields more powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is # allowed to run in parallel. When set to 0 (the default) doxygen will # base this on the number of processors available in the system. You can set it # explicitly to a value larger than 0 to get control over the balance # between CPU load and processing speed. DOT_NUM_THREADS = 0 # By default doxygen will use the Helvetica font for all dot files that # doxygen generates. When you want a differently looking font you can specify # the font name using DOT_FONTNAME. You need to make sure dot is able to find # the font, which can be done by putting it in a standard location or by setting # the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the # directory containing the font. DOT_FONTNAME = Helvetica # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the Helvetica font. # If you specify a different font using DOT_FONTNAME you can use DOT_FONTPATH to # set the path where dot can find it. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will generate a graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are svg, png, jpg, or gif. # If left blank png will be used. If you choose svg you need to set # HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible in IE 9+ (other browsers do not have this requirement). DOT_IMAGE_FORMAT = png # If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to # enable generation of interactive SVG images that allow zooming and panning. # Note that this requires a modern browser other than Internet Explorer. # Tested and working are Firefox, Chrome, Safari, and Opera. For IE 9+ you # need to set HTML_FILE_EXTENSION to xhtml in order to make the SVG files # visible. Older versions of IE do not have SVG support. INTERACTIVE_SVG = NO # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The MSCFILE_DIRS tag can be used to specify one or more directories that # contain msc files that are included in the documentation (see the # \mscfile command). MSCFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = YES # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = NO # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES cppcheck-1.61/externals/000077500000000000000000000000001217722632100152315ustar00rootroot00000000000000cppcheck-1.61/externals/tinyxml/000077500000000000000000000000001217722632100167355ustar00rootroot00000000000000cppcheck-1.61/externals/tinyxml/tinyxml.pri000066400000000000000000000001101217722632100211450ustar00rootroot00000000000000HEADERS += $${BASEPATH}tinyxml2.h SOURCES += $${BASEPATH}tinyxml2.cpp cppcheck-1.61/externals/tinyxml/tinyxml2.cpp000066400000000000000000001466721217722632100212470ustar00rootroot00000000000000/* Original code by Lee Thomason (www.grinninglizard.com) 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. */ #include "tinyxml2.h" #include // yes, this one new style header, is in the Android SDK. # ifdef ANDROID_NDK # include #else # include #endif static const char LINE_FEED = (char)0x0a; // all line endings are normalized to LF static const char LF = LINE_FEED; static const char CARRIAGE_RETURN = (char)0x0d; // CR gets filtered out static const char CR = CARRIAGE_RETURN; static const char SINGLE_QUOTE = '\''; static const char DOUBLE_QUOTE = '\"'; // Bunch of unicode info at: // http://www.unicode.org/faq/utf_bom.html // ef bb bf (Microsoft "lead bytes") - designates UTF-8 static const unsigned char TIXML_UTF_LEAD_0 = 0xefU; static const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; static const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; #define DELETE_NODE( node ) { \ if ( node ) { \ MemPool* pool = node->_memPool; \ node->~XMLNode(); \ pool->Free( node ); \ } \ } #define DELETE_ATTRIBUTE( attrib ) { \ if ( attrib ) { \ MemPool* pool = attrib->_memPool; \ attrib->~XMLAttribute(); \ pool->Free( attrib ); \ } \ } namespace tinyxml2 { struct Entity { const char* pattern; int length; char value; }; static const int NUM_ENTITIES = 5; static const Entity entities[NUM_ENTITIES] = { { "quot", 4, DOUBLE_QUOTE }, { "amp", 3, '&' }, { "apos", 4, SINGLE_QUOTE }, { "lt", 2, '<' }, { "gt", 2, '>' } }; StrPair::~StrPair() { Reset(); } void StrPair::Reset() { if ( _flags & NEEDS_DELETE ) { delete [] _start; } _flags = 0; _start = 0; _end = 0; } void StrPair::SetStr( const char* str, int flags ) { Reset(); size_t len = strlen( str ); _start = new char[ len+1 ]; memcpy( _start, str, len+1 ); _end = _start + len; _flags = flags | NEEDS_DELETE; } char* StrPair::ParseText( char* p, const char* endTag, int strFlags ) { TIXMLASSERT( endTag && *endTag ); char* start = p; // fixme: hides a member char endChar = *endTag; size_t length = strlen( endTag ); // Inner loop of text parsing. while ( *p ) { if ( *p == endChar && strncmp( p, endTag, length ) == 0 ) { Set( start, p, strFlags ); return p + length; } ++p; } return 0; } char* StrPair::ParseName( char* p ) { char* start = p; if ( !start || !(*start) ) { return 0; } while( *p && ( p == start ? XMLUtil::IsNameStartChar( *p ) : XMLUtil::IsNameChar( *p ) )) { ++p; } if ( p > start ) { Set( start, p, 0 ); return p; } return 0; } void StrPair::CollapseWhitespace() { // Trim leading space. _start = XMLUtil::SkipWhiteSpace( _start ); if ( _start && *_start ) { char* p = _start; // the read pointer char* q = _start; // the write pointer while( *p ) { if ( XMLUtil::IsWhiteSpace( *p )) { p = XMLUtil::SkipWhiteSpace( p ); if ( *p == 0 ) { break; // don't write to q; this trims the trailing space. } *q = ' '; ++q; } *q = *p; ++q; ++p; } *q = 0; } } const char* StrPair::GetStr() { if ( _flags & NEEDS_FLUSH ) { *_end = 0; _flags ^= NEEDS_FLUSH; if ( _flags ) { char* p = _start; // the read pointer char* q = _start; // the write pointer while( p < _end ) { if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == CR ) { // CR-LF pair becomes LF // CR alone becomes LF // LF-CR becomes LF if ( *(p+1) == LF ) { p += 2; } else { ++p; } *q++ = LF; } else if ( (_flags & NEEDS_NEWLINE_NORMALIZATION) && *p == LF ) { if ( *(p+1) == CR ) { p += 2; } else { ++p; } *q++ = LF; } else if ( (_flags & NEEDS_ENTITY_PROCESSING) && *p == '&' ) { // Entities handled by tinyXML2: // - special entities in the entity table [in/out] // - numeric character reference [in] // 中 or 中 if ( *(p+1) == '#' ) { char buf[10] = { 0 }; int len; p = const_cast( XMLUtil::GetCharacterRef( p, buf, &len ) ); for( int i=0; i(p); // Check for BOM: if ( *(pu+0) == TIXML_UTF_LEAD_0 && *(pu+1) == TIXML_UTF_LEAD_1 && *(pu+2) == TIXML_UTF_LEAD_2 ) { *bom = true; p += 3; } return p; } void XMLUtil::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ) { const unsigned long BYTE_MASK = 0xBF; const unsigned long BYTE_MARK = 0x80; const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; if (input < 0x80) { *length = 1; } else if ( input < 0x800 ) { *length = 2; } else if ( input < 0x10000 ) { *length = 3; } else if ( input < 0x200000 ) { *length = 4; } else { *length = 0; // This code won't covert this correctly anyway. return; } output += *length; // Scary scary fall throughs. switch (*length) { case 4: --output; *output = (char)((input | BYTE_MARK) & BYTE_MASK); input >>= 6; case 3: --output; *output = (char)((input | BYTE_MARK) & BYTE_MASK); input >>= 6; case 2: --output; *output = (char)((input | BYTE_MARK) & BYTE_MASK); input >>= 6; case 1: --output; *output = (char)(input | FIRST_BYTE_MARK[*length]); default: break; } } const char* XMLUtil::GetCharacterRef( const char* p, char* value, int* length ) { // Presume an entity, and pull it out. *length = 0; if ( *(p+1) == '#' && *(p+2) ) { unsigned long ucs = 0; ptrdiff_t delta = 0; unsigned mult = 1; if ( *(p+2) == 'x' ) { // Hexadecimal. if ( !*(p+3) ) { return 0; } const char* q = p+3; q = strchr( q, ';' ); if ( !q || !*q ) { return 0; } delta = q-p; --q; while ( *q != 'x' ) { if ( *q >= '0' && *q <= '9' ) { ucs += mult * (*q - '0'); } else if ( *q >= 'a' && *q <= 'f' ) { ucs += mult * (*q - 'a' + 10); } else if ( *q >= 'A' && *q <= 'F' ) { ucs += mult * (*q - 'A' + 10 ); } else { return 0; } mult *= 16; --q; } } else { // Decimal. if ( !*(p+2) ) { return 0; } const char* q = p+2; q = strchr( q, ';' ); if ( !q || !*q ) { return 0; } delta = q-p; --q; while ( *q != '#' ) { if ( *q >= '0' && *q <= '9' ) { ucs += mult * (*q - '0'); } else { return 0; } mult *= 10; --q; } } // convert the UCS to UTF-8 ConvertUTF32ToUTF8( ucs, value, length ); return p + delta + 1; } return p+1; } void XMLUtil::ToStr( int v, char* buffer, int bufferSize ) { TIXML_SNPRINTF( buffer, bufferSize, "%d", v ); } void XMLUtil::ToStr( unsigned v, char* buffer, int bufferSize ) { TIXML_SNPRINTF( buffer, bufferSize, "%u", v ); } void XMLUtil::ToStr( bool v, char* buffer, int bufferSize ) { TIXML_SNPRINTF( buffer, bufferSize, "%d", v ? 1 : 0 ); } void XMLUtil::ToStr( float v, char* buffer, int bufferSize ) { TIXML_SNPRINTF( buffer, bufferSize, "%g", v ); } void XMLUtil::ToStr( double v, char* buffer, int bufferSize ) { TIXML_SNPRINTF( buffer, bufferSize, "%g", v ); } bool XMLUtil::ToInt( const char* str, int* value ) { if ( TIXML_SSCANF( str, "%d", value ) == 1 ) { return true; } return false; } bool XMLUtil::ToUnsigned( const char* str, unsigned *value ) { if ( TIXML_SSCANF( str, "%u", value ) == 1 ) { return true; } return false; } bool XMLUtil::ToBool( const char* str, bool* value ) { int ival = 0; if ( ToInt( str, &ival )) { *value = (ival==0) ? false : true; return true; } if ( StringEqual( str, "true" ) ) { *value = true; return true; } else if ( StringEqual( str, "false" ) ) { *value = false; return true; } return false; } bool XMLUtil::ToFloat( const char* str, float* value ) { if ( TIXML_SSCANF( str, "%f", value ) == 1 ) { return true; } return false; } bool XMLUtil::ToDouble( const char* str, double* value ) { if ( TIXML_SSCANF( str, "%lf", value ) == 1 ) { return true; } return false; } char* XMLDocument::Identify( char* p, XMLNode** node ) { XMLNode* returnNode = 0; char* start = p; p = XMLUtil::SkipWhiteSpace( p ); if( !p || !*p ) { return p; } // What is this thing? // - Elements start with a letter or underscore, but xml is reserved. // - Comments: // // With a special case: // // // // // Where the closing element (/foo) *must* be the next thing after the opening // element, and the names must match. BUT the tricky bit is that the closing // element will be read by the child. // // 'endTag' is the end tag for this node, it is returned by a call to a child. // 'parentEnd' is the end tag for the parent, which is filled in and returned. while( p && *p ) { XMLNode* node = 0; p = _document->Identify( p, &node ); if ( p == 0 || node == 0 ) { break; } StrPair endTag; p = node->ParseDeep( p, &endTag ); if ( !p ) { DELETE_NODE( node ); node = 0; if ( !_document->Error() ) { _document->SetError( XML_ERROR_PARSING, 0, 0 ); } break; } // We read the end tag. Return it to the parent. if ( node->ToElement() && node->ToElement()->ClosingType() == XMLElement::CLOSING ) { if ( parentEnd ) { *parentEnd = static_cast(node)->_value; } node->_memPool->SetTracked(); // created and then immediately deleted. DELETE_NODE( node ); return p; } // Handle an end tag returned to this level. // And handle a bunch of annoying errors. XMLElement* ele = node->ToElement(); if ( ele ) { if ( endTag.Empty() && ele->ClosingType() == XMLElement::OPEN ) { _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, node->Value(), 0 ); p = 0; } else if ( !endTag.Empty() && ele->ClosingType() != XMLElement::OPEN ) { _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, node->Value(), 0 ); p = 0; } else if ( !endTag.Empty() ) { if ( !XMLUtil::StringEqual( endTag.GetStr(), node->Value() )) { _document->SetError( XML_ERROR_MISMATCHED_ELEMENT, node->Value(), 0 ); p = 0; } } } if ( p == 0 ) { DELETE_NODE( node ); node = 0; } if ( node ) { this->InsertEndChild( node ); } } return 0; } // --------- XMLText ---------- // char* XMLText::ParseDeep( char* p, StrPair* ) { const char* start = p; if ( this->CData() ) { p = _value.ParseText( p, "]]>", StrPair::NEEDS_NEWLINE_NORMALIZATION ); if ( !p ) { _document->SetError( XML_ERROR_PARSING_CDATA, start, 0 ); } return p; } else { int flags = _document->ProcessEntities() ? StrPair::TEXT_ELEMENT : StrPair::TEXT_ELEMENT_LEAVE_ENTITIES; if ( _document->WhitespaceMode() == COLLAPSE_WHITESPACE ) { flags |= StrPair::COLLAPSE_WHITESPACE; } p = _value.ParseText( p, "<", flags ); if ( !p ) { _document->SetError( XML_ERROR_PARSING_TEXT, start, 0 ); } if ( p && *p ) { return p-1; } } return 0; } XMLNode* XMLText::ShallowClone( XMLDocument* doc ) const { if ( !doc ) { doc = _document; } XMLText* text = doc->NewText( Value() ); // fixme: this will always allocate memory. Intern? text->SetCData( this->CData() ); return text; } bool XMLText::ShallowEqual( const XMLNode* compare ) const { return ( compare->ToText() && XMLUtil::StringEqual( compare->ToText()->Value(), Value() )); } bool XMLText::Accept( XMLVisitor* visitor ) const { return visitor->Visit( *this ); } // --------- XMLComment ---------- // XMLComment::XMLComment( XMLDocument* doc ) : XMLNode( doc ) { } XMLComment::~XMLComment() { } char* XMLComment::ParseDeep( char* p, StrPair* ) { // Comment parses as text. const char* start = p; p = _value.ParseText( p, "-->", StrPair::COMMENT ); if ( p == 0 ) { _document->SetError( XML_ERROR_PARSING_COMMENT, start, 0 ); } return p; } XMLNode* XMLComment::ShallowClone( XMLDocument* doc ) const { if ( !doc ) { doc = _document; } XMLComment* comment = doc->NewComment( Value() ); // fixme: this will always allocate memory. Intern? return comment; } bool XMLComment::ShallowEqual( const XMLNode* compare ) const { return ( compare->ToComment() && XMLUtil::StringEqual( compare->ToComment()->Value(), Value() )); } bool XMLComment::Accept( XMLVisitor* visitor ) const { return visitor->Visit( *this ); } // --------- XMLDeclaration ---------- // XMLDeclaration::XMLDeclaration( XMLDocument* doc ) : XMLNode( doc ) { } XMLDeclaration::~XMLDeclaration() { //printf( "~XMLDeclaration\n" ); } char* XMLDeclaration::ParseDeep( char* p, StrPair* ) { // Declaration parses as text. const char* start = p; p = _value.ParseText( p, "?>", StrPair::NEEDS_NEWLINE_NORMALIZATION ); if ( p == 0 ) { _document->SetError( XML_ERROR_PARSING_DECLARATION, start, 0 ); } return p; } XMLNode* XMLDeclaration::ShallowClone( XMLDocument* doc ) const { if ( !doc ) { doc = _document; } XMLDeclaration* dec = doc->NewDeclaration( Value() ); // fixme: this will always allocate memory. Intern? return dec; } bool XMLDeclaration::ShallowEqual( const XMLNode* compare ) const { return ( compare->ToDeclaration() && XMLUtil::StringEqual( compare->ToDeclaration()->Value(), Value() )); } bool XMLDeclaration::Accept( XMLVisitor* visitor ) const { return visitor->Visit( *this ); } // --------- XMLUnknown ---------- // XMLUnknown::XMLUnknown( XMLDocument* doc ) : XMLNode( doc ) { } XMLUnknown::~XMLUnknown() { } char* XMLUnknown::ParseDeep( char* p, StrPair* ) { // Unknown parses as text. const char* start = p; p = _value.ParseText( p, ">", StrPair::NEEDS_NEWLINE_NORMALIZATION ); if ( !p ) { _document->SetError( XML_ERROR_PARSING_UNKNOWN, start, 0 ); } return p; } XMLNode* XMLUnknown::ShallowClone( XMLDocument* doc ) const { if ( !doc ) { doc = _document; } XMLUnknown* text = doc->NewUnknown( Value() ); // fixme: this will always allocate memory. Intern? return text; } bool XMLUnknown::ShallowEqual( const XMLNode* compare ) const { return ( compare->ToUnknown() && XMLUtil::StringEqual( compare->ToUnknown()->Value(), Value() )); } bool XMLUnknown::Accept( XMLVisitor* visitor ) const { return visitor->Visit( *this ); } // --------- XMLAttribute ---------- // char* XMLAttribute::ParseDeep( char* p, bool processEntities ) { // Parse using the name rules: bug fix, was using ParseText before p = _name.ParseName( p ); if ( !p || !*p ) { return 0; } // Skip white space before = p = XMLUtil::SkipWhiteSpace( p ); if ( !p || *p != '=' ) { return 0; } ++p; // move up to opening quote p = XMLUtil::SkipWhiteSpace( p ); if ( *p != '\"' && *p != '\'' ) { return 0; } char endTag[2] = { *p, 0 }; ++p; // move past opening quote p = _value.ParseText( p, endTag, processEntities ? StrPair::ATTRIBUTE_VALUE : StrPair::ATTRIBUTE_VALUE_LEAVE_ENTITIES ); return p; } void XMLAttribute::SetName( const char* n ) { _name.SetStr( n ); } XMLError XMLAttribute::QueryIntValue( int* value ) const { if ( XMLUtil::ToInt( Value(), value )) { return XML_NO_ERROR; } return XML_WRONG_ATTRIBUTE_TYPE; } XMLError XMLAttribute::QueryUnsignedValue( unsigned int* value ) const { if ( XMLUtil::ToUnsigned( Value(), value )) { return XML_NO_ERROR; } return XML_WRONG_ATTRIBUTE_TYPE; } XMLError XMLAttribute::QueryBoolValue( bool* value ) const { if ( XMLUtil::ToBool( Value(), value )) { return XML_NO_ERROR; } return XML_WRONG_ATTRIBUTE_TYPE; } XMLError XMLAttribute::QueryFloatValue( float* value ) const { if ( XMLUtil::ToFloat( Value(), value )) { return XML_NO_ERROR; } return XML_WRONG_ATTRIBUTE_TYPE; } XMLError XMLAttribute::QueryDoubleValue( double* value ) const { if ( XMLUtil::ToDouble( Value(), value )) { return XML_NO_ERROR; } return XML_WRONG_ATTRIBUTE_TYPE; } void XMLAttribute::SetAttribute( const char* v ) { _value.SetStr( v ); } void XMLAttribute::SetAttribute( int v ) { char buf[BUF_SIZE]; XMLUtil::ToStr( v, buf, BUF_SIZE ); _value.SetStr( buf ); } void XMLAttribute::SetAttribute( unsigned v ) { char buf[BUF_SIZE]; XMLUtil::ToStr( v, buf, BUF_SIZE ); _value.SetStr( buf ); } void XMLAttribute::SetAttribute( bool v ) { char buf[BUF_SIZE]; XMLUtil::ToStr( v, buf, BUF_SIZE ); _value.SetStr( buf ); } void XMLAttribute::SetAttribute( double v ) { char buf[BUF_SIZE]; XMLUtil::ToStr( v, buf, BUF_SIZE ); _value.SetStr( buf ); } void XMLAttribute::SetAttribute( float v ) { char buf[BUF_SIZE]; XMLUtil::ToStr( v, buf, BUF_SIZE ); _value.SetStr( buf ); } // --------- XMLElement ---------- // XMLElement::XMLElement( XMLDocument* doc ) : XMLNode( doc ), _closingType( 0 ), _rootAttribute( 0 ) { } XMLElement::~XMLElement() { while( _rootAttribute ) { XMLAttribute* next = _rootAttribute->_next; DELETE_ATTRIBUTE( _rootAttribute ); _rootAttribute = next; } } XMLAttribute* XMLElement::FindAttribute( const char* name ) { XMLAttribute* a = 0; for( a=_rootAttribute; a; a = a->_next ) { if ( XMLUtil::StringEqual( a->Name(), name ) ) { return a; } } return 0; } const XMLAttribute* XMLElement::FindAttribute( const char* name ) const { XMLAttribute* a = 0; for( a=_rootAttribute; a; a = a->_next ) { if ( XMLUtil::StringEqual( a->Name(), name ) ) { return a; } } return 0; } const char* XMLElement::Attribute( const char* name, const char* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) { return 0; } if ( !value || XMLUtil::StringEqual( a->Value(), value )) { return a->Value(); } return 0; } const char* XMLElement::GetText() const { if ( FirstChild() && FirstChild()->ToText() ) { return FirstChild()->ToText()->Value(); } return 0; } XMLError XMLElement::QueryIntText( int* ival ) const { if ( FirstChild() && FirstChild()->ToText() ) { const char* t = FirstChild()->ToText()->Value(); if ( XMLUtil::ToInt( t, ival ) ) { return XML_SUCCESS; } return XML_CAN_NOT_CONVERT_TEXT; } return XML_NO_TEXT_NODE; } XMLError XMLElement::QueryUnsignedText( unsigned* uval ) const { if ( FirstChild() && FirstChild()->ToText() ) { const char* t = FirstChild()->ToText()->Value(); if ( XMLUtil::ToUnsigned( t, uval ) ) { return XML_SUCCESS; } return XML_CAN_NOT_CONVERT_TEXT; } return XML_NO_TEXT_NODE; } XMLError XMLElement::QueryBoolText( bool* bval ) const { if ( FirstChild() && FirstChild()->ToText() ) { const char* t = FirstChild()->ToText()->Value(); if ( XMLUtil::ToBool( t, bval ) ) { return XML_SUCCESS; } return XML_CAN_NOT_CONVERT_TEXT; } return XML_NO_TEXT_NODE; } XMLError XMLElement::QueryDoubleText( double* dval ) const { if ( FirstChild() && FirstChild()->ToText() ) { const char* t = FirstChild()->ToText()->Value(); if ( XMLUtil::ToDouble( t, dval ) ) { return XML_SUCCESS; } return XML_CAN_NOT_CONVERT_TEXT; } return XML_NO_TEXT_NODE; } XMLError XMLElement::QueryFloatText( float* fval ) const { if ( FirstChild() && FirstChild()->ToText() ) { const char* t = FirstChild()->ToText()->Value(); if ( XMLUtil::ToFloat( t, fval ) ) { return XML_SUCCESS; } return XML_CAN_NOT_CONVERT_TEXT; } return XML_NO_TEXT_NODE; } XMLAttribute* XMLElement::FindOrCreateAttribute( const char* name ) { XMLAttribute* last = 0; XMLAttribute* attrib = 0; for( attrib = _rootAttribute; attrib; last = attrib, attrib = attrib->_next ) { if ( XMLUtil::StringEqual( attrib->Name(), name ) ) { break; } } if ( !attrib ) { attrib = new (_document->_attributePool.Alloc() ) XMLAttribute(); attrib->_memPool = &_document->_attributePool; if ( last ) { last->_next = attrib; } else { _rootAttribute = attrib; } attrib->SetName( name ); attrib->_memPool->SetTracked(); // always created and linked. } return attrib; } void XMLElement::DeleteAttribute( const char* name ) { XMLAttribute* prev = 0; for( XMLAttribute* a=_rootAttribute; a; a=a->_next ) { if ( XMLUtil::StringEqual( name, a->Name() ) ) { if ( prev ) { prev->_next = a->_next; } else { _rootAttribute = a->_next; } DELETE_ATTRIBUTE( a ); break; } prev = a; } } char* XMLElement::ParseAttributes( char* p ) { const char* start = p; XMLAttribute* prevAttribute = 0; // Read the attributes. while( p ) { p = XMLUtil::SkipWhiteSpace( p ); if ( !p || !(*p) ) { _document->SetError( XML_ERROR_PARSING_ELEMENT, start, Name() ); return 0; } // attribute. if (XMLUtil::IsNameStartChar( *p ) ) { XMLAttribute* attrib = new (_document->_attributePool.Alloc() ) XMLAttribute(); attrib->_memPool = &_document->_attributePool; attrib->_memPool->SetTracked(); p = attrib->ParseDeep( p, _document->ProcessEntities() ); if ( !p || Attribute( attrib->Name() ) ) { DELETE_ATTRIBUTE( attrib ); _document->SetError( XML_ERROR_PARSING_ATTRIBUTE, start, p ); return 0; } // There is a minor bug here: if the attribute in the source xml // document is duplicated, it will not be detected and the // attribute will be doubly added. However, tracking the 'prevAttribute' // avoids re-scanning the attribute list. Preferring performance for // now, may reconsider in the future. if ( prevAttribute ) { prevAttribute->_next = attrib; } else { _rootAttribute = attrib; } prevAttribute = attrib; } // end of the tag else if ( *p == '/' && *(p+1) == '>' ) { _closingType = CLOSED; return p+2; // done; sealed element. } // end of the tag else if ( *p == '>' ) { ++p; break; } else { _document->SetError( XML_ERROR_PARSING_ELEMENT, start, p ); return 0; } } return p; } // // // foobar // char* XMLElement::ParseDeep( char* p, StrPair* strPair ) { // Read the element name. p = XMLUtil::SkipWhiteSpace( p ); if ( !p ) { return 0; } // The closing element is the form. It is // parsed just like a regular element then deleted from // the DOM. if ( *p == '/' ) { _closingType = CLOSING; ++p; } p = _value.ParseName( p ); if ( _value.Empty() ) { return 0; } p = ParseAttributes( p ); if ( !p || !*p || _closingType ) { return p; } p = XMLNode::ParseDeep( p, strPair ); return p; } XMLNode* XMLElement::ShallowClone( XMLDocument* doc ) const { if ( !doc ) { doc = _document; } XMLElement* element = doc->NewElement( Value() ); // fixme: this will always allocate memory. Intern? for( const XMLAttribute* a=FirstAttribute(); a; a=a->Next() ) { element->SetAttribute( a->Name(), a->Value() ); // fixme: this will always allocate memory. Intern? } return element; } bool XMLElement::ShallowEqual( const XMLNode* compare ) const { const XMLElement* other = compare->ToElement(); if ( other && XMLUtil::StringEqual( other->Value(), Value() )) { const XMLAttribute* a=FirstAttribute(); const XMLAttribute* b=other->FirstAttribute(); while ( a && b ) { if ( !XMLUtil::StringEqual( a->Value(), b->Value() ) ) { return false; } a = a->Next(); b = b->Next(); } if ( a || b ) { // different count return false; } return true; } return false; } bool XMLElement::Accept( XMLVisitor* visitor ) const { if ( visitor->VisitEnter( *this, _rootAttribute ) ) { for ( const XMLNode* node=FirstChild(); node; node=node->NextSibling() ) { if ( !node->Accept( visitor ) ) { break; } } } return visitor->VisitExit( *this ); } // --------- XMLDocument ----------- // XMLDocument::XMLDocument( bool processEntities, Whitespace whitespace ) : XMLNode( 0 ), _writeBOM( false ), _processEntities( processEntities ), _errorID( XML_NO_ERROR ), _whitespace( whitespace ), _errorStr1( 0 ), _errorStr2( 0 ), _charBuffer( 0 ) { _document = this; // avoid warning about 'this' in initializer list } XMLDocument::~XMLDocument() { DeleteChildren(); delete [] _charBuffer; #if 0 _textPool.Trace( "text" ); _elementPool.Trace( "element" ); _commentPool.Trace( "comment" ); _attributePool.Trace( "attribute" ); #endif #ifdef DEBUG if ( Error() == false ) { TIXMLASSERT( _elementPool.CurrentAllocs() == _elementPool.Untracked() ); TIXMLASSERT( _attributePool.CurrentAllocs() == _attributePool.Untracked() ); TIXMLASSERT( _textPool.CurrentAllocs() == _textPool.Untracked() ); TIXMLASSERT( _commentPool.CurrentAllocs() == _commentPool.Untracked() ); } #endif } void XMLDocument::Clear() { DeleteChildren(); _errorID = XML_NO_ERROR; _errorStr1 = 0; _errorStr2 = 0; delete [] _charBuffer; _charBuffer = 0; } XMLElement* XMLDocument::NewElement( const char* name ) { XMLElement* ele = new (_elementPool.Alloc()) XMLElement( this ); ele->_memPool = &_elementPool; ele->SetName( name ); return ele; } XMLComment* XMLDocument::NewComment( const char* str ) { XMLComment* comment = new (_commentPool.Alloc()) XMLComment( this ); comment->_memPool = &_commentPool; comment->SetValue( str ); return comment; } XMLText* XMLDocument::NewText( const char* str ) { XMLText* text = new (_textPool.Alloc()) XMLText( this ); text->_memPool = &_textPool; text->SetValue( str ); return text; } XMLDeclaration* XMLDocument::NewDeclaration( const char* str ) { XMLDeclaration* dec = new (_commentPool.Alloc()) XMLDeclaration( this ); dec->_memPool = &_commentPool; dec->SetValue( str ? str : "xml version=\"1.0\" encoding=\"UTF-8\"" ); return dec; } XMLUnknown* XMLDocument::NewUnknown( const char* str ) { XMLUnknown* unk = new (_commentPool.Alloc()) XMLUnknown( this ); unk->_memPool = &_commentPool; unk->SetValue( str ); return unk; } XMLError XMLDocument::LoadFile( const char* filename ) { Clear(); FILE* fp = 0; #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) errno_t err = fopen_s(&fp, filename, "rb" ); if ( !fp || err) { #else fp = fopen( filename, "rb" ); if ( !fp) { #endif SetError( XML_ERROR_FILE_NOT_FOUND, filename, 0 ); return _errorID; } LoadFile( fp ); fclose( fp ); return _errorID; } XMLError XMLDocument::LoadFile( FILE* fp ) { Clear(); fseek( fp, 0, SEEK_END ); size_t size = ftell( fp ); fseek( fp, 0, SEEK_SET ); if ( size == 0 ) { return _errorID; } _charBuffer = new char[size+1]; size_t read = fread( _charBuffer, 1, size, fp ); if ( read != size ) { SetError( XML_ERROR_FILE_READ_ERROR, 0, 0 ); return _errorID; } _charBuffer[size] = 0; const char* p = _charBuffer; p = XMLUtil::SkipWhiteSpace( p ); p = XMLUtil::ReadBOM( p, &_writeBOM ); if ( !p || !*p ) { SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 ); return _errorID; } ParseDeep( _charBuffer + (p-_charBuffer), 0 ); return _errorID; } XMLError XMLDocument::SaveFile( const char* filename, bool compact ) { FILE* fp = 0; #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) errno_t err = fopen_s(&fp, filename, "w" ); if ( !fp || err) { #else fp = fopen( filename, "w" ); if ( !fp) { #endif SetError( XML_ERROR_FILE_COULD_NOT_BE_OPENED, filename, 0 ); return _errorID; } SaveFile(fp, compact); fclose( fp ); return _errorID; } XMLError XMLDocument::SaveFile( FILE* fp, bool compact ) { XMLPrinter stream( fp, compact ); Print( &stream ); return _errorID; } XMLError XMLDocument::Parse( const char* p, size_t len ) { Clear(); if ( !p || !*p ) { SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 ); return _errorID; } if ( len == (size_t)(-1) ) { len = strlen( p ); } _charBuffer = new char[ len+1 ]; memcpy( _charBuffer, p, len ); _charBuffer[len] = 0; p = XMLUtil::SkipWhiteSpace( p ); p = XMLUtil::ReadBOM( p, &_writeBOM ); if ( !p || !*p ) { SetError( XML_ERROR_EMPTY_DOCUMENT, 0, 0 ); return _errorID; } ParseDeep( _charBuffer, 0 ); return _errorID; } void XMLDocument::Print( XMLPrinter* streamer ) { XMLPrinter stdStreamer( stdout ); if ( !streamer ) { streamer = &stdStreamer; } Accept( streamer ); } void XMLDocument::SetError( XMLError error, const char* str1, const char* str2 ) { _errorID = error; _errorStr1 = str1; _errorStr2 = str2; } void XMLDocument::PrintError() const { if ( _errorID ) { static const int LEN = 20; char buf1[LEN] = { 0 }; char buf2[LEN] = { 0 }; if ( _errorStr1 ) { TIXML_SNPRINTF( buf1, LEN, "%s", _errorStr1 ); } if ( _errorStr2 ) { TIXML_SNPRINTF( buf2, LEN, "%s", _errorStr2 ); } printf( "XMLDocument error id=%d str1=%s str2=%s\n", _errorID, buf1, buf2 ); } } XMLPrinter::XMLPrinter( FILE* file, bool compact ) : _elementJustOpened( false ), _firstElement( true ), _fp( file ), _depth( 0 ), _textDepth( -1 ), _processEntities( true ), _compactMode( compact ) { for( int i=0; i'] = true; // not required, but consistency is nice _buffer.Push( 0 ); } void XMLPrinter::Print( const char* format, ... ) { va_list va; va_start( va, format ); if ( _fp ) { vfprintf( _fp, format, va ); } else { // This seems brutally complex. Haven't figured out a better // way on windows. #ifdef _MSC_VER int len = -1; int expand = 1000; while ( len < 0 ) { len = vsnprintf_s( _accumulator.Mem(), _accumulator.Capacity(), _TRUNCATE, format, va ); if ( len < 0 ) { expand *= 3/2; _accumulator.PushArr( expand ); } } char* p = _buffer.PushArr( len ) - 1; memcpy( p, _accumulator.Mem(), len+1 ); #else int len = vsnprintf( 0, 0, format, va ); // Close out and re-start the va-args va_end( va ); va_start( va, format ); char* p = _buffer.PushArr( len ) - 1; vsnprintf( p, len+1, format, va ); #endif } va_end( va ); } void XMLPrinter::PrintSpace( int depth ) { for( int i=0; i 0 && *q < ENTITY_RANGE ) { // Check for entities. If one is found, flush // the stream up until the entity, write the // entity, and keep looking. if ( flag[(unsigned)(*q)] ) { while ( p < q ) { Print( "%c", *p ); ++p; } for( int i=0; i 0) ) { Print( "%s", p ); } } void XMLPrinter::PushHeader( bool writeBOM, bool writeDec ) { static const unsigned char bom[] = { TIXML_UTF_LEAD_0, TIXML_UTF_LEAD_1, TIXML_UTF_LEAD_2, 0 }; if ( writeBOM ) { Print( "%s", bom ); } if ( writeDec ) { PushDeclaration( "xml version=\"1.0\"" ); } } void XMLPrinter::OpenElement( const char* name ) { if ( _elementJustOpened ) { SealElement(); } _stack.Push( name ); if ( _textDepth < 0 && !_firstElement && !_compactMode ) { Print( "\n" ); PrintSpace( _depth ); } Print( "<%s", name ); _elementJustOpened = true; _firstElement = false; ++_depth; } void XMLPrinter::PushAttribute( const char* name, const char* value ) { TIXMLASSERT( _elementJustOpened ); Print( " %s=\"", name ); PrintString( value, false ); Print( "\"" ); } void XMLPrinter::PushAttribute( const char* name, int v ) { char buf[BUF_SIZE]; XMLUtil::ToStr( v, buf, BUF_SIZE ); PushAttribute( name, buf ); } void XMLPrinter::PushAttribute( const char* name, unsigned v ) { char buf[BUF_SIZE]; XMLUtil::ToStr( v, buf, BUF_SIZE ); PushAttribute( name, buf ); } void XMLPrinter::PushAttribute( const char* name, bool v ) { char buf[BUF_SIZE]; XMLUtil::ToStr( v, buf, BUF_SIZE ); PushAttribute( name, buf ); } void XMLPrinter::PushAttribute( const char* name, double v ) { char buf[BUF_SIZE]; XMLUtil::ToStr( v, buf, BUF_SIZE ); PushAttribute( name, buf ); } void XMLPrinter::CloseElement() { --_depth; const char* name = _stack.Pop(); if ( _elementJustOpened ) { Print( "/>" ); } else { if ( _textDepth < 0 && !_compactMode) { Print( "\n" ); PrintSpace( _depth ); } Print( "", name ); } if ( _textDepth == _depth ) { _textDepth = -1; } if ( _depth == 0 && !_compactMode) { Print( "\n" ); } _elementJustOpened = false; } void XMLPrinter::SealElement() { _elementJustOpened = false; Print( ">" ); } void XMLPrinter::PushText( const char* text, bool cdata ) { _textDepth = _depth-1; if ( _elementJustOpened ) { SealElement(); } if ( cdata ) { Print( "" ); } else { PrintString( text, true ); } } void XMLPrinter::PushText( int value ) { char buf[BUF_SIZE]; XMLUtil::ToStr( value, buf, BUF_SIZE ); PushText( buf, false ); } void XMLPrinter::PushText( unsigned value ) { char buf[BUF_SIZE]; XMLUtil::ToStr( value, buf, BUF_SIZE ); PushText( buf, false ); } void XMLPrinter::PushText( bool value ) { char buf[BUF_SIZE]; XMLUtil::ToStr( value, buf, BUF_SIZE ); PushText( buf, false ); } void XMLPrinter::PushText( float value ) { char buf[BUF_SIZE]; XMLUtil::ToStr( value, buf, BUF_SIZE ); PushText( buf, false ); } void XMLPrinter::PushText( double value ) { char buf[BUF_SIZE]; XMLUtil::ToStr( value, buf, BUF_SIZE ); PushText( buf, false ); } void XMLPrinter::PushComment( const char* comment ) { if ( _elementJustOpened ) { SealElement(); } if ( _textDepth < 0 && !_firstElement && !_compactMode) { Print( "\n" ); PrintSpace( _depth ); } _firstElement = false; Print( "", comment ); } void XMLPrinter::PushDeclaration( const char* value ) { if ( _elementJustOpened ) { SealElement(); } if ( _textDepth < 0 && !_firstElement && !_compactMode) { Print( "\n" ); PrintSpace( _depth ); } _firstElement = false; Print( "", value ); } void XMLPrinter::PushUnknown( const char* value ) { if ( _elementJustOpened ) { SealElement(); } if ( _textDepth < 0 && !_firstElement && !_compactMode) { Print( "\n" ); PrintSpace( _depth ); } _firstElement = false; Print( "", value ); } bool XMLPrinter::VisitEnter( const XMLDocument& doc ) { _processEntities = doc.ProcessEntities(); if ( doc.HasBOM() ) { PushHeader( true, false ); } return true; } bool XMLPrinter::VisitEnter( const XMLElement& element, const XMLAttribute* attribute ) { OpenElement( element.Name() ); while ( attribute ) { PushAttribute( attribute->Name(), attribute->Value() ); attribute = attribute->Next(); } return true; } bool XMLPrinter::VisitExit( const XMLElement& ) { CloseElement(); return true; } bool XMLPrinter::Visit( const XMLText& text ) { PushText( text.Value(), text.CData() ); return true; } bool XMLPrinter::Visit( const XMLComment& comment ) { PushComment( comment.Value() ); return true; } bool XMLPrinter::Visit( const XMLDeclaration& declaration ) { PushDeclaration( declaration.Value() ); return true; } bool XMLPrinter::Visit( const XMLUnknown& unknown ) { PushUnknown( unknown.Value() ); return true; } } // namespace tinyxml2 cppcheck-1.61/externals/tinyxml/tinyxml2.h000066400000000000000000001624521217722632100207060ustar00rootroot00000000000000/* Original code by Lee Thomason (www.grinninglizard.com) 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. */ #ifndef TINYXML2_INCLUDED #define TINYXML2_INCLUDED #if defined(ANDROID_NDK) || defined(__BORLANDC__) # include # include # include # include # include # include #else # include # include # include # include # include # include #endif /* TODO: intern strings instead of allocation. */ /* gcc: g++ -Wall -DDEBUG tinyxml2.cpp xmltest.cpp -o gccxmltest.exe Formatting, Artistic Style: AStyle.exe --style=1tbs --indent-switches --break-closing-brackets --indent-preprocessor tinyxml2.cpp tinyxml2.h */ #if defined( _DEBUG ) || defined( DEBUG ) || defined (__DEBUG__) # ifndef DEBUG # define DEBUG # endif #endif #if defined(DEBUG) # if defined(_MSC_VER) # define TIXMLASSERT( x ) if ( !(x)) { __debugbreak(); } //if ( !(x)) WinDebugBreak() # elif defined (ANDROID_NDK) # include # define TIXMLASSERT( x ) if ( !(x)) { __android_log_assert( "assert", "grinliz", "ASSERT in '%s' at %d.", __FILE__, __LINE__ ); } # else # include # define TIXMLASSERT assert # endif # else # define TIXMLASSERT( x ) {} #endif #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) // Microsoft visual studio, version 2005 and higher. /*int _snprintf_s( char *buffer, size_t sizeOfBuffer, size_t count, const char *format [, argument] ... );*/ inline int TIXML_SNPRINTF( char* buffer, size_t size, const char* format, ... ) { va_list va; va_start( va, format ); int result = vsnprintf_s( buffer, size, _TRUNCATE, format, va ); va_end( va ); return result; } #define TIXML_SSCANF sscanf_s #else // GCC version 3 and higher //#warning( "Using sn* functions." ) #define TIXML_SNPRINTF snprintf #define TIXML_SSCANF sscanf #endif static const int TIXML2_MAJOR_VERSION = 1; static const int TIXML2_MINOR_VERSION = 0; static const int TIXML2_PATCH_VERSION = 11; namespace tinyxml2 { class XMLDocument; class XMLElement; class XMLAttribute; class XMLComment; class XMLNode; class XMLText; class XMLDeclaration; class XMLUnknown; class XMLPrinter; /* A class that wraps strings. Normally stores the start and end pointers into the XML file itself, and will apply normalization and entity translation if actually read. Can also store (and memory manage) a traditional char[] */ class StrPair { public: enum { NEEDS_ENTITY_PROCESSING = 0x01, NEEDS_NEWLINE_NORMALIZATION = 0x02, COLLAPSE_WHITESPACE = 0x04, TEXT_ELEMENT = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION, TEXT_ELEMENT_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION, ATTRIBUTE_NAME = 0, ATTRIBUTE_VALUE = NEEDS_ENTITY_PROCESSING | NEEDS_NEWLINE_NORMALIZATION, ATTRIBUTE_VALUE_LEAVE_ENTITIES = NEEDS_NEWLINE_NORMALIZATION, COMMENT = NEEDS_NEWLINE_NORMALIZATION }; StrPair() : _flags( 0 ), _start( 0 ), _end( 0 ) {} ~StrPair(); void Set( char* start, char* end, int flags ) { Reset(); _start = start; _end = end; _flags = flags | NEEDS_FLUSH; } const char* GetStr(); bool Empty() const { return _start == _end; } void SetInternedStr( const char* str ) { Reset(); _start = const_cast(str); } void SetStr( const char* str, int flags=0 ); char* ParseText( char* in, const char* endTag, int strFlags ); char* ParseName( char* in ); private: void Reset(); void CollapseWhitespace(); enum { NEEDS_FLUSH = 0x100, NEEDS_DELETE = 0x200 }; // After parsing, if *end != 0, it can be set to zero. int _flags; char* _start; char* _end; }; /* A dynamic array of Plain Old Data. Doesn't support constructors, etc. Has a small initial memory pool, so that low or no usage will not cause a call to new/delete */ template class DynArray { public: DynArray< T, INIT >() { _mem = _pool; _allocated = INIT; _size = 0; } ~DynArray() { if ( _mem != _pool ) { delete [] _mem; } } void Push( T t ) { EnsureCapacity( _size+1 ); _mem[_size++] = t; } T* PushArr( int count ) { EnsureCapacity( _size+count ); T* ret = &_mem[_size]; _size += count; return ret; } T Pop() { return _mem[--_size]; } void PopArr( int count ) { TIXMLASSERT( _size >= count ); _size -= count; } bool Empty() const { return _size == 0; } T& operator[](int i) { TIXMLASSERT( i>= 0 && i < _size ); return _mem[i]; } const T& operator[](int i) const { TIXMLASSERT( i>= 0 && i < _size ); return _mem[i]; } int Size() const { return _size; } int Capacity() const { return _allocated; } const T* Mem() const { return _mem; } T* Mem() { return _mem; } private: void EnsureCapacity( int cap ) { if ( cap > _allocated ) { int newAllocated = cap * 2; T* newMem = new T[newAllocated]; memcpy( newMem, _mem, sizeof(T)*_size ); // warning: not using constructors, only works for PODs if ( _mem != _pool ) { delete [] _mem; } _mem = newMem; _allocated = newAllocated; } } T* _mem; T _pool[INIT]; int _allocated; // objects allocated int _size; // number objects in use }; /* Parent virtual class of a pool for fast allocation and deallocation of objects. */ class MemPool { public: MemPool() {} virtual ~MemPool() {} virtual int ItemSize() const = 0; virtual void* Alloc() = 0; virtual void Free( void* ) = 0; virtual void SetTracked() = 0; }; /* Template child class to create pools of the correct type. */ template< int SIZE > class MemPoolT : public MemPool { public: MemPoolT() : _root(0), _currentAllocs(0), _nAllocs(0), _maxAllocs(0), _nUntracked(0) {} ~MemPoolT() { // Delete the blocks. for( int i=0; i<_blockPtrs.Size(); ++i ) { delete _blockPtrs[i]; } } virtual int ItemSize() const { return SIZE; } int CurrentAllocs() const { return _currentAllocs; } virtual void* Alloc() { if ( !_root ) { // Need a new block. Block* block = new Block(); _blockPtrs.Push( block ); for( int i=0; ichunk[i].next = &block->chunk[i+1]; } block->chunk[COUNT-1].next = 0; _root = block->chunk; } void* result = _root; _root = _root->next; ++_currentAllocs; if ( _currentAllocs > _maxAllocs ) { _maxAllocs = _currentAllocs; } _nAllocs++; _nUntracked++; return result; } virtual void Free( void* mem ) { if ( !mem ) { return; } --_currentAllocs; Chunk* chunk = (Chunk*)mem; #ifdef DEBUG memset( chunk, 0xfe, sizeof(Chunk) ); #endif chunk->next = _root; _root = chunk; } void Trace( const char* name ) { printf( "Mempool %s watermark=%d [%dk] current=%d size=%d nAlloc=%d blocks=%d\n", name, _maxAllocs, _maxAllocs*SIZE/1024, _currentAllocs, SIZE, _nAllocs, _blockPtrs.Size() ); } void SetTracked() { _nUntracked--; } int Untracked() const { return _nUntracked; } // This number is perf sensitive. 4k seems like a good tradeoff on my machine. // The test file is large, 170k. // Release: VS2010 gcc(no opt) // 1k: 4000 // 2k: 4000 // 4k: 3900 21000 // 16k: 5200 // 32k: 4300 // 64k: 4000 21000 enum { COUNT = (4*1024)/SIZE }; // Some compilers do not accept to use COUNT in private part if COUNT is private private: union Chunk { Chunk* next; char mem[SIZE]; }; struct Block { Chunk chunk[COUNT]; }; DynArray< Block*, 10 > _blockPtrs; Chunk* _root; int _currentAllocs; int _nAllocs; int _maxAllocs; int _nUntracked; }; /** Implements the interface to the "Visitor pattern" (see the Accept() method.) If you call the Accept() method, it requires being passed a XMLVisitor class to handle callbacks. For nodes that contain other nodes (Document, Element) you will get called with a VisitEnter/VisitExit pair. Nodes that are always leafs are simply called with Visit(). If you return 'true' from a Visit method, recursive parsing will continue. If you return false, no children of this node or its sibilings will be visited. All flavors of Visit methods have a default implementation that returns 'true' (continue visiting). You need to only override methods that are interesting to you. Generally Accept() is called on the TiXmlDocument, although all nodes support visiting. You should never change the document from a callback. @sa XMLNode::Accept() */ class XMLVisitor { public: virtual ~XMLVisitor() {} /// Visit a document. virtual bool VisitEnter( const XMLDocument& /*doc*/ ) { return true; } /// Visit a document. virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; } /// Visit an element. virtual bool VisitEnter( const XMLElement& /*element*/, const XMLAttribute* /*firstAttribute*/ ) { return true; } /// Visit an element. virtual bool VisitExit( const XMLElement& /*element*/ ) { return true; } /// Visit a declaration. virtual bool Visit( const XMLDeclaration& /*declaration*/ ) { return true; } /// Visit a text node. virtual bool Visit( const XMLText& /*text*/ ) { return true; } /// Visit a comment node. virtual bool Visit( const XMLComment& /*comment*/ ) { return true; } /// Visit an unknown node. virtual bool Visit( const XMLUnknown& /*unknown*/ ) { return true; } }; /* Utility functionality. */ class XMLUtil { public: // Anything in the high order range of UTF-8 is assumed to not be whitespace. This isn't // correct, but simple, and usually works. static const char* SkipWhiteSpace( const char* p ) { while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast(p) ) ) { ++p; } return p; } static char* SkipWhiteSpace( char* p ) { while( !IsUTF8Continuation(*p) && isspace( *reinterpret_cast(p) ) ) { ++p; } return p; } static bool IsWhiteSpace( char p ) { return !IsUTF8Continuation(p) && isspace( static_cast(p) ); } inline static bool IsNameStartChar( unsigned char ch ) { return ( ( ch < 128 ) ? isalpha( ch ) : 1 ) || ch == ':' || ch == '_'; } inline static bool IsNameChar( unsigned char ch ) { return IsNameStartChar( ch ) || isdigit( ch ) || ch == '.' || ch == '-'; } inline static bool StringEqual( const char* p, const char* q, int nChar=INT_MAX ) { int n = 0; if ( p == q ) { return true; } while( *p && *q && *p == *q && n(const_cast(this)->FirstChildElement( value )); } /// Get the last child node, or null if none exists. const XMLNode* LastChild() const { return _lastChild; } XMLNode* LastChild() { return const_cast(const_cast(this)->LastChild() ); } /** Get the last child element or optionally the last child element with the specified name. */ const XMLElement* LastChildElement( const char* value=0 ) const; XMLElement* LastChildElement( const char* value=0 ) { return const_cast(const_cast(this)->LastChildElement(value) ); } /// Get the previous (left) sibling node of this node. const XMLNode* PreviousSibling() const { return _prev; } XMLNode* PreviousSibling() { return _prev; } /// Get the previous (left) sibling element of this node, with an opitionally supplied name. const XMLElement* PreviousSiblingElement( const char* value=0 ) const ; XMLElement* PreviousSiblingElement( const char* value=0 ) { return const_cast(const_cast(this)->PreviousSiblingElement( value ) ); } /// Get the next (right) sibling node of this node. const XMLNode* NextSibling() const { return _next; } XMLNode* NextSibling() { return _next; } /// Get the next (right) sibling element of this node, with an opitionally supplied name. const XMLElement* NextSiblingElement( const char* value=0 ) const; XMLElement* NextSiblingElement( const char* value=0 ) { return const_cast(const_cast(this)->NextSiblingElement( value ) ); } /** Add a child node as the last (right) child. */ XMLNode* InsertEndChild( XMLNode* addThis ); XMLNode* LinkEndChild( XMLNode* addThis ) { return InsertEndChild( addThis ); } /** Add a child node as the first (left) child. */ XMLNode* InsertFirstChild( XMLNode* addThis ); /** Add a node after the specified child node. */ XMLNode* InsertAfterChild( XMLNode* afterThis, XMLNode* addThis ); /** Delete all the children of this node. */ void DeleteChildren(); /** Delete a child of this node. */ void DeleteChild( XMLNode* node ); /** Make a copy of this node, but not its children. You may pass in a Document pointer that will be the owner of the new Node. If the 'document' is null, then the node returned will be allocated from the current Document. (this->GetDocument()) Note: if called on a XMLDocument, this will return null. */ virtual XMLNode* ShallowClone( XMLDocument* document ) const = 0; /** Test if 2 nodes are the same, but don't test children. The 2 nodes do not need to be in the same Document. Note: if called on a XMLDocument, this will return false. */ virtual bool ShallowEqual( const XMLNode* compare ) const = 0; /** Accept a hierarchical visit of the nodes in the TinyXML DOM. Every node in the XML tree will be conditionally visited and the host will be called back via the TiXmlVisitor interface. This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse the XML for the callbacks, so the performance of TinyXML is unchanged by using this interface versus any other.) The interface has been based on ideas from: - http://www.saxproject.org/ - http://c2.com/cgi/wiki?HierarchicalVisitorPattern Which are both good references for "visiting". An example of using Accept(): @verbatim TiXmlPrinter printer; tinyxmlDoc.Accept( &printer ); const char* xmlcstr = printer.CStr(); @endverbatim */ virtual bool Accept( XMLVisitor* visitor ) const = 0; // internal virtual char* ParseDeep( char*, StrPair* ); protected: XMLNode( XMLDocument* ); virtual ~XMLNode(); XMLNode( const XMLNode& ); // not supported XMLNode& operator=( const XMLNode& ); // not supported XMLDocument* _document; XMLNode* _parent; mutable StrPair _value; XMLNode* _firstChild; XMLNode* _lastChild; XMLNode* _prev; XMLNode* _next; private: MemPool* _memPool; void Unlink( XMLNode* child ); }; /** XML text. Note that a text node can have child element nodes, for example: @verbatim This is bold @endverbatim A text node can have 2 ways to output the next. "normal" output and CDATA. It will default to the mode it was parsed from the XML file and you generally want to leave it alone, but you can change the output mode with SetCDATA() and query it with CDATA(). */ class XMLText : public XMLNode { friend class XMLBase; friend class XMLDocument; public: virtual bool Accept( XMLVisitor* visitor ) const; virtual XMLText* ToText() { return this; } virtual const XMLText* ToText() const { return this; } /// Declare whether this should be CDATA or standard text. void SetCData( bool isCData ) { _isCData = isCData; } /// Returns true if this is a CDATA text element. bool CData() const { return _isCData; } char* ParseDeep( char*, StrPair* endTag ); virtual XMLNode* ShallowClone( XMLDocument* document ) const; virtual bool ShallowEqual( const XMLNode* compare ) const; protected: XMLText( XMLDocument* doc ) : XMLNode( doc ), _isCData( false ) {} virtual ~XMLText() {} XMLText( const XMLText& ); // not supported XMLText& operator=( const XMLText& ); // not supported private: bool _isCData; }; /** An XML Comment. */ class XMLComment : public XMLNode { friend class XMLDocument; public: virtual XMLComment* ToComment() { return this; } virtual const XMLComment* ToComment() const { return this; } virtual bool Accept( XMLVisitor* visitor ) const; char* ParseDeep( char*, StrPair* endTag ); virtual XMLNode* ShallowClone( XMLDocument* document ) const; virtual bool ShallowEqual( const XMLNode* compare ) const; protected: XMLComment( XMLDocument* doc ); virtual ~XMLComment(); XMLComment( const XMLComment& ); // not supported XMLComment& operator=( const XMLComment& ); // not supported private: }; /** In correct XML the declaration is the first entry in the file. @verbatim @endverbatim TinyXML2 will happily read or write files without a declaration, however. The text of the declaration isn't interpreted. It is parsed and written as a string. */ class XMLDeclaration : public XMLNode { friend class XMLDocument; public: virtual XMLDeclaration* ToDeclaration() { return this; } virtual const XMLDeclaration* ToDeclaration() const { return this; } virtual bool Accept( XMLVisitor* visitor ) const; char* ParseDeep( char*, StrPair* endTag ); virtual XMLNode* ShallowClone( XMLDocument* document ) const; virtual bool ShallowEqual( const XMLNode* compare ) const; protected: XMLDeclaration( XMLDocument* doc ); virtual ~XMLDeclaration(); XMLDeclaration( const XMLDeclaration& ); // not supported XMLDeclaration& operator=( const XMLDeclaration& ); // not supported }; /** Any tag that tinyXml doesn't recognize is saved as an unknown. It is a tag of text, but should not be modified. It will be written back to the XML, unchanged, when the file is saved. DTD tags get thrown into TiXmlUnknowns. */ class XMLUnknown : public XMLNode { friend class XMLDocument; public: virtual XMLUnknown* ToUnknown() { return this; } virtual const XMLUnknown* ToUnknown() const { return this; } virtual bool Accept( XMLVisitor* visitor ) const; char* ParseDeep( char*, StrPair* endTag ); virtual XMLNode* ShallowClone( XMLDocument* document ) const; virtual bool ShallowEqual( const XMLNode* compare ) const; protected: XMLUnknown( XMLDocument* doc ); virtual ~XMLUnknown(); XMLUnknown( const XMLUnknown& ); // not supported XMLUnknown& operator=( const XMLUnknown& ); // not supported }; enum XMLError { XML_NO_ERROR = 0, XML_SUCCESS = 0, XML_NO_ATTRIBUTE, XML_WRONG_ATTRIBUTE_TYPE, XML_ERROR_FILE_NOT_FOUND, XML_ERROR_FILE_COULD_NOT_BE_OPENED, XML_ERROR_FILE_READ_ERROR, XML_ERROR_ELEMENT_MISMATCH, XML_ERROR_PARSING_ELEMENT, XML_ERROR_PARSING_ATTRIBUTE, XML_ERROR_IDENTIFYING_TAG, XML_ERROR_PARSING_TEXT, XML_ERROR_PARSING_CDATA, XML_ERROR_PARSING_COMMENT, XML_ERROR_PARSING_DECLARATION, XML_ERROR_PARSING_UNKNOWN, XML_ERROR_EMPTY_DOCUMENT, XML_ERROR_MISMATCHED_ELEMENT, XML_ERROR_PARSING, XML_CAN_NOT_CONVERT_TEXT, XML_NO_TEXT_NODE }; /** An attribute is a name-value pair. Elements have an arbitrary number of attributes, each with a unique name. @note The attributes are not XMLNodes. You may only query the Next() attribute in a list. */ class XMLAttribute { friend class XMLElement; public: /// The name of the attribute. const char* Name() const { return _name.GetStr(); } /// The value of the attribute. const char* Value() const { return _value.GetStr(); } /// The next attribute in the list. const XMLAttribute* Next() const { return _next; } /** IntAttribute interprets the attribute as an integer, and returns the value. If the value isn't an integer, 0 will be returned. There is no error checking; use QueryIntAttribute() if you need error checking. */ int IntValue() const { int i=0; QueryIntValue( &i ); return i; } /// Query as an unsigned integer. See IntAttribute() unsigned UnsignedValue() const { unsigned i=0; QueryUnsignedValue( &i ); return i; } /// Query as a boolean. See IntAttribute() bool BoolValue() const { bool b=false; QueryBoolValue( &b ); return b; } /// Query as a double. See IntAttribute() double DoubleValue() const { double d=0; QueryDoubleValue( &d ); return d; } /// Query as a float. See IntAttribute() float FloatValue() const { float f=0; QueryFloatValue( &f ); return f; } /** QueryIntAttribute interprets the attribute as an integer, and returns the value in the provided paremeter. The function will return XML_NO_ERROR on success, and XML_WRONG_ATTRIBUTE_TYPE if the conversion is not successful. */ XMLError QueryIntValue( int* value ) const; /// See QueryIntAttribute XMLError QueryUnsignedValue( unsigned int* value ) const; /// See QueryIntAttribute XMLError QueryBoolValue( bool* value ) const; /// See QueryIntAttribute XMLError QueryDoubleValue( double* value ) const; /// See QueryIntAttribute XMLError QueryFloatValue( float* value ) const; /// Set the attribute to a string value. void SetAttribute( const char* value ); /// Set the attribute to value. void SetAttribute( int value ); /// Set the attribute to value. void SetAttribute( unsigned value ); /// Set the attribute to value. void SetAttribute( bool value ); /// Set the attribute to value. void SetAttribute( double value ); /// Set the attribute to value. void SetAttribute( float value ); private: enum { BUF_SIZE = 200 }; XMLAttribute() : _next( 0 ) {} virtual ~XMLAttribute() {} XMLAttribute( const XMLAttribute& ); // not supported void operator=( const XMLAttribute& ); // not supported void SetName( const char* name ); char* ParseDeep( char* p, bool processEntities ); mutable StrPair _name; mutable StrPair _value; XMLAttribute* _next; MemPool* _memPool; }; /** The element is a container class. It has a value, the element name, and can contain other elements, text, comments, and unknowns. Elements also contain an arbitrary number of attributes. */ class XMLElement : public XMLNode { friend class XMLBase; friend class XMLDocument; public: /// Get the name of an element (which is the Value() of the node.) const char* Name() const { return Value(); } /// Set the name of the element. void SetName( const char* str, bool staticMem=false ) { SetValue( str, staticMem ); } virtual XMLElement* ToElement() { return this; } virtual const XMLElement* ToElement() const { return this; } virtual bool Accept( XMLVisitor* visitor ) const; /** Given an attribute name, Attribute() returns the value for the attribute of that name, or null if none exists. For example: @verbatim const char* value = ele->Attribute( "foo" ); @endverbatim The 'value' parameter is normally null. However, if specified, the attribute will only be returned if the 'name' and 'value' match. This allow you to write code: @verbatim if ( ele->Attribute( "foo", "bar" ) ) callFooIsBar(); @endverbatim rather than: @verbatim if ( ele->Attribute( "foo" ) ) { if ( strcmp( ele->Attribute( "foo" ), "bar" ) == 0 ) callFooIsBar(); } @endverbatim */ const char* Attribute( const char* name, const char* value=0 ) const; /** Given an attribute name, IntAttribute() returns the value of the attribute interpreted as an integer. 0 will be returned if there is an error. For a method with error checking, see QueryIntAttribute() */ int IntAttribute( const char* name ) const { int i=0; QueryIntAttribute( name, &i ); return i; } /// See IntAttribute() unsigned UnsignedAttribute( const char* name ) const { unsigned i=0; QueryUnsignedAttribute( name, &i ); return i; } /// See IntAttribute() bool BoolAttribute( const char* name ) const { bool b=false; QueryBoolAttribute( name, &b ); return b; } /// See IntAttribute() double DoubleAttribute( const char* name ) const { double d=0; QueryDoubleAttribute( name, &d ); return d; } /// See IntAttribute() float FloatAttribute( const char* name ) const { float f=0; QueryFloatAttribute( name, &f ); return f; } /** Given an attribute name, QueryIntAttribute() returns XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion can't be performed, or XML_NO_ATTRIBUTE if the attribute doesn't exist. If successful, the result of the conversion will be written to 'value'. If not successful, nothing will be written to 'value'. This allows you to provide default value: @verbatim int value = 10; QueryIntAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10 @endverbatim */ XMLError QueryIntAttribute( const char* name, int* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) { return XML_NO_ATTRIBUTE; } return a->QueryIntValue( value ); } /// See QueryIntAttribute() XMLError QueryUnsignedAttribute( const char* name, unsigned int* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) { return XML_NO_ATTRIBUTE; } return a->QueryUnsignedValue( value ); } /// See QueryIntAttribute() XMLError QueryBoolAttribute( const char* name, bool* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) { return XML_NO_ATTRIBUTE; } return a->QueryBoolValue( value ); } /// See QueryIntAttribute() XMLError QueryDoubleAttribute( const char* name, double* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) { return XML_NO_ATTRIBUTE; } return a->QueryDoubleValue( value ); } /// See QueryIntAttribute() XMLError QueryFloatAttribute( const char* name, float* value ) const { const XMLAttribute* a = FindAttribute( name ); if ( !a ) { return XML_NO_ATTRIBUTE; } return a->QueryFloatValue( value ); } /** Given an attribute name, QueryAttribute() returns XML_NO_ERROR, XML_WRONG_ATTRIBUTE_TYPE if the conversion can't be performed, or XML_NO_ATTRIBUTE if the attribute doesn't exist. It is overloaded for the primitive types, and is a generally more convenient replacement of QueryIntAttribute() and related functions. If successful, the result of the conversion will be written to 'value'. If not successful, nothing will be written to 'value'. This allows you to provide default value: @verbatim int value = 10; QueryAttribute( "foo", &value ); // if "foo" isn't found, value will still be 10 @endverbatim */ int QueryAttribute( const char* name, int* value ) const { return QueryIntAttribute( name, value ); } int QueryAttribute( const char* name, unsigned int* value ) const { return QueryUnsignedAttribute( name, value ); } int QueryAttribute( const char* name, bool* value ) const { return QueryBoolAttribute( name, value ); } int QueryAttribute( const char* name, double* value ) const { return QueryDoubleAttribute( name, value ); } int QueryAttribute( const char* name, float* value ) const { return QueryFloatAttribute( name, value ); } /// Sets the named attribute to value. void SetAttribute( const char* name, const char* value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); } /// Sets the named attribute to value. void SetAttribute( const char* name, int value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); } /// Sets the named attribute to value. void SetAttribute( const char* name, unsigned value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); } /// Sets the named attribute to value. void SetAttribute( const char* name, bool value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); } /// Sets the named attribute to value. void SetAttribute( const char* name, double value ) { XMLAttribute* a = FindOrCreateAttribute( name ); a->SetAttribute( value ); } /** Delete an attribute. */ void DeleteAttribute( const char* name ); /// Return the first attribute in the list. const XMLAttribute* FirstAttribute() const { return _rootAttribute; } /// Query a specific attribute in the list. const XMLAttribute* FindAttribute( const char* name ) const; /** Convenience function for easy access to the text inside an element. Although easy and concise, GetText() is limited compared to getting the TiXmlText child and accessing it directly. If the first child of 'this' is a TiXmlText, the GetText() returns the character string of the Text node, else null is returned. This is a convenient method for getting the text of simple contained text: @verbatim This is text const char* str = fooElement->GetText(); @endverbatim 'str' will be a pointer to "This is text". Note that this function can be misleading. If the element foo was created from this XML: @verbatim This is text @endverbatim then the value of str would be null. The first child node isn't a text node, it is another element. From this XML: @verbatim This is text @endverbatim GetText() will return "This is ". */ const char* GetText() const; /** Convenience method to query the value of a child text node. This is probably best shown by example. Given you have a document is this form: @verbatim 1 1.4 @endverbatim The QueryIntText() and similar functions provide a safe and easier way to get to the "value" of x and y. @verbatim int x = 0; float y = 0; // types of x and y are contrived for example const XMLElement* xElement = pointElement->FirstChildElement( "x" ); const XMLElement* yElement = pointElement->FirstChildElement( "y" ); xElement->QueryIntText( &x ); yElement->QueryFloatText( &y ); @endverbatim @returns XML_SUCCESS (0) on success, XML_CAN_NOT_CONVERT_TEXT if the text cannot be converted to the requested type, and XML_NO_TEXT_NODE if there is no child text to query. */ XMLError QueryIntText( int* ival ) const; /// See QueryIntText() XMLError QueryUnsignedText( unsigned* uval ) const; /// See QueryIntText() XMLError QueryBoolText( bool* bval ) const; /// See QueryIntText() XMLError QueryDoubleText( double* dval ) const; /// See QueryIntText() XMLError QueryFloatText( float* fval ) const; // internal: enum { OPEN, // CLOSED, // CLOSING // }; int ClosingType() const { return _closingType; } char* ParseDeep( char* p, StrPair* endTag ); virtual XMLNode* ShallowClone( XMLDocument* document ) const; virtual bool ShallowEqual( const XMLNode* compare ) const; private: XMLElement( XMLDocument* doc ); virtual ~XMLElement(); XMLElement( const XMLElement& ); // not supported void operator=( const XMLElement& ); // not supported XMLAttribute* FindAttribute( const char* name ); XMLAttribute* FindOrCreateAttribute( const char* name ); //void LinkAttribute( XMLAttribute* attrib ); char* ParseAttributes( char* p ); int _closingType; // The attribute list is ordered; there is no 'lastAttribute' // because the list needs to be scanned for dupes before adding // a new attribute. XMLAttribute* _rootAttribute; }; enum Whitespace { PRESERVE_WHITESPACE, COLLAPSE_WHITESPACE }; /** A Document binds together all the functionality. It can be saved, loaded, and printed to the screen. All Nodes are connected and allocated to a Document. If the Document is deleted, all its Nodes are also deleted. */ class XMLDocument : public XMLNode { friend class XMLElement; public: /// constructor XMLDocument( bool processEntities = true, Whitespace = PRESERVE_WHITESPACE ); ~XMLDocument(); virtual XMLDocument* ToDocument() { return this; } virtual const XMLDocument* ToDocument() const { return this; } /** Parse an XML file from a character string. Returns XML_NO_ERROR (0) on success, or an errorID. You may optionally pass in the 'nBytes', which is the number of bytes which will be parsed. If not specified, TinyXML will assume 'xml' points to a null terminated string. */ XMLError Parse( const char* xml, size_t nBytes=(size_t)(-1) ); /** Load an XML file from disk. Returns XML_NO_ERROR (0) on success, or an errorID. */ XMLError LoadFile( const char* filename ); /** Load an XML file from disk. You are responsible for providing and closing the FILE*. Returns XML_NO_ERROR (0) on success, or an errorID. */ XMLError LoadFile( FILE* ); /** Save the XML file to disk. Returns XML_NO_ERROR (0) on success, or an errorID. */ XMLError SaveFile( const char* filename, bool compact = false ); /** Save the XML file to disk. You are responsible for providing and closing the FILE*. Returns XML_NO_ERROR (0) on success, or an errorID. */ XMLError SaveFile( FILE* fp, bool compact = false ); bool ProcessEntities() const { return _processEntities; } Whitespace WhitespaceMode() const { return _whitespace; } /** Returns true if this document has a leading Byte Order Mark of UTF8. */ bool HasBOM() const { return _writeBOM; } /** Sets whether to write the BOM when writing the file. */ void SetBOM( bool useBOM ) { _writeBOM = useBOM; } /** Return the root element of DOM. Equivalent to FirstChildElement(). To get the first node, use FirstChild(). */ XMLElement* RootElement() { return FirstChildElement(); } const XMLElement* RootElement() const { return FirstChildElement(); } /** Print the Document. If the Printer is not provided, it will print to stdout. If you provide Printer, this can print to a file: @verbatim XMLPrinter printer( fp ); doc.Print( &printer ); @endverbatim Or you can use a printer to print to memory: @verbatim XMLPrinter printer; doc->Print( &printer ); // printer.CStr() has a const char* to the XML @endverbatim */ void Print( XMLPrinter* streamer=0 ); virtual bool Accept( XMLVisitor* visitor ) const; /** Create a new Element associated with this Document. The memory for the Element is managed by the Document. */ XMLElement* NewElement( const char* name ); /** Create a new Comment associated with this Document. The memory for the Comment is managed by the Document. */ XMLComment* NewComment( const char* comment ); /** Create a new Text associated with this Document. The memory for the Text is managed by the Document. */ XMLText* NewText( const char* text ); /** Create a new Declaration associated with this Document. The memory for the object is managed by the Document. If the 'text' param is null, the standard declaration is used.: @verbatim @endverbatim */ XMLDeclaration* NewDeclaration( const char* text=0 ); /** Create a new Unknown associated with this Document. The memory forthe object is managed by the Document. */ XMLUnknown* NewUnknown( const char* text ); /** Delete a node associated with this document. It will be unlinked from the DOM. */ void DeleteNode( XMLNode* node ) { node->_parent->DeleteChild( node ); } void SetError( XMLError error, const char* str1, const char* str2 ); /// Return true if there was an error parsing the document. bool Error() const { return _errorID != XML_NO_ERROR; } /// Return the errorID. XMLError ErrorID() const { return _errorID; } /// Return a possibly helpful diagnostic location or string. const char* GetErrorStr1() const { return _errorStr1; } /// Return a possibly helpful secondary diagnostic location or string. const char* GetErrorStr2() const { return _errorStr2; } /// If there is an error, print it to stdout. void PrintError() const; /// Clear the document, resetting it to the initial state. void Clear(); // internal char* Identify( char* p, XMLNode** node ); virtual XMLNode* ShallowClone( XMLDocument* /*document*/ ) const { return 0; } virtual bool ShallowEqual( const XMLNode* /*compare*/ ) const { return false; } private: XMLDocument( const XMLDocument& ); // not supported void operator=( const XMLDocument& ); // not supported bool _writeBOM; bool _processEntities; XMLError _errorID; Whitespace _whitespace; const char* _errorStr1; const char* _errorStr2; char* _charBuffer; MemPoolT< sizeof(XMLElement) > _elementPool; MemPoolT< sizeof(XMLAttribute) > _attributePool; MemPoolT< sizeof(XMLText) > _textPool; MemPoolT< sizeof(XMLComment) > _commentPool; }; /** A XMLHandle is a class that wraps a node pointer with null checks; this is an incredibly useful thing. Note that XMLHandle is not part of the TinyXML DOM structure. It is a separate utility class. Take an example: @verbatim @endverbatim Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very easy to write a *lot* of code that looks like: @verbatim XMLElement* root = document.FirstChildElement( "Document" ); if ( root ) { XMLElement* element = root->FirstChildElement( "Element" ); if ( element ) { XMLElement* child = element->FirstChildElement( "Child" ); if ( child ) { XMLElement* child2 = child->NextSiblingElement( "Child" ); if ( child2 ) { // Finally do something useful. @endverbatim And that doesn't even cover "else" cases. XMLHandle addresses the verbosity of such code. A XMLHandle checks for null pointers so it is perfectly safe and correct to use: @verbatim XMLHandle docHandle( &document ); XMLElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild().NextSibling().ToElement(); if ( child2 ) { // do something useful @endverbatim Which is MUCH more concise and useful. It is also safe to copy handles - internally they are nothing more than node pointers. @verbatim XMLHandle handleCopy = handle; @endverbatim See also XMLConstHandle, which is the same as XMLHandle, but operates on const objects. */ class XMLHandle { public: /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. XMLHandle( XMLNode* node ) { _node = node; } /// Create a handle from a node. XMLHandle( XMLNode& node ) { _node = &node; } /// Copy constructor XMLHandle( const XMLHandle& ref ) { _node = ref._node; } /// Assignment XMLHandle& operator=( const XMLHandle& ref ) { _node = ref._node; return *this; } /// Get the first child of this handle. XMLHandle FirstChild() { return XMLHandle( _node ? _node->FirstChild() : 0 ); } /// Get the first child element of this handle. XMLHandle FirstChildElement( const char* value=0 ) { return XMLHandle( _node ? _node->FirstChildElement( value ) : 0 ); } /// Get the last child of this handle. XMLHandle LastChild() { return XMLHandle( _node ? _node->LastChild() : 0 ); } /// Get the last child element of this handle. XMLHandle LastChildElement( const char* _value=0 ) { return XMLHandle( _node ? _node->LastChildElement( _value ) : 0 ); } /// Get the previous sibling of this handle. XMLHandle PreviousSibling() { return XMLHandle( _node ? _node->PreviousSibling() : 0 ); } /// Get the previous sibling element of this handle. XMLHandle PreviousSiblingElement( const char* _value=0 ) { return XMLHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 ); } /// Get the next sibling of this handle. XMLHandle NextSibling() { return XMLHandle( _node ? _node->NextSibling() : 0 ); } /// Get the next sibling element of this handle. XMLHandle NextSiblingElement( const char* _value=0 ) { return XMLHandle( _node ? _node->NextSiblingElement( _value ) : 0 ); } /// Safe cast to XMLNode. This can return null. XMLNode* ToNode() { return _node; } /// Safe cast to XMLElement. This can return null. XMLElement* ToElement() { return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 ); } /// Safe cast to XMLText. This can return null. XMLText* ToText() { return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 ); } /// Safe cast to XMLUnknown. This can return null. XMLUnknown* ToUnknown() { return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 ); } /// Safe cast to XMLDeclaration. This can return null. XMLDeclaration* ToDeclaration() { return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 ); } private: XMLNode* _node; }; /** A variant of the XMLHandle class for working with const XMLNodes and Documents. It is the same in all regards, except for the 'const' qualifiers. See XMLHandle for API. */ class XMLConstHandle { public: XMLConstHandle( const XMLNode* node ) { _node = node; } XMLConstHandle( const XMLNode& node ) { _node = &node; } XMLConstHandle( const XMLConstHandle& ref ) { _node = ref._node; } XMLConstHandle& operator=( const XMLConstHandle& ref ) { _node = ref._node; return *this; } const XMLConstHandle FirstChild() const { return XMLConstHandle( _node ? _node->FirstChild() : 0 ); } const XMLConstHandle FirstChildElement( const char* value=0 ) const { return XMLConstHandle( _node ? _node->FirstChildElement( value ) : 0 ); } const XMLConstHandle LastChild() const { return XMLConstHandle( _node ? _node->LastChild() : 0 ); } const XMLConstHandle LastChildElement( const char* _value=0 ) const { return XMLConstHandle( _node ? _node->LastChildElement( _value ) : 0 ); } const XMLConstHandle PreviousSibling() const { return XMLConstHandle( _node ? _node->PreviousSibling() : 0 ); } const XMLConstHandle PreviousSiblingElement( const char* _value=0 ) const { return XMLConstHandle( _node ? _node->PreviousSiblingElement( _value ) : 0 ); } const XMLConstHandle NextSibling() const { return XMLConstHandle( _node ? _node->NextSibling() : 0 ); } const XMLConstHandle NextSiblingElement( const char* _value=0 ) const { return XMLConstHandle( _node ? _node->NextSiblingElement( _value ) : 0 ); } const XMLNode* ToNode() const { return _node; } const XMLElement* ToElement() const { return ( ( _node && _node->ToElement() ) ? _node->ToElement() : 0 ); } const XMLText* ToText() const { return ( ( _node && _node->ToText() ) ? _node->ToText() : 0 ); } const XMLUnknown* ToUnknown() const { return ( ( _node && _node->ToUnknown() ) ? _node->ToUnknown() : 0 ); } const XMLDeclaration* ToDeclaration() const { return ( ( _node && _node->ToDeclaration() ) ? _node->ToDeclaration() : 0 ); } private: const XMLNode* _node; }; /** Printing functionality. The XMLPrinter gives you more options than the XMLDocument::Print() method. It can: -# Print to memory. -# Print to a file you provide. -# Print XML without a XMLDocument. Print to Memory @verbatim XMLPrinter printer; doc->Print( &printer ); SomeFunction( printer.CStr() ); @endverbatim Print to a File You provide the file pointer. @verbatim XMLPrinter printer( fp ); doc.Print( &printer ); @endverbatim Print without a XMLDocument When loading, an XML parser is very useful. However, sometimes when saving, it just gets in the way. The code is often set up for streaming, and constructing the DOM is just overhead. The Printer supports the streaming case. The following code prints out a trivially simple XML file without ever creating an XML document. @verbatim XMLPrinter printer( fp ); printer.OpenElement( "foo" ); printer.PushAttribute( "foo", "bar" ); printer.CloseElement(); @endverbatim */ class XMLPrinter : public XMLVisitor { public: /** Construct the printer. If the FILE* is specified, this will print to the FILE. Else it will print to memory, and the result is available in CStr(). If 'compact' is set to true, then output is created with only required whitespace and newlines. */ XMLPrinter( FILE* file=0, bool compact = false ); ~XMLPrinter() {} /** If streaming, write the BOM and declaration. */ void PushHeader( bool writeBOM, bool writeDeclaration ); /** If streaming, start writing an element. The element must be closed with CloseElement() */ void OpenElement( const char* name ); /// If streaming, add an attribute to an open element. void PushAttribute( const char* name, const char* value ); void PushAttribute( const char* name, int value ); void PushAttribute( const char* name, unsigned value ); void PushAttribute( const char* name, bool value ); void PushAttribute( const char* name, double value ); /// If streaming, close the Element. void CloseElement(); /// Add a text node. void PushText( const char* text, bool cdata=false ); /// Add a text node from an integer. void PushText( int value ); /// Add a text node from an unsigned. void PushText( unsigned value ); /// Add a text node from a bool. void PushText( bool value ); /// Add a text node from a float. void PushText( float value ); /// Add a text node from a double. void PushText( double value ); /// Add a comment void PushComment( const char* comment ); void PushDeclaration( const char* value ); void PushUnknown( const char* value ); virtual bool VisitEnter( const XMLDocument& /*doc*/ ); virtual bool VisitExit( const XMLDocument& /*doc*/ ) { return true; } virtual bool VisitEnter( const XMLElement& element, const XMLAttribute* attribute ); virtual bool VisitExit( const XMLElement& element ); virtual bool Visit( const XMLText& text ); virtual bool Visit( const XMLComment& comment ); virtual bool Visit( const XMLDeclaration& declaration ); virtual bool Visit( const XMLUnknown& unknown ); /** If in print to memory mode, return a pointer to the XML file in memory. */ const char* CStr() const { return _buffer.Mem(); } /** If in print to memory mode, return the size of the XML file in memory. (Note the size returned includes the terminating null.) */ int CStrSize() const { return _buffer.Size(); } private: void SealElement(); void PrintSpace( int depth ); void PrintString( const char*, bool restrictedEntitySet ); // prints out, after detecting entities. void Print( const char* format, ... ); bool _elementJustOpened; bool _firstElement; FILE* _fp; int _depth; int _textDepth; bool _processEntities; bool _compactMode; enum { ENTITY_RANGE = 64, BUF_SIZE = 200 }; bool _entityFlag[ENTITY_RANGE]; bool _restrictedEntityFlag[ENTITY_RANGE]; DynArray< const char*, 10 > _stack; DynArray< char, 20 > _buffer; #ifdef _MSC_VER DynArray< char, 20 > _accumulator; #endif }; } // tinyxml2 #endif // TINYXML2_INCLUDED cppcheck-1.61/generate_coverage_report000077500000000000000000000007341217722632100202160ustar00rootroot00000000000000#!/bin/bash set -e make clean rm -rf coverage_report make test CXXFLAGS="-g -fprofile-arcs -ftest-coverage" gcov lib/*.cpp -o lib/ lcov --directory ./ --capture --output-file lcov_tmp.info -b ./ lcov --extract lcov_tmp.info "$(pwd)/*" --output-file lcov.info genhtml lcov.info -o coverage_report rm cli/*.gcda rm cli/*.gcno rm lib/*.gcda rm lib/*.gcno rm test/*.gcda rm test/*.gcno rm externals/tinyxml/*.gcda rm externals/tinyxml/*.gcno rm lcov.info lcov_tmp.info make clean cppcheck-1.61/gui/000077500000000000000000000000001217722632100140105ustar00rootroot00000000000000cppcheck-1.61/gui/about.ui000066400000000000000000000102071217722632100154610ustar00rootroot00000000000000 About 0 0 478 300 About Cppcheck :/icon.png Qt::Vertical 20 40 Qt::Horizontal 40 20 Version %1 Cppcheck - A tool for static C/C++ code analysis. true Copyright © 2007-2013 Daniel Marjamäki and cppcheck team. true This program is licensed under the terms of the GNU General Public License version 3 true Visit Cppcheck homepage at %1 true true Qt::Horizontal QDialogButtonBox::Ok mButtons accepted() About accept() 248 254 157 274 mButtons rejected() About reject() 316 260 286 274 cppcheck-1.61/gui/aboutdialog.cpp000066400000000000000000000026151217722632100170120ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include #include #include "aboutdialog.h" AboutDialog::AboutDialog(const QString &version, const QString &extraVersion, QWidget *parent) : QDialog(parent) { mUI.setupUi(this); QString fmtVersion(version); if (!extraVersion.isEmpty()) { fmtVersion += " (" + extraVersion + ")"; } mUI.mVersion->setText(mUI.mVersion->text().arg(fmtVersion)); QString url = "http://cppcheck.sourceforge.net/"; mUI.mHomepage->setText(mUI.mHomepage->text().arg(url)); connect(mUI.mButtons, SIGNAL(accepted()), this, SLOT(accept())); } cppcheck-1.61/gui/aboutdialog.h000066400000000000000000000022411217722632100164520ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #ifndef ABOUT_DIALOG_H #define ABOUT_DIALOG_H #include #include #include "ui_about.h" class QWidget; /// @addtogroup GUI /// @{ /** * @brief About dialog * */ class AboutDialog : public QDialog { Q_OBJECT public: AboutDialog(const QString &version, const QString &extraVersion, QWidget *parent = 0); private: Ui::About mUI; }; /// @} #endif // ABOUT_DIALOG_H cppcheck-1.61/gui/application.cpp000066400000000000000000000017241217722632100170230ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include "application.h" Application::Application(const QString &name, const QString &path, const QString ¶ms) : mName(name) , mPath(path) , mParameters(params) { } cppcheck-1.61/gui/application.h000066400000000000000000000057241217722632100164740ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #ifndef APPLICATION_H #define APPLICATION_H #include /** * @brief A class containing information of the application to execute. * * Each application has a name and a path. Name is displayed to the user * and has no other meaning. It isn't used to start the application. * Path contains the full path to the application containing the executable name. * Parameters contains the command line arguments for the executable. * * User can also specify certain predefined strings to parameters. These strings * will be replaced with appropriate values concerning the error. Strings are: * (file) - Filename containing the error * (line) - Line number containing the error * (message) - Error message * (severity) - Error severity * * Example opening a file with Kate and make Kate scroll to the correct line. * Executable: kate * Parameters: -l(line) (file) */ class Application { public: Application() { } Application(const QString &name, const QString &path, const QString ¶ms); /** * @brief Get application name. * @return Application name. */ QString getName() const { return mName; } /** * @brief Get application path. * @return Application path. */ QString getPath() const { return mPath; } /** * @brief Get application command line parameters. * @return Application command line parameters. */ QString getParameters() const { return mParameters; } /** * @brief Set application name. * @param name Application name. */ void setName(const QString &name) { mName = name; } /** * @brief Set application path. * @param path Application path. */ void setPath(const QString &path) { mPath = path; } /** * @brief Set application command line parameters. * @param parameters Application command line parameters. */ void setParameters(const QString ¶meters) { mParameters = parameters; } private: /** * @brief Application's name */ QString mName; /** * @brief Application's path */ QString mPath; /** * @brief Application's parameters */ QString mParameters; }; #endif // APPLICATION_H cppcheck-1.61/gui/application.ui000066400000000000000000000125211217722632100166530ustar00rootroot00000000000000 ApplicationDialog Qt::WindowModal 0 0 569 471 0 0 Add an application 0 0 0 0 Here you can add an application that can open error files. Specify a name for the application, the application executable and command line parameters for the application. The following texts in parameters are replaced with appropriate values when application is executed: (file) - Filename containing the error (line) - Line number containing the error (message) - Error message (severity) - Error severity Example opening a file with Kate and make Kate scroll to the correct line: Executable: kate Parameters: -l(line) (file) Qt::AutoText false Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop true &Name: mName &Executable: mPath &Parameters: mParameters Qt::Horizontal 40 20 Browse Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok mName mPath mParameters mButtonBrowse mButtons mButtons accepted() ApplicationDialog accept() 248 254 157 274 mButtons rejected() ApplicationDialog reject() 316 260 286 274 cppcheck-1.61/gui/applicationdialog.cpp000066400000000000000000000057321217722632100202060ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include #include #include #include #include "applicationdialog.h" #include "application.h" #include "common.h" ApplicationDialog::ApplicationDialog(const QString &title, Application &app, QWidget *parent) : QDialog(parent), mApplication(app) { mUI.setupUi(this); connect(mUI.mButtonBrowse, SIGNAL(clicked()), this, SLOT(Browse())); connect(mUI.mButtons, SIGNAL(accepted()), this, SLOT(Ok())); connect(mUI.mButtons, SIGNAL(rejected()), this, SLOT(reject())); mUI.mPath->setText(app.getPath()); mUI.mName->setText(app.getName()); mUI.mParameters->setText(app.getParameters()); setWindowTitle(title); adjustSize(); } ApplicationDialog::~ApplicationDialog() { //dtor } void ApplicationDialog::Browse() { QString filter; #ifdef Q_WS_WIN // In Windows (almost) all executables have .exe extension // so it does not make sense to show everything. filter += tr("Executable files (*.exe);;All files(*.*)"); #endif // Q_WS_WIN QString selectedFile = QFileDialog::getOpenFileName(this, tr("Select viewer application"), GetPath(SETTINGS_LAST_APP_PATH), filter); if (!selectedFile.isEmpty()) { SetPath(SETTINGS_LAST_APP_PATH, selectedFile); QString path(QDir::toNativeSeparators(selectedFile)); mUI.mPath->setText(path); } } void ApplicationDialog::Ok() { if (mUI.mName->text().isEmpty() || mUI.mPath->text().isEmpty()) { QMessageBox msg(QMessageBox::Warning, tr("Cppcheck"), tr("You must specify a name, a path and optionally parameters for the application!"), QMessageBox::Ok, this); msg.exec(); reject(); } else { // Convert possible native (Windows) path to internal presentation format mApplication.setName(mUI.mName->text()); mApplication.setPath(QDir::fromNativeSeparators(mUI.mPath->text())); mApplication.setParameters(mUI.mParameters->text()); accept(); } } cppcheck-1.61/gui/applicationdialog.h000066400000000000000000000035161217722632100176510ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #ifndef APPLICATIONDIALOG_H #define APPLICATIONDIALOG_H #include #include #include "application.h" #include "ui_application.h" class QWidget; /// @addtogroup GUI /// @{ /** * @brief Dialog to edit a startable application. * User can open errors with user specified applications. This is a dialog * to modify/add an application to open errors with. * */ class ApplicationDialog : public QDialog { Q_OBJECT public: /** * @brief Constructor. * @param title Title for the dialog. * @param app Application definition. * @param parent Parent widget. */ ApplicationDialog(const QString &title, Application &app, QWidget *parent = 0); virtual ~ApplicationDialog(); protected slots: void Ok(); /** * @brief Slot to browse for an application * */ void Browse(); protected: /** * @brief UI from the Qt designer * */ Ui::ApplicationDialog mUI; private: /** * @brief Underlying Application */ Application& mApplication; }; /// @} #endif // APPLICATIONDIALOG_H cppcheck-1.61/gui/applicationlist.cpp000066400000000000000000000145741217722632100177260ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include #include #include #include #include "common.h" #include "applicationlist.h" #include "application.h" ApplicationList::ApplicationList(QObject *parent) : QObject(parent), mDefaultApplicationIndex(-1) { //ctor } ApplicationList::~ApplicationList() { Clear(); } bool ApplicationList::LoadSettings() { QSettings settings; QStringList names = settings.value(SETTINGS_APPLICATION_NAMES, QStringList()).toStringList(); QStringList paths = settings.value(SETTINGS_APPLICATION_PATHS, QStringList()).toStringList(); QStringList params = settings.value(SETTINGS_APPLICATION_PARAMS, QStringList()).toStringList(); int defapp = settings.value(SETTINGS_APPLICATION_DEFAULT, -1).toInt(); // Params will be empty first time starting with the new setting. // Return false and inform user about problem with application settings. bool succeeded = true; if (!names.empty() && !paths.empty() && params.empty()) { for (int i = 0; i < paths.length(); i++) params << ""; succeeded = false; } if (names.empty() && paths.empty() && params.empty()) { #ifndef _WIN32 // use as default for gnome environments if (QFileInfo("/usr/bin/gedit").isExecutable()) { Application app; app.setName("gedit"); app.setPath("/usr/bin/gedit"); app.setParameters("+(line) (file)"); AddApplication(app); defapp = 0; } // use as default for kde environments if (QFileInfo("/usr/bin/kate").isExecutable()) { Application app; app.setName("kate"); app.setPath("/usr/bin/kate"); app.setParameters("-l(line) (file)"); AddApplication(app); defapp = 0; } #else if (FindDefaultWindowsEditor()) { defapp = 0; } #endif } else if (names.size() == paths.size()) { for (int i = 0; i < names.size(); i++) { const Application app(names[i], paths[i], params[i]); AddApplication(app); } } if (defapp == -1) mDefaultApplicationIndex = 0; else if (defapp < names.size()) mDefaultApplicationIndex = defapp; else mDefaultApplicationIndex = 0; return succeeded; } void ApplicationList::SaveSettings() const { QSettings settings; QStringList names; QStringList paths; QStringList params; for (int i = 0; i < GetApplicationCount(); i++) { const Application& app = GetApplication(i); names << app.getName(); paths << app.getPath(); params << app.getParameters(); } settings.setValue(SETTINGS_APPLICATION_NAMES, names); settings.setValue(SETTINGS_APPLICATION_PATHS, paths); settings.setValue(SETTINGS_APPLICATION_PARAMS, params); settings.setValue(SETTINGS_APPLICATION_DEFAULT, mDefaultApplicationIndex); } int ApplicationList::GetApplicationCount() const { return mApplications.size(); } Application& ApplicationList::GetApplication(const int index) { if (index >= 0 && index < mApplications.size()) { return mApplications[index]; } static Application dummy; // TODO: Throw exception instead? return dummy; } const Application& ApplicationList::GetApplication(const int index) const { if (index >= 0 && index < mApplications.size()) { return mApplications[index]; } static const Application dummy; // TODO: Throw exception instead? return dummy; } void ApplicationList::AddApplication(const Application &app) { if (app.getName().isEmpty() || app.getPath().isEmpty()) { return; } mApplications << app; } void ApplicationList::RemoveApplication(const int index) { mApplications.removeAt(index); } void ApplicationList::SetDefault(const int index) { if (index < mApplications.size() && index >= 0) { mDefaultApplicationIndex = index; } } void ApplicationList::Copy(const ApplicationList *list) { if (!list) { return; } Clear(); for (int i = 0; i < list->GetApplicationCount(); i++) { const Application& app = list->GetApplication(i); AddApplication(app); } mDefaultApplicationIndex = list->GetDefaultApplication(); } void ApplicationList::Clear() { mApplications.clear(); mDefaultApplicationIndex = -1; } bool ApplicationList::FindDefaultWindowsEditor() { bool foundOne = false; const QString appPath(getenv("ProgramFiles")); const QString notepadppPath = appPath + "\\Notepad++\\notepad++.exe"; if (QFileInfo(notepadppPath).exists() && QFileInfo(notepadppPath).isExecutable()) { Application app; app.setName("Notepad++"); app.setPath("\"" + notepadppPath + "\""); app.setParameters("-n(line) (file)"); AddApplication(app); foundOne = true; } const QString notepadTwoPath = appPath + "\\Notepad2\\Notepad2.exe"; if (QFileInfo(notepadTwoPath).exists() && QFileInfo(notepadTwoPath).isExecutable()) { Application app; app.setName("Notepad2"); app.setPath("\"" + notepadTwoPath + "\""); app.setParameters("/g (line) (file)"); AddApplication(app); foundOne = true; } const QString windowsPath(getenv("windir")); const QString notepadPath = windowsPath + "\\system32\\notepad.exe"; if (QFileInfo(notepadPath).exists() && QFileInfo(notepadPath).isExecutable()) { Application app; app.setName("Notepad"); app.setPath(notepadPath); app.setParameters("(file)"); AddApplication(app); foundOne = true; } return foundOne; } cppcheck-1.61/gui/applicationlist.h000066400000000000000000000063131217722632100173630ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #ifndef APPLICATIONLIST_H #define APPLICATIONLIST_H #include #include "application.h" /// @addtogroup GUI /// @{ /** * @brief List of applications user has specified to open errors with. */ class ApplicationList : public QObject { Q_OBJECT public: ApplicationList(QObject *parent = 0); virtual ~ApplicationList(); /** * @brief Load all applications * * @return true if loading succeeded, false if there is problem with * application list. Most probably because of older version settings need * to be upgraded. */ bool LoadSettings(); /** * @brief Save all applications */ void SaveSettings() const; /** * @brief Get the amount of applications in the list * @return The count of applications */ int GetApplicationCount() const; /** * @brief Get specific application's name * * @param index Index of the application whose name to get * @return Name of the application */ const Application& GetApplication(const int index) const; Application& GetApplication(const int index); /** * @brief Return the default application. * @return Index of the default application. */ int GetDefaultApplication() const { return mDefaultApplicationIndex; } /** * @brief Add a new application * * @param app Application to add. */ void AddApplication(const Application &app); /** * @brief Remove an application from the list * * @param index Index of the application to remove. */ void RemoveApplication(const int index); /** * @brief Set application as default application. * @param index Index of the application to make the default one */ void SetDefault(const int index); /** * @brief Remove all applications from this list and copy all applications from * list given as a parameter. * @param list Copying source */ void Copy(const ApplicationList *list); protected: /** * @brief Clear the list * */ void Clear(); /** * @brief Find editor used by default in Windows. * Check if Notepad++ is installed and use it. If not, use Notepad. */ bool FindDefaultWindowsEditor(); private: /** * @brief List of applications * */ QList mApplications; /** * @brief Index of the default application. * */ int mDefaultApplicationIndex; }; /// @} #endif // APPLICATIONLIST_H cppcheck-1.61/gui/checkstatistics.cpp000066400000000000000000000043711217722632100177110ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include "checkstatistics.h" CheckStatistics::CheckStatistics(QObject *parent) : QObject(parent) { Clear(); } void CheckStatistics::AddItem(ShowTypes::ShowType type) { switch (type) { case ShowTypes::ShowStyle: mStyle++; break; case ShowTypes::ShowWarnings: mWarning++; break; case ShowTypes::ShowPerformance: mPerformance++; break; case ShowTypes::ShowPortability: mPortability++; break; case ShowTypes::ShowErrors: mError++; break; case ShowTypes::ShowInformation: mInformation++; break; case ShowTypes::ShowNone: default: qDebug() << "Unknown error type - not added to statistics."; break; } } void CheckStatistics::Clear() { mStyle = 0; mWarning = 0; mPerformance = 0; mPortability = 0; mInformation = 0; mError = 0; } unsigned CheckStatistics::GetCount(ShowTypes::ShowType type) const { switch (type) { case ShowTypes::ShowStyle: return mStyle; case ShowTypes::ShowWarnings: return mWarning; case ShowTypes::ShowPerformance: return mPerformance; case ShowTypes::ShowPortability: return mPortability; case ShowTypes::ShowErrors: return mError; case ShowTypes::ShowInformation: return mInformation; case ShowTypes::ShowNone: default: qDebug() << "Unknown error type - returning zero statistics."; return 0; } } cppcheck-1.61/gui/checkstatistics.h000066400000000000000000000032341217722632100173530ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #ifndef CHECKSTATISTICS_H #define CHECKSTATISTICS_H #include #include "showtypes.h" /// @addtogroup GUI /// @{ /** * A class for check statistics. */ class CheckStatistics : public QObject { public: CheckStatistics(QObject *parent = NULL); /** * @brief Add new checked item to statistics. * * @param type Type of the item to add. */ void AddItem(ShowTypes::ShowType type); /** * @brief Clear the statistics. * */ void Clear(); /** * @brief Return statistics for given type. * * @param type Type for which the statistics are returned. * @return Number of items of given type. */ unsigned GetCount(ShowTypes::ShowType type) const; private: unsigned mStyle; unsigned mWarning; unsigned mPerformance; unsigned mPortability; unsigned mInformation; unsigned mError; }; /// @} #endif // CHECKSTATISTICS_H cppcheck-1.61/gui/checkthread.cpp000066400000000000000000000032521217722632100167630ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include #include "checkthread.h" #include "threadresult.h" #include "cppcheck.h" CheckThread::CheckThread(ThreadResult &result) : mState(Ready), mResult(result), mCppcheck(result, true) { //ctor } CheckThread::~CheckThread() { //dtor } void CheckThread::Check(const Settings &settings) { mCppcheck.settings() = settings; start(); } void CheckThread::run() { mState = Running; QString file; file = mResult.GetNextFile(); while (!file.isEmpty() && mState == Running) { qDebug() << "Checking file" << file; mCppcheck.check(file.toStdString()); emit FileChecked(file); if (mState == Running) file = mResult.GetNextFile(); } if (mState == Running) mState = Ready; else mState = Stopped; emit Done(); } void CheckThread::stop() { mState = Stopping; mCppcheck.terminate(); } cppcheck-1.61/gui/checkthread.h000066400000000000000000000043641217722632100164350ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #ifndef CHECKTHREAD_H #define CHECKTHREAD_H #include #include "cppcheck.h" #include "threadresult.h" class Settings; /// @addtogroup GUI /// @{ /** * @brief Thread to run cppcheck * */ class CheckThread : public QThread { Q_OBJECT public: CheckThread(ThreadResult &result); virtual ~CheckThread(); /** * @brief Set settings for cppcheck * * @param settings settings for cppcheck */ void Check(const Settings &settings); /** * @brief method that is run in a thread * */ void run(); void stop(); signals: /** * @brief cpp checking is done * */ void Done(); void FileChecked(const QString &file); protected: /** * @brief States for the check thread. * Whole purpose of these states is to allow stopping of the checking. When * stopping we say for the thread (Stopping) that stop when current check * has been completed. Thread must be stopped cleanly, just terminating thread * likely causes unpredictable side-effects. */ enum State { Running, /**< The thread is checking. */ Stopping, /**< The thread will stop after current work. */ Stopped, /**< The thread has been stopped. */ Ready, /**< The thread is ready. */ }; /** * @brief Thread's current execution state. */ State mState; ThreadResult &mResult; /** * @brief Cppcheck itself * */ CppCheck mCppcheck; private: }; /// @} #endif // CHECKTHREAD_H cppcheck-1.61/gui/common.cpp000066400000000000000000000026571217722632100160160ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include "common.h" #include #include #include QString GetPath(const QString &type) { QSettings settings; QString path = settings.value(type, "").toString(); if (path.isEmpty()) { // if not set, fallback to last check path hoping that it will be close enough path = settings.value(SETTINGS_LAST_CHECK_PATH, "").toString(); if (path.isEmpty()) // if not set, return user's home directory as the best we can do for now return QDir::homePath(); } return path; } void SetPath(const QString &type, const QString &value) { QSettings settings; settings.setValue(type, value); } cppcheck-1.61/gui/common.h000066400000000000000000000110131217722632100154450ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #ifndef COMMON_H #define COMMON_H #include /// @addtogroup GUI /// @{ /** * QSetting value names */ // Window/dialog sizes #define SETTINGS_WINDOW_MAXIMIZED "Window maximized" #define SETTINGS_WINDOW_WIDTH "Window width" #define SETTINGS_WINDOW_HEIGHT "Window height" #define SETTINGS_LOG_VIEW_WIDTH "Log/View width" #define SETTINGS_LOG_VIEW_HEIGHT "Log/View height" #define SETTINGS_MAINWND_SPLITTER_STATE "Mainwindow/Vertical splitter state" #define SETTINGS_CHECK_DIALOG_WIDTH "Check dialog width" #define SETTINGS_CHECK_DIALOG_HEIGHT "Check dialog height" #define SETTINGS_PROJECT_DIALOG_WIDTH "Project dialog width" #define SETTINGS_PROJECT_DIALOG_HEIGHT "Project dialog height" // Main window settings #define SETTINGS_RESULT_COLUMN_WIDTH "Result column %1 width" #define SETTINGS_TOOLBARS_MAIN_SHOW "Toolbars/ShowStandard" #define SETTINGS_TOOLBARS_VIEW_SHOW "Toolbars/ShowView" #define SETTINGS_TOOLBARS_FILTER_SHOW "Toolbars/ShowFilter" // Show * states #define SETTINGS_SHOW_STYLE "Show style" #define SETTINGS_SHOW_ERRORS "Show errors" #define SETTINGS_SHOW_WARNINGS "Show warnings" #define SETTINGS_SHOW_PERFORMANCE "Show performance" #define SETTINGS_SHOW_INFORMATION "Show information" #define SETTINGS_SHOW_PORTABILITY "Show portability" // Standards support #define SETTINGS_STD_CPP03 "Platform CPP03" #define SETTINGS_STD_CPP11 "Platform CPP11" #define SETTINGS_STD_C89 "Platform C89" #define SETTINGS_STD_C99 "Platform C99" #define SETTINGS_STD_C11 "Platform C11" #define SETTINGS_STD_POSIX "Platform Posix" // Other settings #define SETTINGS_CHECK_FORCE "Check force" #define SETTINGS_CHECK_THREADS "Check threads" #define SETTINGS_SHOW_FULL_PATH "Show full path" #define SETTINGS_SHOW_NO_ERRORS "Show no errors message" #define SETTINGS_SHOW_DEBUG_WARNINGS "Show debug warnings" #define SETTINGS_SAVE_ALL_ERRORS "Save all errors" #define SETTINGS_SAVE_FULL_PATH "Save full path" #define SETTINGS_APPLICATION_NAMES "Application names" #define SETTINGS_APPLICATION_PATHS "Application paths" #define SETTINGS_APPLICATION_PARAMS "Application parameters" #define SETTINGS_APPLICATION_DEFAULT "Default Application" #define SETTINGS_LANGUAGE "Application language" #define SETTINGS_GLOBAL_INCLUDE_PATHS "Global include paths" #define SETTINGS_INLINE_SUPPRESSIONS "Inline suppressions" #define SETTINGS_INCONCLUSIVE_ERRORS "Inconclusive errors" #define SETTINGS_MRU_PROJECTS "MRU Projects" #define SETTINGS_SHOW_ERROR_ID "Show error Id" // The maximum value for the progress bar #define PROGRESS_MAX 1024.0 #define SETTINGS_CHECKED_PLATFORM "Checked platform" #define SETTINGS_LAST_CHECK_PATH "Last check path" #define SETTINGS_LAST_PROJECT_PATH "Last project path" #define SETTINGS_LAST_RESULT_PATH "Last result path" #define SETTINGS_LAST_SOURCE_PATH "Last source path" #define SETTINGS_LAST_INCLUDE_PATH "Last include path" #define SETTINGS_LAST_APP_PATH "Last application path" /** * @brief Obtains the path of specified type * Returns the path of specified type if not empty. Otherwise returns last check * path if valid or user's home directory. * @param type Type of path to obtain * @return Best path fo provided type */ QString GetPath(const QString &type); /** * @brief Stores last used path of specified type * Stores provided path as last used path for specified type. * @param type Type of the path to store * @param value Path to store */ void SetPath(const QString &type, const QString &value); /// @} #endif cppcheck-1.61/gui/cppcheck-gui.rc000066400000000000000000000002661217722632100167040ustar00rootroot00000000000000// Include command line program's resource file containing version info #include "../cli/version.rc" // GUI Icon IDI_ICON1 ICON DISCARDABLE "cppcheck.ico" cppcheck-1.61/gui/cppcheck.ico000066400000000000000000000611761217722632100162770ustar00rootroot00000000000000 00h ( 00 h^"00 %'  nM h^(0`p 32333 0#3333p`#33333#p#33333330p333333332 p333333333333333332333332333330#333330p33332333333 p3303333332p#333332p3333330p333333 3333330sp333333"wpp#333333 pp|3333333333333 |pppp#33332  3330p|p32 3 |wppwGpppp pp p p p @ p 0  @p p p pp w wpwpww@ p  @ p p| p| pw|p|Lpwtpp???~???>A3B5D6F8I:K<L=QATCWEaMeQjUlVnXpYs\v^ya|c}dAAAFFFIIINNNPPPTTTYYY^^^nAApBBuEExGGzHH}JJ```eeehhhoooqqquuuzzz}}}LLNNPPSSTTUUXX[[]]^^``bbccddiikkmmooppssuuwwyy{{||~~fhjmpstwxz|~ځ݂ބⅅ戈銊싋/ P6pLbx1Qq,/KPip1Qq/-P?pRcv1Qqϑܱ/Pp!&,>X1qQq@pp6C|)b8%|%``CJ Zj7*l7[lr6dh5*A`Wr@YdAl>kaX=|*ca55a Im]d4$nKe8~)8g9mr __KAbj< C|Xf .r I+7[ lB ib @Jd;!r~sz~r\a?K*/3ML3 C~~!X9#||@"Rt?#8^JH,uTRV}HiZ?B1y,%Kl.Nxmaf9nCEy{A3T*q[k;Ir-"~+Q0z%=k>I*u?t@#6dW?s,GsCy(znnI @znn+,oDz?/|+0~}l?xE|+1~|3?G|+3~JQ*?G|+3AVwA?G|+3~!wuC*Gq)3rVH##G ##.~"#3 %##ytHP{,P?uvB'{0HTy?&y{0yrL~/00S00{-00P00)+zznGBzz|zzm3Czzz!(U??G|+3~nF2'??G|+3~QIlN??G|+3~IM%??G|+3~!UO.%R??U0|+V-~"UOmnP@C}B!OM'LP.COF.qI,OTuywtRL-@onC+ !.JsGwGwGwGwGw?GwGwGwGwGwGwGwGwGw?GwGw?GwGwGwGwGwGw~Gw??Gw?Gw2 :1 ;2 ?4%!!)"".##)&&-$$*)),++0 4""2$$9##8$$1**5((4--:**=++9,,=,, 1-$30)42+74-64*84100:11<222;96=;F**F--I--L--P//A33D11I22M22M44@88A>>E<<P00T22R77U77\66]99`99a<<f<<h==B5B6D7H;J<M=M>RBUDXG[I^K_L8B@?FEaMhSkUmWoYpYs\ya|c~eAAAGCCEEEICCIEELFFEHGFIHIIIMHHILKIOMNNNRNNTOOKQOPQQVRRVUUUXW[]\]]]kAAnAApBBvEEyHHKK`]]^a_bbbfeennnpoorqqvuuyyy}}}MMOOPPTTVVXXZZ]]``bbcceehhkkmmqqrrttvvxxyy||~~hnpvxy}ہ݃鉉싋/ P6pLbx1Qq,/KPip1Qq/-P?pRcv1Qqϑܱ/Pp!&,>X1qQq:~aX9 ^4UVr3g {gua] hdwRfvbi0fd{rY[ 5_zTijZ9ic@=PL/o3\S9/A`ZW"CBo7HT2<lGWk8#+.KN#7yP *;Q)mF+%+>(,Ikn8ttO/I{|//O/I{|8EEO}'|8D6+BC}7J8p.$&7xx?xx|3c3qssxs( 1,,E++F..H//N00Q::W::TF XH ]LTHZL*SK+TL3RK:UO6WP:VQgSiUmWr[s\zaZEE\FFSOOTPPoBBjKKqJJwKKzII{MM|NNbPPfRRcTTnSSnUUj^^o^^qQQ{QQJa\Tb_Uca[ge_libbbgccmcciiiqbbreeujjvllktrrppuqqvttyww|wwqyw~~~VVZZ^^mmyyqy~}܂戈 =1[Qyq/"P0p=LYgx1Qq&/@PZpt1Qq/&PAp[tϩ1Qq/P"p0>M[iy1Qqұ/Pp  >1\Qzq/Pp!+6@IZ1pQq/ P6pLbx1Qq,/KPip1Qq/-P?pRcv1Qqϑܱ/Pp!&,>X1qQq/0NJ P KONOO:5ONOOI  LONJOOH*BC!-HOOLUF<)D@K1?TW+#$=A.+WW6#WV9A"WV9CSEGS(WW*<3;3>(W,,7&RS%A%R43''! '<?G]](0` [6R*!Z )cOxj/%%WF{WEM k E7g{b+" C*"~ewI: 9<( lVu^%{!WEso?30d D6tlVf S<0}dt`MB5nm8--diTaM&%fz`M V8 L=w{mW#I= nXh-$!.%h~s\1'X) TC~yTC OWeQ|c7, bC5pYum  i,#jzG9 ;lt"Uw_fQjAkVo4*!8_{oH+K<|bN^7'4C''@&&3;B5ug1' [55[[zzځ߄ᅅ݃{{kkj?? tg.%lxQA GA pBBفuuNNa::Z55MMddᅅ܂h== Ix`xF8LG.mm}JJ!J,,ww{HHq9bOoX1' [8!!zzKK )!_4tt닋`88. I;|c3) b%ppvv .Y55yy,~:.p}d<0mMPPoBB+x qqm@@' _)!lVA3u*ބ;##2KKss m-oH!4d3LLqq f7 cc^^ @) /{,B, Vsscc 5  !@zHH8!!BMM/3݃XX2333+ @߄NN=$$BTT3X44쌌LL@߄NN=$$BTT3i>>vFF@߄NN=$$BTT3xGGoBB55hNN=$$553 55jTT3855LLj??yNN=$$TT3|IIm@@ ]]bbbb}}oobbbbT11XXbbbbmmbbbbU33nAAtEELL-戈MM`99{II銊}JJ+ރ~KKA&&ㆆSSU``[),,[[_88,, ',,__V33,+ g zz__%9  rNN=$$`TT3=__kkOY SSc;;$@߄NN=$$BTT3<##||0ㆆOO$@߄NN=$$BTT3hjjW33!J,,OO$@߄NN=$$BTT3D((ہ``giccOO$@߄NN=$$BTT3?d;;牉O..c U[66싋OO$@b::-Bi>>%ud;;ᅅځO.. xV33OO$<?uM..qqㆆ]]D((  @&&UUㆆW33$<EE)=EE&LO//ii~~艉ꊊㆆۂ}}mmLL;## #w M..b99qBB~JJxGGnAA\66B''%w<%G{}K/GwGwGwGw?GwGwGwGwGw?Gw?GwGwGwGwGw?Gw`<GwGwGwGwpGw0Gw8GwGwGwGwGw7Gw?Gw?Gw?GwGwGwGwGwGwGwGw?Gw?Gw?Gw?Gw?Gw?Gw?GwGw?GwGw( @ a 84!bNJ; K8#_Lh) &f C6npF8F[ <0pqZ&"1!s\zn6+0`M~y^K3)x`kV~>@3opY1' }hS}d1'. oYxmW1'U:QAzXGc G ( i) >1z|c"!M*"fyUD _7VhfQ* w{bjT!I%E((f<1 kT@&&zzj?? 7 ``qq )/%hvM=1'ttqq A=$$߃^77v 7B@3V=*_@%%WW ӝ]]wFF&  dJA TTnAAq+)P//ei>> γjjZ55\ +,T22eoBB $vvM--Q9,T22o&oBB *||G**N=,T22oBB 'yyJ++OYL--qqyyssMM ݷkkss݃vv``!!ssP//TY`99cc艉{{* ``b::c? D((h== KK,xFFyHHF))0u5W,T225,.FoBB 75A닋cc  eeZ55c+,T22eoBB VV}}137.Z55c+,T22eoBB דWWbb e1/` ШccZ55c* )c6 Vؚ[[[[B'' =$$ZZ싋E))ct2 VY#$MMeessxxttmm``OOF)) 0K "(&  ^4??00p x!0!!!??(  9#lV@3J VDr[ r[x`'gSy2(8mP@+"HHL=cO ~0.)2(}q%("*PP[[zHHf<<v!rK<_W33yy L*]]Z zadP$ `99uEE7 f|X443V^>%%2a>%%zHH%n@&&R@&&avFF&-ZZ戈mm戈oBBK,,8!!  K,, u K,, t܂pBBoBB.@&&2a@&&1戈<##;""ᅅ( %H  {Q00vEEqCCP// 6A?AAAAAAAAAAAAAAAcppcheck-1.61/gui/cppcheck_de.ts000066400000000000000000001661551217722632100166260ustar00rootroot00000000000000 About About Cppcheck Über Cppcheck Version %1 Version %1 Cppcheck - A tool for static C/C++ code analysis. Cppcheck - Ein Werkzeug zur statischen C/C++-Code-Analyse. Copyright © 2007-2013 Daniel Marjamäki and cppcheck team. Copyright © 2007-2013 Daniel Marjamäki und das Cppcheck-Team. This program is licensed under the terms of the GNU General Public License version 3 Dieses Programm ist unter den Bedingungen der GNU General Public License Version 3 lizenziert Visit Cppcheck homepage at %1 Besuchen Sie die Cppcheck-Homepage unter %1 ApplicationDialog Add an application Anwendung hinzufügen Here you can add an application that can open error files. Specify a name for the application, the application executable and command line parameters for the application. The following texts in parameters are replaced with appropriate values when application is executed: (file) - Filename containing the error (line) - Line number containing the error (message) - Error message (severity) - Error severity Example opening a file with Kate and make Kate scroll to the correct line: Executable: kate Parameters: -l(line) (file) Hier können Sie Anwendungen hinzufügen, die Codedateien öffnen können. Geben Sie den Namen der Anwendung, deren ausführbare Datei und Kommandozeilenparameter für die Ausführung an. Die folgenden Texte in Parametern werden durch die passenden Werte ersetzt, wenn die Anwendung ausgeführt wird: (file) - Name der Datei, die den Fehler enthält (line) - Zeile, die den Fehler enthält (message) - Fehlermeldung (severity) - Schweregrad des Fehlers Beispiel: Öffnen einer Datei mit Kate, automatisch zur korrekten Zeile scrollen: Ausführbare Datei: kate Parameter: -l(line) (file) &Name: &Name: &Executable: &Ausführbare Datei: &Parameters: &Parameter: Browse Suchen Executable files (*.exe);;All files(*.*) Ausführbare Dateien (*.exe);;Alle Dateien(*.*) Select viewer application Anzeigeanwendung auswählen Cppcheck Cppcheck You must specify a name, a path and optionally parameters for the application! Sie müssen einen Namen, einen Pfad und ggf. Parameter für die Anwendung angeben! FileViewDialog Could not find the file: %1 Konnte die Datei nicht finden: %1 Cppcheck Cppcheck Could not read the file: %1 Konnte die Datei nicht lesen: %1 LogView Checking Log Untersuchungs-Log Clear Löschen Save Log Speichere Log Text files (*.txt *.log);;All files (*.*) Textdateien (*.txt *.log);;Alle Dateien(*.*) Cppcheck Cppcheck Could not open file for writing: "%1" Datei kann nicht zum Schreiben geöffnet werden: "%1" MainWindow Cppcheck Cppcheck Standard Standard &File &Datei &View &Ansicht &Toolbars &Symbolleisten &Check &Prüfen C++ standard C++-Standard C standard C-Standard &Edit &Bearbeiten &License... &Lizenz... A&uthors... &Autoren... &About... Ü&ber... &Files... &Dateien... Check files Prüfe Dateien Ctrl+F Strg+F &Directory... &Verzeichnis... Check directory Prüfe Verzeichnis Ctrl+D Strg+D &Recheck files Dateien &neu prüfen Ctrl+R Strg+R &Stop &Stoppen Stop checking Prüfung abbrechen Esc Esc &Save results to file... &Ergebnisse in Datei speichern... Ctrl+S Strg+S &Quit &Beenden &Clear results Ergebnisse &löschen &Preferences &Einstellungen Errors Fehler Show errors Zeige Fehler Show S&cratchpad... Zeige Schmierzettel Warnings Warnungen Show warnings Zeige Warnungen Performance warnings Performance-Warnungen Show performance warnings Zeige Performance-Warnungen Show &hidden Zeige &versteckte Information Information Show information messages Zeige Informationsmeldungen Portability Portabilität Show portability warnings Zeige Portabilitätswarnungen &Filter &Filter Filter results Gefilterte Ergebnisse Windows 32-bit ANSI Windows 32-bit, ANSI Windows 32-bit Unicode Windows 32-bit, Unicode Unix 32-bit Unix 32-bit Unix 64-bit Unix 64-bit Windows 64-bit Windows 64-bit Platforms Plattformen C++11 C++11 C99 C99 Posix Posix C11 C11 C89 C89 C++03 C++03 &Check all Alle &auswählen Filter Filter &Uncheck all Alle a&bwählen Collapse &all Alle &reduzieren &Expand all Alle &erweitern &Standard &Standard Standard items Standardeinträge Toolbar Symbolleiste &Categories &Kategorien Error categories Fehler-Kategorien &Open XML... Öffne &XML... Open P&roject File... Pr&ojektdatei öffnen... &New Project File... &Neue Projektdatei... &Log View &Loganzeige Log View Loganzeige C&lose Project File Projektdatei &schließen &Edit Project File... Projektdatei &bearbeiten... &Statistics &Statistik &Contents &Inhalte Categories Kategorien Style warnings Stilwarnungen Show style warnings Zeige Stilwarnungen Open the help contents Öffnet die Hilfe-Inhalte F1 F1 &Help &Hilfe Select directory to check Verzeichnis zum Überprüfen auswählen No suitable files found to check! Keine passenden Dateien zum Überprüfen gefunden! Quick Filter: Schnellfilter: Found project file: %1 Do you want to load this project file instead? Gefundene Projektdatei: %1 Möchten Sie stattdessen diese öffnen? Found project files from the directory. Do you want to proceed checking without using any of these project files? Projektdatei im Verzeichnis gefunden. Möchten Sie die Prüfung wirklich durchführen, ohne eine Projektdatei zu verwenden? License Lizenz Authors Autoren XML files version 2 (*.xml);;XML files version 1 (*.xml);;Text files (*.txt);;CSV files (*.csv) XML-Dateien Version 2 (*.xml);;XML-Dateien Version 1 (*.xml);;Textdateien (*.txt);;CSV-Dateien (*.csv) Save the report file Speichert die Berichtdatei XML files (*.xml) XML-Dateien (*.xml) There was a problem with loading the editor application settings. This is probably because the settings were changed between the Cppcheck versions. Please check (and fix) the editor application settings, otherwise the editor program might not start correctly. Beim Laden der Editor-Anwendungseinstellungen trat ein Problem auf. Dies wurde vermutlich durch einen Wechsel der Cppcheck-Version hervorgerufen. Bitte prüfen (und korrigieren) Sie die Einstellungen, andernfalls könnte die Editor-Anwendung nicht korrekt starten. You must close the project file before selecting new files or directories! Sie müssen die Projektdatei schließen, bevor Sie neue Dateien oder Verzeichnisse auswählen! Select files to check Dateien zum Überprüfen auswählen Current results will be cleared. Opening a new XML file will clear current results.Do you want to proceed? Aktuelle Ergebnisse werden gelöscht. Das Einlesen einer XML-Datei löscht die aktuellen Ergebnisse. Fortfahren? Open the report file Berichtdatei öffnen Checking is running. Do you want to stop the checking and exit Cppcheck?. Prüfung läuft. Möchten Sie die Prüfung abbrechen und Cppcheck beenden? XML files version 1 (*.xml) XML-Dateien Version 1 (*.xml) XML files version 2 (*.xml) XML-Dateien Version 2 (*.xml) Text files (*.txt) Textdateien (*.txt) CSV files (*.csv) CSV-Dateien (*.csv) Cppcheck - %1 Cppcheck - %1 Project files (*.cppcheck);;All files(*.*) Projektdateien (*.cppcheck);;Alle Dateien(*.*) Select Project File Projektdatei auswählen Project: Projekt: Select Project Filename Projektnamen auswählen No project file loaded Keine Projektdatei geladen The project file %1 could not be found! Do you want to remove the file from the recently used projects -list? Die Projektdatei %1 konnte nicht gefunden werden! Möchten Sie die Datei von der Liste der zuletzt benutzten Projekte entfernen? Finnish Finnisch English Englisch Chinese (Simplified) Chinesisch (vereinfacht) Dutch Niederländisch French Französisch Italian Italienisch Korean Koreanisch Spanish Spanisch Swedish Schwedisch German Deutsch Russian Russisch Japanese Japanisch Serbian Serbisch Cppcheck GUI. Syntax: cppcheck-gui [OPTIONS] [files or paths] Options: -h, --help Print this help -p <file> Open given project file and start checking it -l <file> Open given results xml file -d <directory> Specify the directory that was checked to generate the results xml specified with -l -v, --version Show program version Cppcheck-GUI Syntax: cppcheck-gui [OPTIONEN] [Dateien oder Pfade] Optionen: -h, --help Gibt diese Hilfeinformationen aus -p <Datei> Öffnet das angegebene Projekt und startet die Prüfung -l <Datei> Öffnet die angegenbene XML-Resultatdatei -d <Verzeichnis> Spezifiziert das Verzeichnis, dass überprüft wurde, als die mit -l angegebene Datei erstellt wurde -v, --version Zeigt die Programmversion Cppcheck GUI - Command line parameters Cppcheck GUI - Kommandozeilenparameter Platforms Built-in Built-In Unix 32-bit Unix 32-bit Unix 64-bit Unix 64-bit Windows 32-bit ANSI Windows 32-bit, ANSI Windows 32-bit Unicode Windows 32-bit, Unicode Windows 64-bit Windows 64-bit Project Cppcheck Cppcheck Could not read the project file. Projektdatei konnte nicht gelesen werden. Could not write the project file. Projektdatei konnte nicht geschrieben werden. ProjectFile Project File Projektdatei Project Projekt Root: Wurzel: Paths: Pfade: Add... Hinzufügen... Edit Bearbeiten Remove Entfernen Includes Includes Include directories: Include-Verzeichnisse: Up Auf Down Ab Exclude Ausschließen Defines: Definitionen: ProjectFileDialog Project file: %1 Projektdatei: %1 Select include directory Wähle Include-Verzeichnisse Select a directory to check Wähle zu prüfendes Verzeichnis Select directory to ignore Wähle zu ignorierendes Verzeichnis QDialogButtonBox OK OK Cancel Abbrechen Close Schließen Save Speichern QObject Unknown language specified! Unbekannte Sprache angegeben! Language file %1 not found! Sprachdatei %1 nicht gefunden! Failed to load translation for language %1 from file %2 Die Übersetzungen der Sprache %1 konnten nicht aus der Datei %2 geladen werden ResultsTree File Datei Severity Schweregrad Line Zeile Summary Zusammenfassung Undefined file Undefinierte Datei [Inconclusive] [unklar] debug Debug Copy filename Dateiname kopieren Copy full path Vollständigen Pfad kopieren Copy message Meldung kopieren Copy message id Meldungs-Id kopieren Hide Verstecken Hide all with id Verstecke alle mit gleicher ID Cppcheck Cppcheck No editor application configured. Configure the editor application for Cppcheck in preferences/Applications. Keine Editor-Anwendung eingestellt. Konfigurieren Sie diese unter Einstellungen/Anwendungen. No default editor application selected. Please select the default editor application in preferences/Applications. Keine Standard-Editor-Anwendung eingestellt. Bitte wählen Sie eine Standardanwendung unter Einstellungen/Anwendungen. Could not find the file! Datei konnte nicht gefunden werden! Could not start %1 Please check the application path and parameters are correct. %1 konnte nicht gestartet werden. Bitte überprüfen Sie ob der Pfad und die Parameter der Anwendung richtig eingestellt sind. Could not find file: %1 Please select the directory where file is located. Datei konnte nicht gefunden werden: %1 Bitte wählen Sie das Verzeichnis, in dem sich die Datei befindet. Select Directory Wähle Verzeichnis Id Id style Stil error Fehler warning Warnung performance Performance portability Portabilität information Information ResultsView %p% (%1 of %2 files checked) %p% (%1 von %2 Dateien geprüft) Cppcheck Cppcheck No errors found. Keine Fehler gefunden. Errors were found, but they are configured to be hidden. To toggle what kind of errors are shown, open view menu. Es wurden Fehler gefunden, aber sie sind so konfiguriert, ausgeblendet zu werden. Legen Sie unter dem Menü Ansicht fest, welche Arten von Fehlern angezeigt werden sollen. Failed to read the report. Lesen des Berichts fehlgeschlagen. Summary Zusammenfassung Message Meldung Id Id No errors found, nothing to save. Keine Fehler gefunden, nichts zu speichern. Failed to save the report. Der Bericht konnte nicht speichern werden. Results Berichte ScratchPad Scratchpad Schmierzettel filename Dateiname Check Prüfe Settings Preferences Einstellungen General Allgemein Include paths: Include-Pfade: Add... Hinzufügen... Number of threads: Anzahl der Threads: Ideal count: Ideale Anzahl: Force checking all #ifdef configurations Erzwinge Prüfung aller #ifdef-Konfigurationen Show full path of files Vollständigen Dateipfad anzeigen Show "No errors found" message when no errors found "Keine Fehler gefunden"-Meldung anzeigen, wenn keine Fehler gefunden werden Display error Id in column "Id" Zeige Meldungs-Id in Spalte "Id" Enable inline suppressions Inline-Fehlerunterdrückung aktivieren Paths Pfade Edit Bearbeiten Remove Entfernen Applications Anwendungen Edit... Bearbeiten... Set as default Als Standard festlegen Reports Berichte Save all errors when creating report Alle Fehler beim Erstellen von Berichten speichern Save full path to files in reports Vollständigen Dateipfad in Berichten speichern Language Sprache Advanced Erweitert &Show inconclusive errors &Unklare Fehler anzeigen S&how internal warnings in log &Interne Warnungen im Log anzeigen SettingsDialog N/A kA Add a new application Neue Anwendung hinzufügen Modify an application Anwendung ändern [Default] [Standard] Select include directory Wähle Include-Verzeichnis StatsDialog Statistics Statistik Project Projekt Project: Projekt: Paths: Pfade: Include paths: Include-Pfade: Defines: Definitionen: Previous Scan Vorherige Prüfung Path Selected: Ausgewählte Pfade: Number of Files Scanned: Anzahl der geprüften Dateien: Scan Duration: Prüfungsdauer: Errors: Fehler: Warnings: Warnungen: Stylistic warnings: Stilwarnungen: Portability warnings: Portabilitätswarnungen: Performance issues: Performance-Probleme: Information messages: Informationsmeldungen: Copy to Clipboard In die Zwischenablage kopieren 1 day 1 Tag %1 days %1 Tage 1 hour 1 Stunde %1 hours %1 Stunden 1 minute 1 Minute %1 minutes %1 Minuten 1 second 1 Sekunde %1 seconds %1 Sekunden 0.%1 seconds 0,%1 Sekunden and und Project Settings Projekteinstellungen Paths Pfade Include paths Include-Pfade Defines Definitionen Path selected Gewählte Pfade Number of files scanned Anzahl geprüfter Dateien Scan duration Prüfungsdauer Errors Fehler Warnings Warnungen Style warnings Stilwarnungen Portability warnings Portabilitätswarnungen Performance warnings Performance-Warnungen Information messages Informationsmeldungen ThreadResult %1 of %2 files checked %1 von %2 Dateien geprüft TranslationHandler Failed to change the user interface language: %1 The user interface language has been reset to English. Open the Preferences-dialog to select any of the available languages. Wechsel der Sprache der Benutzeroberfläche fehlgeschlagen: %1 Die Sprache wurde auf Englisch zurückgesetzt. Öffnen Sie den Einstellungen-Dialog um eine verfügbare Sprache auszuwählen. Cppcheck Cppcheck TxtReport inconclusive unklar cppcheck-1.61/gui/cppcheck_es.ts000066400000000000000000001633621217722632100166420ustar00rootroot00000000000000 About About Cppcheck Sobre Cppcheck Version %1 Version %1 Cppcheck - A tool for static C/C++ code analysis. Cppcheck - Utilidad para análisis estático de código. Copyright © 2007-2013 Daniel Marjamäki and cppcheck team. Copyright © 2007-2012 Daniel Marjamäki and cppcheck team. Copyright © 2007-2010 Daniel Marjamäki y el equipo de cppcheck. This program is licensed under the terms of the GNU General Public License version 3 Estre programa está licenciado bajo los términos de GNU General Public License versión 3 Visit Cppcheck homepage at %1 Visita Cppcheck en %1 ApplicationDialog Add an application Añade una aplicación Here you can add an application that can open error files. Specify a name for the application, the application executable and command line parameters for the application. The following texts in parameters are replaced with appropriate values when application is executed: (file) - Filename containing the error (line) - Line number containing the error (message) - Error message (severity) - Error severity Example opening a file with Kate and make Kate scroll to the correct line: Executable: kate Parameters: -l(line) (file) &Name: &Executable: &Parameters: Browse Buscar Executable files (*.exe);;All files(*.*) Ficheros ejecutables (*.exe);;Todos los ficheros(*.*) Select viewer application Selecciona la aplicación para visualizar Cppcheck Cppcheck You must specify a name, a path and optionally parameters for the application! FileViewDialog Could not find the file: %1 No se ha encontrado el fichero: %1 Cppcheck Cppcheck Could not read the file: %1 No se ha podido leer el fichero: %1 LogView Checking Log Comprobando log Clear Limpiar Save Log Text files (*.txt *.log);;All files (*.*) Cppcheck Cppcheck Could not open file for writing: "%1" MainWindow Cppcheck Cppcheck &File &Fichero &View &Ver &Toolbars &Herramientas &Help &Ayuda &Check &Comprobar C++ standard C standard &Edit &Editar Standard Estándar Categories Categorías &License... &licencia... A&uthors... A&utores... &About... &sobre... &Files... &Ficheros... Check files Ctrl+F Ctrl+F &Directory... &Carpeta... Check directory Ctrl+D Ctrl+D &Recheck files &Volver a revisar ficheros Ctrl+R Ctrl+R &Stop &Parar Stop checking Esc Esc &Save results to file... &Guardar los resultados en el fichero... Ctrl+S Ctrl+S &Quit &Salir &Clear results &Limpiar resultados &Preferences &Preferencias Style warnings Estilos de advertencias Show style warnings Mostrar estilos de advertencias Errors Show errors Show S&cratchpad... Information Show information messages Portability Show portability warnings &Filter Filter results Windows 32-bit ANSI Windows 32-bit Unicode Unix 32-bit Unix 64-bit Windows 64-bit Platforms C++11 C99 Posix C11 C89 C++03 &Check all &Seleccionar todo Filter &Uncheck all &Deseleccionar todo Collapse &all Contraer &todo &Expand all &Expandir todo &Standard &Estándar Standard items Elementos estándar &Contents &Contenidos Open the help contents Abrir la ayuda de contenidos F1 F1 Toolbar Barra de herramientas &Categories &Categorías Error categories Categorías de error &Open XML... &Abrir XML... Open P&roject File... Abrir P&royecto... &New Project File... &Nuevo Proyecto... &Log View &Vista de log Log View Vista de log C&lose Project File C&errar Proyecto &Edit Project File... &Editar Proyecto... &Statistics &Estadísticas Warnings Advertencias Show warnings Mostrar advertencias Performance warnings Ajustar advertencias Show performance warnings Mostrar ajustes de advertencias Show &hidden Mostrar &ocultas There was a problem with loading the editor application settings. This is probably because the settings were changed between the Cppcheck versions. Please check (and fix) the editor application settings, otherwise the editor program might not start correctly. No suitable files found to check! ¡No se han encontrado ficheros para comprobar! You must close the project file before selecting new files or directories! ¡Tienes que cerrar el fichero de proyecto antes de seleccionar nuevos ficheros o carpetas! Select directory to check Selecciona una carpeta para comprobar XML files (*.xml) Ficheros XML(*.xml) Open the report file Abrir informe Checking is running. Do you want to stop the checking and exit Cppcheck?. El proceso de comprobación está en curso. ¿Quieres parar la comprobación y salir del Cppcheck?. License Licencia Authors Autores XML files version 2 (*.xml);;XML files version 1 (*.xml);;Text files (*.txt);;CSV files (*.csv) Save the report file Guardar informe Quick Filter: Select files to check Selecciona ficheros para comprobar Found project file: %1 Do you want to load this project file instead? Found project files from the directory. Do you want to proceed checking without using any of these project files? Current results will be cleared. Opening a new XML file will clear current results.Do you want to proceed? XML files version 1 (*.xml) XML files version 2 (*.xml) Text files (*.txt) Ficheros de texto (*.txt) CSV files (*.csv) Ficheros CVS (*.cvs) Cppcheck - %1 Cppcheck - %1 Project files (*.cppcheck);;All files(*.*) Ficheros de proyecto (*.cppcheck;;Todos los ficheros (*.*) Select Project File Selecciona proyecto Project: Proyecto: Select Project Filename Selecciona el nombre del proyecto No project file loaded No hay ningún proyecto cargado The project file %1 could not be found! Do you want to remove the file from the recently used projects -list? English English Dutch Holandés Chinese (Simplified) Finnish Finés French Italian Korean Spanish Swedish Sueco German Alemán Russian Ruso Japanese Japonés Serbian Servio Cppcheck GUI. Syntax: cppcheck-gui [OPTIONS] [files or paths] Options: -h, --help Print this help -p <file> Open given project file and start checking it -l <file> Open given results xml file -d <directory> Specify the directory that was checked to generate the results xml specified with -l -v, --version Show program version Cppcheck GUI - Command line parameters Platforms Built-in Unix 32-bit Unix 64-bit Windows 32-bit ANSI Windows 32-bit Unicode Windows 64-bit Project Cppcheck Cppcheck Could not read the project file. No se ha podido leer el fichero. Could not write the project file. No se ha podido escribir el fichero de proyecto. ProjectFile Project File Fichero de proyecto Project Proyecto Root: Paths: Rutas: Add... Añadir... Edit Remove Includes Include directories: Up Down Exclude Defines: Definiciones: ProjectFileDialog Project file: %1 Fichero de proyecto: %1 Select include directory Selecciona una carpeta para incluir Select a directory to check Select directory to ignore QDialogButtonBox OK Cancel Close Cerrar Save QObject Unknown language specified! Language file %1 not found! ¡Fichero de idioma %1 no encontrado! Failed to load translation for language %1 from file %2 Fallo al cargar la traducción para el idioma %1 desde el fichero %2 ResultsTree File Fichero Severity Importancia Line Línea Summary Resumen Undefined file Fichero no definido [Inconclusive] portability information debug Copy filename Copia nombre Copy full path Copia ruta Copy message Copia mensaje Copy message id Hide Oculta Hide all with id Cppcheck Cppcheck No editor application configured. Configure the editor application for Cppcheck in preferences/Applications. Configure the text file viewer program in Cppcheck preferences/Applications. Configura el programa para ver ficheros en Cppcheck preferencias/Aplicaciones. No default editor application selected. Please select the default editor application in preferences/Applications. Could not find the file! ¡No se ha encontrado el fichero! Could not start %1 Please check the application path and parameters are correct. No se ha podido ejecutar %1 Por favor comprueba que la ruta a la aplicación y los parámetros son correctos. Could not find file: %1 Please select the directory where file is located. No se ha encontrado el fichero: %1 Por favor selecciona la carpeta donde se encuentra. Select Directory Selecciona carpeta Id style estilo error error warning advertencia performance ajuste ResultsView Results Resultados No errors found, nothing to save. No se han encontrado errores, nada que guardar. Failed to save the report. Error al guardar el informe. %p% (%1 of %2 files checked) Cppcheck Cppcheck No errors found. No se han encontrado errores. Errors were found, but they are configured to be hidden. To toggle what kind of errors are shown, open view menu. Se han encontrado errores, pero están configurados para que no se muestren. Para cambiar el tipo de comportamiento, abrir el menú vista. Failed to read the report. Error al leer el informe. Summary Resumen Message Mensaje Id ScratchPad Scratchpad filename Check Settings Preferences Preferencias General General Ideal count: Force checking all #ifdef configurations Display error Id in column "Id" Enable inline suppressions Paths Include paths: Incluye rutas: Add... Añadir... Edit... Set as default Language Advanced &Show inconclusive errors S&how internal warnings in log Number of threads: Número de hilos: Show full path of files Mostrar la ruta completa de los ficheros Show "No errors found" message when no errors found Mostrar el mensaje "No se han encontrado errores" Edit Remove Applications Aplicaciones Reports Informes Save all errors when creating report Guardar todos los errores cuando se cree el informe Save full path to files in reports Guardar la ruta completa en los ficheros de informes SettingsDialog N/A Add a new application Añade una nueva aplicación Modify an application Modificar aplicación [Default] Select include directory Seleccionar carpeta incluida StatsDialog Statistics Estadísticas Project Proyecto Project: Proyecto: Paths: Rutas: Include paths: Incluye rutas: Defines: Definiciones: Previous Scan Revisión anterior Path Selected: Ruta seleccionada: Number of Files Scanned: Número de ficheros revisados: Scan Duration: Tiempo de revisión: Errors: Errores: Warnings: Advertencias: Stylistic warnings: Advertencias de estilo: Portability warnings: Performance issues: Problemas de rendimiento: Information messages: Copy to Clipboard Copiar al portapapeles 1 day %1 days 1 hour %1 hours 1 minute %1 minutes 1 second %1 seconds 0.%1 seconds and Project Settings Paths Include paths Defines Path selected Number of files scanned Scan duration Errors Warnings Advertencias Style warnings Estilos de advertencias Portability warnings Performance warnings Ajustar advertencias Information messages ThreadResult %1 of %2 files checked TranslationHandler Failed to change the user interface language: %1 The user interface language has been reset to English. Open the Preferences-dialog to select any of the available languages. Cppcheck Cppcheck TxtReport inconclusive cppcheck-1.61/gui/cppcheck_fi.ts000066400000000000000000001640121217722632100166220ustar00rootroot00000000000000 About About Cppcheck Tietoa ohjelmasta Cppcheck Version %1 Versio %1 Cppcheck - A tool for static C/C++ code analysis. Cppcheck - Työkalu C/C++ koodin staattiseen analysointiin. Copyright © 2007-2013 Daniel Marjamäki and cppcheck team. Copyright © 2007-2012 Daniel Marjamäki and cppcheck team. Copyright (C) 2007-2009 Daniel Marjamäki ja cppcheck tiimi. This program is licensed under the terms of the GNU General Public License version 3 Tämä ohjelma on lisensoitu GNU General Public lisenssin version 3 alaisuuteen Visit Cppcheck homepage at %1 Cppcheckin kotisivu löytyy osoitteesta %1 ApplicationDialog Add an application Lisää uusi ohjelma Here you can add an application that can open error files. Specify a name for the application, the application executable and command line parameters for the application. The following texts in parameters are replaced with appropriate values when application is executed: (file) - Filename containing the error (line) - Line number containing the error (message) - Error message (severity) - Error severity Example opening a file with Kate and make Kate scroll to the correct line: Executable: kate Parameters: -l(line) (file) &Name: &Executable: &Parameters: Browse Selaa Executable files (*.exe);;All files(*.*) Suoritettavat tiedostot (*.exe);;Kaikki tiedostot(*.*) Select viewer application Valitse ohjelma jolla avata virhetiedosto Cppcheck Cppcheck You must specify a name, a path and optionally parameters for the application! FileViewDialog Could not find the file: %1 Could not find the file: Tiedostoa %1 ei löytynyt Cppcheck Cppcheck Could not read the file: %1 Tiedoston %1 lukeminen epäonnistui LogView Checking Log Clear Save Log Text files (*.txt *.log);;All files (*.*) Cppcheck Cppcheck Could not open file for writing: "%1" MainWindow Cppcheck Cppcheck Standard Vakio &File &Tiedosto &View &Näytä &Toolbars &Check &Tarkista C++ standard C standard &Edit &Muokkaa &License... &Lisenssi... A&uthors... &Tekijät... &About... &Tietoa ohjelmasta Cppcheck... &Files... &Tiedostot... Check files Ctrl+F Ctrl+F &Directory... &Hakemisto... Check directory Ctrl+D Ctrl+D &Recheck files Tarkista tiedostot &uudelleen Ctrl+R Ctrl+R &Stop &Pysäytä Stop checking Esc Esc &Save results to file... &Tallenna tulokset tiedostoon... Ctrl+S Ctrl+S &Quit &Lopeta &Clear results &Tyhjennä tulokset &Preferences &Asetukset Errors Show errors Show S&cratchpad... Warnings Show warnings Performance warnings Show performance warnings Show &hidden Information Show information messages Portability Show portability warnings &Filter Filter results Windows 32-bit ANSI Windows 32-bit Unicode Unix 32-bit Unix 64-bit Windows 64-bit Platforms C++11 C99 Posix C11 C89 C++03 &Check all &Valitse kaikki Filter &Uncheck all &Poista kaikista valinta Collapse &all &Pienennä kaikki &Expand all &Laajenna kaikki &Standard Standard items Toolbar &Categories Error categories &Open XML... Open P&roject File... &New Project File... &Log View Log View C&lose Project File &Edit Project File... &Statistics &Contents Categories Style warnings Show style warnings Open the help contents F1 &Help &Ohje Select directory to check Valitse tarkistettava hakemisto No suitable files found to check! Tarkistettavaksi sopivia tiedostoja ei löytynyt! Quick Filter: Found project file: %1 Do you want to load this project file instead? Found project files from the directory. Do you want to proceed checking without using any of these project files? License Lisenssi Authors Tekijät XML files version 2 (*.xml);;XML files version 1 (*.xml);;Text files (*.txt);;CSV files (*.csv) XML files (*.xml);;Text files (*.txt);;CSV files (*.csv) XML-tiedostot (*.xml);;Tekstitiedostot (*.txt);;CSV-tiedostot (*.csv) Save the report file Tallenna raportti XML files (*.xml) XML-tiedostot (*xml) There was a problem with loading the editor application settings. This is probably because the settings were changed between the Cppcheck versions. Please check (and fix) the editor application settings, otherwise the editor program might not start correctly. You must close the project file before selecting new files or directories! Select files to check Valitse tarkistettavat tiedostot Current results will be cleared. Opening a new XML file will clear current results.Do you want to proceed? Open the report file Checking is running. Do you want to stop the checking and exit Cppcheck?. XML files version 1 (*.xml) XML files version 2 (*.xml) Text files (*.txt) Tekstitiedostot (*.txt) CSV files (*.csv) Cppcheck - %1 Cppcheck - %1 Project files (*.cppcheck);;All files(*.*) Select Project File Project: Select Project Filename No project file loaded The project file %1 could not be found! Do you want to remove the file from the recently used projects -list? Finnish Suomi English Englanti Chinese (Simplified) Dutch French Italian Korean Spanish Swedish Ruotsi German Saksa Russian Venäjä Japanese Japanease Serbian Cppcheck GUI. Syntax: cppcheck-gui [OPTIONS] [files or paths] Options: -h, --help Print this help -p <file> Open given project file and start checking it -l <file> Open given results xml file -d <directory> Specify the directory that was checked to generate the results xml specified with -l -v, --version Show program version Cppcheck GUI - Command line parameters Platforms Built-in Unix 32-bit Unix 64-bit Windows 32-bit ANSI Windows 32-bit Unicode Windows 64-bit Project Cppcheck Cppcheck Could not read the project file. Could not write the project file. ProjectFile Project File Project Root: Paths: Add... Edit Remove Includes Include directories: Up Down Exclude Defines: ProjectFileDialog Project file: %1 Select include directory Select a directory to check Select directory to ignore QDialogButtonBox OK Cancel Close Save QObject Unknown language specified! Language file %1 not found! Language file %1.qm not found! Käännöstiedostoa %1 ei löytynyt! Failed to load translation for language %1 from file %2 Failed to load translation for language %1 from file %2.qm Käänöksen lataaminen kielelle %1 tiedostosta %2 epäonnistui ResultsTree File Tiedosto Severity Tyyppi Line Rivi Summary Undefined file Määrittelemätön tiedosto [Inconclusive] debug Copy filename Kopioi tiedostonimi Copy full path Kopioi tiedoston koko polku Copy message Copy message id Hide Hide all with id Cppcheck Cppcheck No editor application configured. Configure the editor application for Cppcheck in preferences/Applications. Configure the text file viewer program in Cppcheck preferences/Applications. Voit asetuksista määritellä muita ohjelmia joilla avata tämän virheen sisältävän tiedoston. No default editor application selected. Please select the default editor application in preferences/Applications. Could not find the file! Could not start %1 Please check the application path and parameters are correct. Ohjelman %1 käynnistäminen epäonnistui Tarkista että ohjelman polku ja parametrit ovat oikeat. Could not find file: %1 Please select the directory where file is located. Select Directory Id style Tyyli error Yleinen warning performance portability information ResultsView %p% (%1 of %2 files checked) Cppcheck Cppcheck No errors found. Virheitä ei löytynyt. Errors were found, but they are configured to be hidden. To toggle what kind of errors are shown, open view menu. Virheitä löytyi, mutta asetuksissa kyseiset virheet on määritelty piilotettavaksi. Määrittääksesi minkä tyyppisiä virheitä näytetään, avaa näkymä valikko. Failed to read the report. Summary Message Id No errors found, nothing to save. Virheitä ei löytynyt, ei mitään tallennettavaa. Failed to save the report. Raportin tallentaminen epäonnistui. Results Tulokset ScratchPad Scratchpad filename Check Settings Preferences Asetukset General Yleiset Include paths: Add... Number of threads: Säikeiden lukumäärä: Ideal count: Force checking all #ifdef configurations Check all #ifdef configurations Tarkista kaikki #ifdef kombinaatiot Show full path of files Näytä tiedostojen täysi polku Show "No errors found" message when no errors found Näytä "virheitä ei löytynyt"-viesti jos virheitä ei löydy Display error Id in column "Id" Enable inline suppressions Paths Edit Remove Applications Ohjelmat Edit... Set as default Reports Raportit Save all errors when creating report Tallenna kaikki virheet raporttia luodessa Save full path to files in reports Tallenna tiedostojen koko polku raportteihin Language Advanced &Show inconclusive errors S&how internal warnings in log SettingsDialog N/A Add a new application Lisää uusi ohjelma Modify an application Muokkaa ohjelmaa [Default] Select include directory StatsDialog Statistics Project Project: Paths: Include paths: Defines: Previous Scan Path Selected: Number of Files Scanned: Scan Duration: Errors: Warnings: Stylistic warnings: Portability warnings: Performance issues: Information messages: Copy to Clipboard 1 day %1 days 1 hour %1 hours 1 minute %1 minutes 1 second %1 seconds 0.%1 seconds and Project Settings Paths Include paths Defines Path selected Number of files scanned Scan duration Errors Warnings Style warnings Portability warnings Performance warnings Information messages ThreadResult %1 of %2 files checked TranslationHandler Failed to change the user interface language: %1 The user interface language has been reset to English. Open the Preferences-dialog to select any of the available languages. Cppcheck Cppcheck TxtReport inconclusive cppcheck-1.61/gui/cppcheck_fr.ts000066400000000000000000001210561217722632100166340ustar00rootroot00000000000000 About About Cppcheck A propos Version %1 Version %1 Cppcheck - A tool for static C/C++ code analysis. Cppcheck - Un outil d'analyse statique de code C/C++. This program is licensed under the terms of the GNU General Public License version 3 Ce programme est sous license GNU General Public License version 3 Visit Cppcheck homepage at %1 Visitez le site Cppcheck : %1 Copyright © 2007-2013 Daniel Marjamäki and cppcheck team. ApplicationDialog Add an application Ajouter une application Browse Parcourir Executable files (*.exe);;All files(*.*) Fichier exécutable (*.exe);;Tous les fichiers(*.*) Select viewer application Sélection de l'application Cppcheck &Executable: &Parameters: Here you can add an application that can open error files. Specify a name for the application, the application executable and command line parameters for the application. The following texts in parameters are replaced with appropriate values when application is executed: (file) - Filename containing the error (line) - Line number containing the error (message) - Error message (severity) - Error severity Example opening a file with Kate and make Kate scroll to the correct line: Executable: kate Parameters: -l(line) (file) &Name: You must specify a name, a path and optionally parameters for the application! FileViewDialog Could not find the file: %1 Ne trouve pas le fichier : %1 Cppcheck Could not read the file: %1 Ne peut pas lire le fichier : %1 LogView Checking Log Clear Save Log Text files (*.txt *.log);;All files (*.*) Cppcheck Could not open file for writing: "%1" MainWindow Cppcheck &File &Fichier &View &Affichage &Help &Aide &Check &Vérifier &Edit &Édition Standard Standard &License... &License... A&uthors... A&uteur... &About... À &Propos... &Files... &Fichiers... Ctrl+F &Directory... &Répertoires... Ctrl+D &Recheck files &Revérifier les fichiers Ctrl+R &Stop &Arrêter Esc &Save results to file... &Sauvegarder les résultats dans un fichier... Ctrl+S &Quit &Quitter &Clear results &Effacer les résultats &Preferences &Préférences &Check all Tout &cocher &Uncheck all Tout &décocher Collapse &all Tout &réduire &Expand all Tout &afficher &Contents &Contenu Open the help contents Ouvir l'aide F1 No suitable files found to check! Pas de fichiers trouvés ! Select directory to check Sélectionner le répertoire à vérifier License Licence Authors Auteur Save the report file Sauvegarder le rapport XML files (*.xml) Fichier XML (*.xml) Text files (*.txt) Fichier Texte (*.txt) CSV files (*.csv) Fichier CSV (*.csv) Cppcheck - %1 English Anglais Dutch Hollandais Finnish Finlandais Swedish Suédois German Allemand Russian Russe &Toolbars Categories Check files Check directory Stop checking Style warnings Show style warnings Errors Show errors &Standard Standard items Toolbar &Categories Error categories &Open XML... Open P&roject File... &New Project File... &Log View Log View C&lose Project File &Edit Project File... &Statistics Warnings Show warnings Performance warnings Show performance warnings Show &hidden Information Show information messages Portability Show portability warnings You must close the project file before selecting new files or directories! Open the report file Checking is running. Do you want to stop the checking and exit Cppcheck?. XML files version 2 (*.xml);;XML files version 1 (*.xml);;Text files (*.txt);;CSV files (*.csv) XML files version 1 (*.xml) XML files version 2 (*.xml) Project files (*.cppcheck);;All files(*.*) Select Project File Select Project Filename No project file loaded Japanese Serbian French There was a problem with loading the editor application settings. This is probably because the settings were changed between the Cppcheck versions. Please check (and fix) the editor application settings, otherwise the editor program might not start correctly. Spanish &Filter Filter results Quick Filter: Found project file: %1 Do you want to load this project file instead? Found project files from the directory. Do you want to proceed checking without using any of these project files? Project: The project file %1 could not be found! Do you want to remove the file from the recently used projects -list? Filter Windows 32-bit ANSI Windows 32-bit Unicode Unix 32-bit Unix 64-bit Windows 64-bit Platforms C++11 C99 Posix Korean Current results will be cleared. Opening a new XML file will clear current results.Do you want to proceed? Italian Show S&cratchpad... Chinese (Simplified) Select files to check Sélectionner les fichiers à vérifier Cppcheck GUI. Syntax: cppcheck-gui [OPTIONS] [files or paths] Options: -h, --help Print this help -p <file> Open given project file and start checking it -l <file> Open given results xml file -d <directory> Specify the directory that was checked to generate the results xml specified with -l -v, --version Show program version Cppcheck GUI - Command line parameters C++ standard C standard C11 C89 C++03 Platforms Unix 32-bit Unix 64-bit Windows 32-bit ANSI Windows 32-bit Unicode Windows 64-bit Built-in Project Cppcheck Could not read the project file. Could not write the project file. ProjectFile Project File Paths: Defines: Project Add... Edit Remove Includes Include directories: Root: Up Down Exclude ProjectFileDialog Project file: %1 Select include directory Select directory to ignore Select a directory to check QDialogButtonBox OK Cancel Close Save QObject Language file %1 not found! Fichier de langue %1 non trouvé ! Failed to load translation for language %1 from file %2 Erreur lors du chargement de la langue %1 depuis le fichier %2 Unknown language specified! ResultsTree File Fichier Severity Sévérité Line Ligne Undefined file Fichier indéterminé Copy filename Copier nom du fichier Copy full path Copier le chemin complet Copy message Copier le message Cppcheck Could not start %1 Please check the application path and parameters are correct. Ne peut pas démarrer %1 Merci de vérifier que le chemin de l'application et que les paramètres sont corrects. style erreur de style error erreur Summary Hide Could not find the file! Could not find file: %1 Please select the directory where file is located. Select Directory warning performance portability information debug [Inconclusive] No editor application configured. Configure the editor application for Cppcheck in preferences/Applications. No default editor application selected. Please select the default editor application in preferences/Applications. Id Copy message id Hide all with id ResultsView Results Résultats Cppcheck No errors found. Pas d'erreurs trouvées. Errors were found, but they are configured to be hidden. To toggle what kind of errors are shown, open view menu. Des erreurs ont été trouvées mais sont configurées pour rester cachées Pour configurer les erreurs affichées, ouvrez le menu d'affichage. No errors found, nothing to save. Pas d'erreurs trouvées, rien à sauvegarder. Failed to save the report. Erreur lors de la sauvegarde du rapport. Failed to read the report. Summary Message Message %p% (%1 of %2 files checked) Id ScratchPad Scratchpad filename Check Settings Preferences Préférences General Général Number of threads: Nombre de processus : Show full path of files Montrer le chemin complet des fichiers Show "No errors found" message when no errors found Afficher un message "Pas d'erreur trouvée" lorsque aucune erreur est trouvée Applications Applications Reports Rapports Save all errors when creating report Sauvegarder toutes les erreurs lorsqu'un rapport est créé Save full path to files in reports Sauvegarder le chemin complet des fichiers dans les rapports Include paths: Add... Ideal count: Force checking all #ifdef configurations Enable inline suppressions Language Paths Edit Remove Edit... Set as default Advanced &Show inconclusive errors S&how internal warnings in log Display error Id in column "Id" SettingsDialog Add a new application Ajouter une nouvelle application Modify an application Modifier une application N/A Select include directory [Default] StatsDialog Statistics Project Project: Paths: Include paths: Defines: Previous Scan Path Selected: Number of Files Scanned: Scan Duration: Errors: Warnings: Stylistic warnings: Portability warnings: Performance issues: Information messages: Copy to Clipboard 1 day %1 days 1 hour %1 hours 1 minute %1 minutes 1 second %1 seconds 0.%1 seconds and Project Settings Paths Include paths Defines Path selected Number of files scanned Scan duration Errors Warnings Style warnings Portability warnings Performance warnings Information messages ThreadResult %1 of %2 files checked TranslationHandler Failed to change the user interface language: %1 The user interface language has been reset to English. Open the Preferences-dialog to select any of the available languages. Cppcheck TxtReport inconclusive cppcheck-1.61/gui/cppcheck_it.ts000066400000000000000000001675721217722632100166560ustar00rootroot00000000000000 About About Cppcheck Informazioni su Cppcheck Version %1 Versione %1 Cppcheck - A tool for static C/C++ code analysis. Cppcheck - Uno strumento per l'analisi statica di codice C/C++ Copyright © 2007-2013 Daniel Marjamäki and cppcheck team. Copyright © 2007-2012 Daniel Marjamäki and cppcheck team. Copyright (C) 2007-2012 Daniel Marjamäki ed il team Cppcheck. This program is licensed under the terms of the GNU General Public License version 3 Questo programma è rilasciato sotto i termini della GNU General Public License versione 3 Visit Cppcheck homepage at %1 Visita la pagina iniziale di Cppcheck all'indirizzo: %1 ApplicationDialog Add an application Aggiungi un'applicazione Here you can add an application that can open error files. Specify a name for the application, the application executable and command line parameters for the application. The following texts in parameters are replaced with appropriate values when application is executed: (file) - Filename containing the error (line) - Line number containing the error (message) - Error message (severity) - Error severity Example opening a file with Kate and make Kate scroll to the correct line: Executable: kate Parameters: -l(line) (file) Qui puoi aggiungere un'applicazione che può aprire i file contenente l'errore. Specifica un nome per l'applicazione, l'eseguibile dell'applicazione e i parametri di comando per l'applicazione. I seguenti testi nei parametri sono sostituiti con appropriati valori quando l'applicazione è eseguita: (file) - Il nome del file contenente l'errore (line) - La linea contenente l'errore (message) - Messaggio d'errore (severity) - Severità dell'errore Un'esempio di apertura di un file con Kate e lo scorrimento alla giusta linea: Eseguibile: kate Parametri: -l(line) (file) &Name: &Nome: &Executable: &Eseguibile: &Parameters: &Parametri: Browse Esplora Executable files (*.exe);;All files(*.*) File di esecuzione (*.exe);;Tutti i file(*.*) Select viewer application Seleziona l'applicazione di lettura Cppcheck Cppcheck You must specify a name, a path and optionally parameters for the application! Devi specificare un nome, un percorso ed, opzionalmente, i parametri per l'applicazione! FileViewDialog Could not find the file: %1 File non trovato: %1 Cppcheck Cppcheck Could not read the file: %1 Non è stato possibile leggere il file: %1 LogView Checking Log Log sulla scansione Clear Cancella Save Log Salva il rapporto Text files (*.txt *.log);;All files (*.*) File di testo (*.txt *.log);;Tutti i files(*.*) Cppcheck Cppcheck Could not open file for writing: "%1" Non è stato possibile aprire il file per la scrittura: "%1" MainWindow Cppcheck Cppcheck Standard Standard &File &File &View &Visualizza &Toolbars &Barre degli strumenti &Check &Scansiona C++ standard C standard &Edit &Modifica &License... &Licenza... A&uthors... A&utori... &About... I&nformazioni su... &Files... &File... Check files Scansiona i file Ctrl+F Ctrl+F &Directory... &Cartella... Check directory Scansiona la cartella Ctrl+D Ctrl+D &Recheck files &Riscansiona i file Ctrl+R Ctrl+R &Stop &Ferma Stop checking Ferma la scansione Esc Esc &Save results to file... &Salva i risultati nel file... Ctrl+S Ctrl+S &Quit &Esci &Clear results &Cancella i risultati &Preferences &Preferenze Errors Errori Show errors Mostra gli errori Show S&cratchpad... Mostra il blocchetto per appunti... Warnings Avvisi Show warnings Mostra gli avvisi Performance warnings Avvisi sulle prestazioni Show performance warnings Mostra gli avvisi sulle prestazioni Show &hidden Mostra &i nascosti Information Informazione Show information messages Mostra messaggi di informazione Portability Portabilità Show portability warnings Mostra gli avvisi sulla portabilità &Filter &Filtro Filter results Filtra i risultati Windows 32-bit ANSI Windows 32-bit, ANSI Windows 32-bit Unicode Windows 32-bit, Unicode Unix 32-bit Unix 32-bit Unix 64-bit Unix 64-bit Windows 64-bit Windows 64-bit Platforms Piattaforme C++11 C++11 C99 C99 Posix Posix C11 C11 C89 C89 C++03 C++03 &Check all &Seleziona tutto Filter Filtro &Uncheck all &Deseleziona tutto Collapse &all Riduci &tutto &Expand all &Espandi tutto &Standard &Standard Standard items Oggetti standard Toolbar Barra degli strumenti &Categories &Categorie Error categories Categorie di errore &Open XML... &Apri XML... Open P&roject File... Apri file di p&rogetto... &New Project File... &Nuovo file di progetto... &Log View &Visualizza il rapporto Log View Visualizza il rapporto C&lose Project File C&hiudi il file di progetto &Edit Project File... &Modifica il file di progetto... &Statistics &Statistiche &Contents &Contenuti Categories Categorie Style warnings Avvisi sullo stile Show style warnings Mostra gli avvisi sullo stile Open the help contents Apri i contenuti di aiuto F1 F1 &Help &Aiuto Select directory to check Seleziona una cartella da scansionare No suitable files found to check! Nessun file trovato idoneo alla scansione! Quick Filter: Rapido filtro: Found project file: %1 Do you want to load this project file instead? Trovato il file di progetto: %1 Vuoi piuttosto caricare questo file di progetto? Found project files from the directory. Do you want to proceed checking without using any of these project files? Trovati file di progetto dalla directory. Vuoi procedere alla scansione senza usare qualcuno di questi file di progetto? License Licenza Authors Autori XML files version 2 (*.xml);;XML files version 1 (*.xml);;Text files (*.txt);;CSV files (*.csv) File XML Versione 2 (*.xml);;File XML Versione 1 (*.xml);;File di testo (*.txt);;File CSV (*.csv) Save the report file Salva il file di rapporto XML files (*.xml) File XML (*.xml) There was a problem with loading the editor application settings. This is probably because the settings were changed between the Cppcheck versions. Please check (and fix) the editor application settings, otherwise the editor program might not start correctly. C'è stato un problema con il caricamento delle impostazioni delle applicazioni editor. Probabilmente ciò è avvenuto perché le impostazioni sono state modificate tra le versioni di Cppcheck. Per favore controlla (e sistema) le impostazioni delle applicazioni editor, altrimenti il programma editor può non partire correttamente. You must close the project file before selecting new files or directories! Devi chiudere il file di progetto prima di selezionare nuovi file o cartelle! Select files to check Seleziona i file da scansionare Current results will be cleared. Opening a new XML file will clear current results.Do you want to proceed? I risultati correnti verranno ripuliti. L'apertura di un nuovo file XML ripulirà i risultati correnti. Vuoi procedere? Open the report file Apri il file di rapporto Checking is running. Do you want to stop the checking and exit Cppcheck?. La scansione è in esecuzione. Vuoi fermare la scansione ed uscire da Cppcheck? XML files version 1 (*.xml) Files XML versione 1 (*.xml) XML files version 2 (*.xml) Files XML versione 2 (*.xml) Text files (*.txt) File di testo (*.txt) CSV files (*.csv) Files CSV (*.csv) Cppcheck - %1 Cppcheck - %1 Failed to change the user interface language: %1 The user interface language has been reset to English. Open the Preferences-dialog to select any of the available languages. Fallito il tentativo di cambio della lingua dell'interfaccia utente: %1 L'interfaccia utente è stata risettata in Inglese. Apri la finestra di dialogo Preferenze per selezionare una qualunque lingua a disposizione. Project files (*.cppcheck);;All files(*.*) Files di progetto (*.cppcheck);;Tutti i files(*.*) Select Project File Seleziona il file di progetto Project: Progetto: Select Project Filename Seleziona il nome del file di progetto No project file loaded Nessun file di progetto caricato The project file %1 could not be found! Do you want to remove the file from the recently used projects -list? Il file di progetto %1 non è stato trovato! Vuoi rimuovere il file dalla lista dei progetti recentemente usati? Finnish Finnish English English Chinese (Simplified) Dutch Dutch French French Italian Italian Korean Korean Spanish Spanish Swedish Swedish German German Russian Russian Japanese Japanese Serbian Serbian Cppcheck GUI. Syntax: cppcheck-gui [OPTIONS] [files or paths] Options: -h, --help Print this help -p <file> Open given project file and start checking it -l <file> Open given results xml file -d <directory> Specify the directory that was checked to generate the results xml specified with -l -v, --version Show program version Cppcheck GUI - Command line parameters Platforms Built-in Built-in Unix 32-bit Unix 32-bit Unix 64-bit Unix 64-bit Windows 32-bit ANSI Windows 32-bit, ANSI Windows 32-bit Unicode Windows 32-bit, Unicode Windows 64-bit Windows 64-bit Project Cppcheck Cppcheck Could not read the project file. Non è stato possibile leggere il file di progetto. Could not write the project file. Non è stato possibile scrivere il file di progetto. ProjectFile Project File File di progetto Project Progetto Root: Root: Paths: Percorsi: Add... Aggiungi... Edit Modifica Remove Rimuovi Includes Inclusioni Include directories: Cartelle di inclusione: Up Su Down Giù Exclude Escludi Defines: Definizioni: ProjectFileDialog Project file: %1 File di progetto: %1 Select include directory Seleziona la cartella da includere Select a directory to check Seleziona una cartella da scansionare Select directory to ignore Seleziona la cartella da ignorare QDialogButtonBox OK Cancel Close Chiudi Save QObject Unknown language specified! Lingua specificata sconosciuta! Language file %1 not found! Il file di lingua %1 non trovato! Failed to load translation for language %1 from file %2 Fallito il tentativo di aprire la traduzione per la lingua %1 dal file %2 ResultsTree File File Severity Severità Line Linea Summary Riassunto Undefined file File indefinito [Inconclusive] [Inconcludente] debug debug Copy filename Copia nome file Copy full path Copia tutto il percorso Copy message Copia messaggio Copy message id Copia id del messaggio Hide Nascondi Hide all with id Cppcheck Cppcheck No editor application configured. Configure the editor application for Cppcheck in preferences/Applications. Nessun'applicazione di scrittura è stato configurato. Configura l'applicazione di scrittura per Cppcheck in Preferenze/Applicazioni. No default editor application selected. Please select the default editor application in preferences/Applications. Nessun'applicazione di scrittura predefinito Keine è stato selezionato. Per favore seleziona l'applicazione di scrittura predefinito in Preferenze/Applicazioni. Could not find the file! Non è stato possibile trovare il file! Could not start %1 Please check the application path and parameters are correct. Non è stato possibile avviare %1 Per favore verifica che il percorso dell'applicazione e i parametri siano corretti. Could not find file: %1 Please select the directory where file is located. Non è stato possibile trovare il file: %1 Per favore selezioa la cartella dove il file è posizionato. Select Directory Seleziona Cartella Id Id style stile error errore warning avviso performance performance portability portabilità information Informazione ResultsView %p% (%1 of %2 files checked) %p% (%1 su %2 file scansionati) Cppcheck Cppcheck No errors found. Nessun errore trovato. Errors were found, but they are configured to be hidden. To toggle what kind of errors are shown, open view menu. Sono stati trovati errori, ma sono stati configurati per essere nascosti. Per vedere il tipo di errori che sono mostrati, apri il menu Visualizza. Failed to read the report. Apertura del report fallito. Summary Riassunto Message Messaggio Id Id No errors found, nothing to save. Nessun errore trovato, nulla da salvare. Failed to save the report. Salvataggio del report fallito. Results Risultati ScratchPad Scratchpad Blocchetto per appunti filename Nome file Check Scansiona Settings Preferences Preferenze General Generale Include paths: Percorsi d'inclusione: Add... Aggiungi... Number of threads: Numero di threads: Ideal count: Numero ideale: Force checking all #ifdef configurations Forza la scansione di tutte le configurazioni #ifdef Show full path of files Mostra tutto il percorso dei files Show "No errors found" message when no errors found Mostra il messaggio "Nessun errore trovato" quando nessun errore è stato trovato Display error Id in column "Id" Mostra l'id dell'errore nella colonna "Id" Enable inline suppressions Abilita le soppressioni Paths Percorsi Edit Modifica Remove Rimuovi Applications Applicazioni Edit... Modifica... Set as default Imposta come predefinito Reports Rapporti Save all errors when creating report Salva tutti gli errori quando viene creato il rapporto Save full path to files in reports Salva tutto il percorso ai files nei rapporti Language Lingua Advanced Avanzate &Show inconclusive errors &Mostra errori inconcludenti S&how internal warnings in log &Mostra avvisi interni nel log SettingsDialog N/A N/A Add a new application Aggiungi una nuova applicazione Modify an application Modifica un'applicazione [Default] [Predefinito] Select include directory Seleziona la cartella da includere StatsDialog Statistics Statistiche Project Progetto Project: Progetto: Paths: Percorsi: Include paths: Percorsi di inclusione: Defines: Definizioni: Previous Scan Precedente Scansione Path Selected: Selezionato percorso: Number of Files Scanned: Numero di Files Scansionati: Scan Duration: Durata della scansione: Errors: Errori: Warnings: Avvisi: Stylistic warnings: Avvisi sullo stile: Portability warnings: Avvisi sulla portabilità: Performance issues: Casi sulla performance: Information messages: Messaggi di informazione: Copy to Clipboard Copia negli Appunti 1 day 1 giorno %1 days %1 giorni 1 hour 1 ora %1 hours %1 ore 1 minute 1 minuto %1 minutes %1 minuti 1 second 1 secondo %1 seconds %1 secondi 0.%1 seconds 0,%1 secondi and e Project Settings Impostazioni progetto Paths Percorsi Include paths Percorsi di inclusione Defines Definizioni Path selected Selezionato percorso Number of files scanned Numero di file scansionati Scan duration Durata della scansione Errors Errori Warnings Avvisi Style warnings Stilwarnungen Portability warnings Avvisi sulla portabilità Performance warnings Avvisi sulle performance Information messages Messaggi di informazione ThreadResult %1 of %2 files checked %1 su %2 file scansionati TranslationHandler Failed to change the user interface language: %1 The user interface language has been reset to English. Open the Preferences-dialog to select any of the available languages. Fallito il tentativo di cambio della lingua dell'interfaccia utente: %1 L'interfaccia utente è stata risettata in Inglese. Apri la finestra di dialogo Preferenze per selezionare una qualunque lingua a disposizione. Cppcheck Cppcheck TxtReport inconclusive inconcludente cppcheck-1.61/gui/cppcheck_ja.ts000066400000000000000000001652421217722632100166240ustar00rootroot00000000000000 About About Cppcheck cppcheckについて Version %1 Version %1 Cppcheck - A tool for static C/C++ code analysis. CppcheckはC/C++ 静的コード解析ツールです. Copyright © 2007-2013 Daniel Marjamäki and cppcheck team. Copyright © 2007-2012 Daniel Marjamäki and cppcheck team. This program is licensed under the terms of the GNU General Public License version 3 本ソフトウェアはGNU General Public License Version3 ライセンスの元で配布されます Visit Cppcheck homepage at %1 Cppcheckのホームページはこちら %1 ApplicationDialog Add an application アプリケーションの追加 Here you can add an application that can open error files. Specify a name for the application, the application executable and command line parameters for the application. The following texts in parameters are replaced with appropriate values when application is executed: (file) - Filename containing the error (line) - Line number containing the error (message) - Error message (severity) - Error severity Example opening a file with Kate and make Kate scroll to the correct line: Executable: kate Parameters: -l(line) (file) &Name: 名(&N) &Executable: 実行可能(&E) &Parameters: パラメータ:(&P) Browse 参照 Executable files (*.exe);;All files(*.*) 実行ファイル (*.exe);;すべてのファイル(*.*) Select viewer application 表示アプリケーションの選択 Cppcheck Cppcheck You must specify a name, a path and optionally parameters for the application! FileViewDialog Could not find the file: %1 ファイル:%1 が見つかりません Cppcheck Cppcheck Could not read the file: %1 ファイル:%1 が読み込めません LogView Checking Log Cppcheck ログ Clear 消去 Save Log ログ保存 Text files (*.txt *.log);;All files (*.*) テキストファイル (*.txt *.log);;すべてのファイル(*.*) Cppcheck Cppcheck Could not open file for writing: "%1" MainWindow Cppcheck Cppcheck &File ファイル(&F) &View 表示(&V) &Toolbars ツールバー(&T) &Help ヘルプ(&H) &Check 解析(&A) C++ standard C standard &Edit 編集(&E) Standard 標準(&S) Categories カテゴリ(&C) &License... ライセンス(&L)... A&uthors... 作者(&u)... &About... Cppcheckについて(&A)... &Files... ファイル選択(&F)... Check files ファイルをチェック Ctrl+F Ctrl+F &Directory... ディレクトリ選択(&D)... Check directory ディレクトリをチェック Ctrl+D Ctrl+D &Recheck files 再チェック(&R) Ctrl+R Ctrl+R &Stop 停止(&S) Stop checking チェックを停止する Esc Esc &Save results to file... 結果をファイルに保存(&S)... Ctrl+S Ctrl+S &Quit 終了(&Q) &Clear results 結果をクリア(&C) &Preferences 設定(&P) Style warnings スタイル警告 Show style warnings スタイル警告を表示 Errors エラー Show errors エラーを表示 Show S&cratchpad... Information 情報 Show information messages 情報メッセージを表示します。 Portability 移植可能性 Show portability warnings 潜在的な移植可能性の問題を示しています。 &Filter フィルター(&F) Filter results Windows 32-bit ANSI Windows 32-bit Unicode Unix 32-bit Unix 64-bit Windows 64-bit Platforms プラットフォーム C++11 C++11 C99 C99 Posix Posix C11 C11 C89 C89 C++03 C++03 C&lose Project File プロジェクトを閉じる(&l) &Edit Project File... プロジェクトの編集(&E)... &Statistics 統計情報(&S) Warnings 警告 Show warnings 警告を表示 Performance warnings パフォーマンス警告 Show performance warnings パフォーマンス警告を表示 Show &hidden 非表示を表示(&h) &Check all すべてのエラーを表示(&C) Filter フィルター &Uncheck all すべてのエラーを非表示(&U) Collapse &all ツリーを折り畳む(&A) &Expand all ツリーを展開(&E) &Standard 標準(&S) Standard items 標準項目 &Contents コンテンツ(&C) Open the help contents ヘルプファイルを開く F1 F1 Toolbar ツールバー &Categories カテゴリ(&C) Error categories エラーカテゴリ &Open XML... XMLを開く(&O)... Open P&roject File... プロジェクトを開く(&R)... &New Project File... 新規プロジェクト(&N)... &Log View ログを表示(&L) Log View ログ表示 There was a problem with loading the editor application settings. This is probably because the settings were changed between the Cppcheck versions. Please check (and fix) the editor application settings, otherwise the editor program might not start correctly. No suitable files found to check! 解析可能なファイルではありません You must close the project file before selecting new files or directories! 新しいファイル/ディレクトリを解析するには現在のプロジェクトを閉じてください Select directory to check チェック対象のディレクトリを選択 Quick Filter: クイックフィルタ: Select files to check チェック対象のファイルを選択 Found project file: %1 Do you want to load this project file instead? Found project files from the directory. Do you want to proceed checking without using any of these project files? Current results will be cleared. Opening a new XML file will clear current results.Do you want to proceed? XML files (*.xml) XML ファイル (*.xml) Open the report file レポートを開く Checking is running. Do you want to stop the checking and exit Cppcheck?. 解析中です. 解析を停止してCppcheckを終了しますか?. License ライセンス Authors 作者 XML files version 2 (*.xml);;XML files version 1 (*.xml);;Text files (*.txt);;CSV files (*.csv) XML files (*.xml);;Text files (*.txt);;CSV files (*.csv) XML ファイル (*.xml);;テキストファイル (*.txt);;CSV形式ファイル (*.csv) Save the report file レポートを保存 XML files version 1 (*.xml) XMLファイルのバージョン1 XML files version 2 (*.xml) XMLファイルのバージョン2 Text files (*.txt) テキストファイル (*.txt) CSV files (*.csv) CSV形式ファイル (*.csv) Cppcheck - %1 Cppcheck - %1 Project files (*.cppcheck);;All files(*.*) プロジェクトファイル (*.cppcheck);;すべてのファイル(*.*) Select Project File プロジェクトファイルを選択 Project: プロジェクト: Select Project Filename プロジェクトファイル名を選択 No project file loaded プロジェクトファイルが読み込まれていません The project file %1 could not be found! Do you want to remove the file from the recently used projects -list? English 英語 Dutch オランダ語 Chinese (Simplified) Finnish フィンランド語 French フランス語 Italian Korean Spanish スペイン語 Swedish スウェーデン語 German ドイツ語 Russian ロシア語 Japanese Japanease 日本語 Serbian セルビア語 Cppcheck GUI. Syntax: cppcheck-gui [OPTIONS] [files or paths] Options: -h, --help Print this help -p <file> Open given project file and start checking it -l <file> Open given results xml file -d <directory> Specify the directory that was checked to generate the results xml specified with -l -v, --version Show program version Cppcheck GUI - Command line parameters Platforms Built-in Unix 32-bit Unix 64-bit Windows 32-bit ANSI Windows 32-bit Unicode Windows 64-bit Project Cppcheck Cppcheck Could not read the project file. プロジェクトファイルが読み込めませんでした Could not write the project file. プロジェクトファイルが保存できませんでした ProjectFile Project File プロジェクトファイル Project プロジェクト Root: ルート: Paths: パス: Add... 追加... Edit 編集 Remove 取り除く Includes Include directories: Up Down Exclude 除外する Defines: Defines: ProjectFileDialog Project file: %1 プロジェクトファイル:%1 Select include directory includeディレクトリを選択 Select a directory to check Select directory to ignore QDialogButtonBox OK Cancel Close 閉じる Save QObject Unknown language specified! 指定された未知の言語 Language file %1 not found! 言語ファイル %1 が見つかりません! Failed to load translation for language %1 from file %2 ResultsTree File ファイル Severity 警告種別 Line Summary 内容 Undefined file 未定義ファイル [Inconclusive] [結論の出ない] debug デバッグ Copy filename ファイル名をコピー Copy full path フルパスをコピー Copy message メッセージをコピー Copy message id Hide 非表示 Hide all with id Cppcheck Cppcheck No editor application configured. Configure the editor application for Cppcheck in preferences/Applications. Configure the text file viewer program in Cppcheck preferences/Applications. メニューの「編集」→「設定」からテキストファイルを表示するアプリケーションを設定してください。 No default editor application selected. Please select the default editor application in preferences/Applications. Could not find the file! ファイルが見つかりません Could not start %1 Please check the application path and parameters are correct. %1 が実行できません。 実行ファイルパスや引数の設定を確認してください。 Could not find file: %1 Please select the directory where file is located. ファイルが見つかりません: %1 ディレクトリにファイルが存在するか確認してください。 Select Directory ディレクトリを選択 Id style スタイル error エラー warning 警告 performance パフォーマンス portability 移植可能性 information 情報 ResultsView Results 結果 No errors found, nothing to save. 警告/エラーが見つからなかったため、保存しません。 Failed to save the report. レポートの保存に失敗しました。 %p% (%1 of %2 files checked) Cppcheck Cppcheck No errors found. 警告/エラーは見つかりませんでした。 Errors were found, but they are configured to be hidden. To toggle what kind of errors are shown, open view menu. 警告/エラーが見つかりましたが、非表示設定になっています。 Failed to read the report. レポートの読み込みに失敗. Summary 内容 Message メッセージ Id ScratchPad Scratchpad filename Check チェック Settings Preferences 設定 General 全般 Include paths: Include ディレクトリ: Add... 追加... Number of threads: 解析スレッド数: Ideal count: 理想的な数: Force checking all #ifdef configurations Check all #ifdef configurations すべての #ifdef をチェックする Show full path of files ファイルのフルパスを表示 Show "No errors found" message when no errors found エラーが無いときは"エラーなし"を表示 Display error Id in column "Id" Enable inline suppressions inline抑制を有効 Paths パス Edit 編集 Remove 削除 Applications アプリケーション Edit... 編集... Set as default デフォルトとして設定 Reports レポート Save all errors when creating report すべての警告/エラーを保存 Save full path to files in reports ファイルのフルパスを保存 Language 言語 Advanced 高度 &Show inconclusive errors 結論の出ないのエラーを表示 S&how internal warnings in log SettingsDialog N/A N/A Add a new application 新しいアプリケーションの追加 Modify an application アプリケーションの変更 [Default] [デフォルト] Select include directory include ディレクトリを選択 StatsDialog Statistics 統計情報 Project プロジェクト Project: プロジェクト: Paths: パス: Include paths: Include ディレクトリ: Defines: Defines: Previous Scan 前回の解析 Path Selected: ディレクトリ選択: Number of Files Scanned: 解析済みファイル数: Scan Duration: 解析にかかった時間: Errors: エラー: Warnings: 警告: Stylistic warnings: スタイル警告: Portability warnings: 移植可能性の警告 Performance issues: パフォーマンス警告: Information messages: 情報メッセージ Copy to Clipboard クリップボードにコピー 1 day 一日 %1 days %1日 1 hour 一時間 %1 hours %1時間 1 minute 一分 %1 minutes %1分 1 second 一秒 %1 seconds %1秒 0.%1 seconds 0.%1秒 and Project Settings プロジェクトの設定 Paths パス Include paths Defines Path selected 選択されたパス Number of files scanned スキャンしたファイルの数 Scan duration スキャン期間 Errors エラー Warnings 警告 Style warnings スタイル警告 Portability warnings 移植可能性警告 Performance warnings パフォーマンス警告 Information messages 情報メッセージ ThreadResult %1 of %2 files checked TranslationHandler Failed to change the user interface language: %1 The user interface language has been reset to English. Open the Preferences-dialog to select any of the available languages. Cppcheck Cppcheck TxtReport inconclusive 結論の出ない cppcheck-1.61/gui/cppcheck_ko.ts000066400000000000000000001224441217722632100166400ustar00rootroot00000000000000 About About Cppcheck Cppcheck 정보 Version %1 버전 %1 Cppcheck - A tool for static C/C++ code analysis. Cppcheck - 정적 C/C++ 코드 분석 도구. Copyright © 2007-2012 Daniel Marjamäki and cppcheck team. Copyright © 2007-2012 Daniel Marjamäki and cppcheck team. This program is licensed under the terms of the GNU General Public License version 3 이 프로그램은 GNU General Public License version 3을 준수합니다 Visit Cppcheck homepage at %1 Cppcheck 홈페이지(%1)를 방문해보세요 Copyright © 2007-2013 Daniel Marjamäki and cppcheck team. Copyright © 2007-2012 Daniel Marjamäki and cppcheck team. {2007-2013 ?} ApplicationDialog Add an application 응용 프로그램 추가 Here you can add an application that can open error files. Specify a name for the application, the application executable and command line parameters for the application. The following texts in parameters are replaced with appropriate values when application is executed: (file) - Filename containing the error (line) - Line number containing the error (message) - Error message (severity) - Error severity Example opening a file with Kate and make Kate scroll to the correct line: Executable: kate Parameters: -l(line) (file) 에러 파일을 열 응용 프로그램을 추가할 수 있습니다. 응용 프로그램의 이름, 실행 파일, 명령행 인자를 입력하세요. 인자 중에서 아래와 같은 텍스트는 응용 프로그램 실행 시 해당 값으로 대치됩니다: (file) - 에러를 포함한 파일이름 (line) - 에러를 포함한 행번호 (message) - 에러 메시지 (severity) - 에러 종류 Kate로 파일을 열고, 해당 행으로 이동하는 예제: 실행파일: kate 인자: -l(line) (file) &Name: 이름(&N): &Executable: 실행 파일(&E): &Parameters: 명령행 인자(&P): Browse 찾기 Executable files (*.exe);;All files(*.*) 실행 파일(*.exe);;모든 파일(*.*) Select viewer application 뷰어 프로그램 선택 Cppcheck Cppcheck You must specify a name, a path and parameters for the application! 응용 프로그램의 이름, 경로 및 인자를 명시해야 합니다! You must specify a name, a path and optionally parameters for the application! FileViewDialog Could not find the file: %1 파일 찾기 실패: %1 Cppcheck Cppcheck Could not read the file: %1 파일 읽기 실패: %1 LogView Checking Log 로그 확인 Clear 지우기 Save Log 로그 저장 Text files (*.txt *.log);;All files (*.*) 텍스트 파일 (*.txt *.log);;모든 파일 (*.*) Cppcheck Cppcheck Could not open file for writing: "%1" 기록할 파일 열기 실패: "%1" MainWindow Cppcheck Cppcheck &File 파일(&F) &View 보기(&V) &Toolbars 도구바(&T) &Help 도움말(&H) &Check 검사(&C) &Edit 편집(&E) Standard 표준 도구 Categories 분류 도구 Filter 필터 도구 &License... 저작권(&L)... A&uthors... 제작자(&u)... &About... 정보(&A)... &Files... 파일(&F)... Check files 파일 검사 Ctrl+F Ctrl+F &Directory... 디렉토리(&D)... Check directory 디렉토리 검사 Ctrl+D Ctrl+D &Recheck files 파일 재검사(&R) Ctrl+R Ctrl+R &Stop 중지(&S) Stop checking 검사 중지 Esc Esc &Save results to file... 결과를 파일에 저장(&S)... Ctrl+S Ctrl+S &Quit 종료(&Q) &Clear results 결과 지우기(&C) &Preferences 설정(&P) Style warnings 스타일 경고 Show style warnings 스타일 경고 표시 Errors 에러 Show errors 애러 표시 &Check all 전체 선택(&C) &Uncheck all 전체 해제(&U) Collapse &all 전체 접기(&A) &Expand all 전체 펼치기(&E) &Standard 표준 도구(&S) Standard items 표준 아이템 &Contents 내용(&C) Open the help contents 도움말을 엽니다 F1 F1 Toolbar 도구바 &Categories 분류 도구(&C) Error categories 에러 종류 &Open XML... XML 열기(&O)... Open P&roject File... 프로젝트 파일 열기(&R)... &New Project File... 새 프로젝트 파일(&N)... &Log View 로그 보기(&L) Log View 로그 보기 C&lose Project File 프로젝트 파일 닫기(&L) &Edit Project File... 프로젝트 파일 편집(&E)... &Statistics 통계 보기(&S) Warnings 경고 Show warnings 경고 표시 Performance warnings 성능 경고 Show performance warnings 성능 경고 표시 Show &hidden 숨기기 보기(&H) Information 정보 Show information messages 정보 표시 Portability 이식성 경고 Show portability warnings 이식성 경고 표시 &Filter 필터 도구(&F) Filter results 필터링 결과 Windows 32-bit ANSI Windows 32-bit ANSI Windows 32-bit Unicode Windows 32-bit Unicode Unix 32-bit Unix 32-bit Unix 64-bit Unix 64-bit Windows 64-bit Windows 64-bit Platforms 플랫폼 C++11 C++11 C99 C99 Posix Posix Quick Filter: 빠른 필터: There was a problem with loading the editor application settings. This is probably because the settings were changed between the Cppcheck versions. Please check (and fix) the editor application settings, otherwise the editor program might not start correctly. 편집기 설정을 불러오는데 문제가 있습니다. Cppcheck 버전간 설정 방법 차이때문인 것으로 보입니다. 편집기 설정을 검사(및 수정)해주세요, 그렇지 않으면 편집기가 제대로 시작하지 않습니다. No suitable files found to check! 검사할 수 있는 파일이 없습니다! You must close the project file before selecting new files or directories! 새로운 파일이나 디렉토리를 선택하기 전에 프로젝트 파일을 닫으세요! Select directory to check 검사할 디렉토리 선택 Found project file: %1 Do you want to load this project file instead? 프로젝트 파일 존재: %1 이 프로젝트 파일을 불러오겠습니까? Found project files from the directory. Do you want to proceed checking without using any of these project files? 디렉토리에 프로젝트 파일 존재. 이 프로젝트 파일을 사용하지 않고 검사를 계속하시겠습니까? XML files (*.xml) XML 파일 (*.xml) Open the report file 보고서 파일 열기 Checking is running. Do you want to stop the checking and exit Cppcheck?. 검사 중. 검사를 중지하고 Cppcheck을 종료하시겠습니까?. License 저작권 Authors 제작자 XML files version 2 (*.xml);;XML files version 1 (*.xml);;Text files (*.txt);;CSV files (*.csv) XML 파일 버전 2 (*.xml);;XML 파일 버전 1 (*.xml);;텍스트 파일 (*.txt);;CSV 파일 (*.csv) Save the report file 보고서 파일 저장 XML files version 1 (*.xml) XML 파일 버전 1 (*.xml) XML files version 2 (*.xml) XML 파일 버전 2 (*.xml) Text files (*.txt) 텍스트 파일 (*.txt) CSV files (*.csv) CSV 파일 (*.csv) Cppcheck - %1 Cppcheck - %1 Failed to change the user interface language: %1 The user interface language has been reset to English. Open the Preferences-dialog to select any of the available languages. 언어 변경 실패: %1 언어가 영어로 초기화 됐습니다. 설정창을 열어서 설정 가능한 언어를 선택하세요. Project files (*.cppcheck);;All files(*.*) 프로젝트 파일 (*.cppcheck);;모든 파일(*.*) Select Project File 프로젝트 파일 선택 Project: 프로젝트: Select Project Filename 프로젝트 파일이름 선택 No project file loaded 프로젝트 파일 불러오기 실패 The project file %1 could not be found! Do you want to remove the file from the recently used projects -list? 프로젝트 파일 %1 이 존재하지 않습니다! 최근 프로젝트 목록에서 파일을 제거하시겠습니까? Dutch 네덜란드어 English 영어 Finnish 핀란드어 French 프랑스어 German 독일어 Japanese 일본어 Korean 한국어 Russian 러시아어 Serbian 세르비아어 Spanish 스페인어 Swedish 스웨덴어 Current results will be cleared. Opening a new XML file will clear current results.Do you want to proceed? Italian Show S&cratchpad... Chinese (Simplified) Select files to check 검사할 파일 선택 Cppcheck GUI. Syntax: cppcheck-gui [OPTIONS] [files or paths] Options: -h, --help Print this help -p <file> Open given project file and start checking it -l <file> Open given results xml file -d <directory> Specify the directory that was checked to generate the results xml specified with -l -v, --version Show program version Cppcheck GUI - Command line parameters C++ standard C standard C11 C11 C89 C89 C++03 C++03 Platforms Unix 32-bit Unix 32-bit Unix 64-bit Unix 64-bit Windows 32-bit ANSI Windows 32-bit ANSI Windows 32-bit Unicode Windows 32-bit Unicode Windows 64-bit Windows 64-bit Built-in 내장 방식 Project Cppcheck Cppcheck Could not read the project file. 프로젝트 파일을 읽을 수 없습니다. Could not write the project file. 프로젝트 파일에 쓸 수 없습니다. ProjectFile Project File 프로젝트 파일 Project 프로젝트 Defines: Defines: Root: Root: Paths: 경로: Add... 추가... Edit 편집 Remove 제거 Includes Includes Include directories: Include 디렉토리: Up 위로 Down 아래로 Exclude Exclude ProjectFileDialog Project file: %1 프로젝트 파일: %1 Select include directory Include 디렉토리 선택 Select a directory to check 검사할 디렉토리 선택 Select directory to ignore 무시할 디렉토리 선택 QDialogButtonBox OK Cancel Close 닫기 Save QObject Unknown language specified! 알 수 없는 언어입니다! Language file %1 not found! 언어 파일(%1)이 없습니다! Failed to load translation for language %1 from file %2 파일(%2)로부터 언어(%1) 불러오기 실패 ResultsTree File 파일 Severity 분류 Line Summary 요약 Undefined file 미정의된 파일 [Inconclusive] [불확실] style 스타일 error 에러 warning 경고 performance 성능 portability 이식성 information 정보 debug 디버그 Copy filename 파일이름 복사 Copy full path 전체 경로 복사 Copy message 메시지 복사 Hide 숨기기 Cppcheck Cppcheck No editor application configured. Configure the editor application for Cppcheck in preferences/Applications. 편집기 미설정. [설정 - 응용 프로그램]에서 편집기를 설정하세요. No default editor application selected. Please select the default editor application in preferences/Applications. 기본 편집기 미선택. [설정 - 응용 프로그램]에서 기본 편집기를 선택하세요. Could not find the file! 파일을 찾을 수 없습니다! Could not start %1 Please check the application path and parameters are correct. %1을 시잘할 수 없습니다 경로와 인자가 정확한지 확인하세요. Could not find file: %1 Please select the directory where file is located. 파일 찾기 실패: %1 파일이 위치한 디렉토리를 선택하세요. Select Directory 디렉토리 선택 Id Copy message id Hide all with id ResultsView Results 결과 No errors found, nothing to save. 에러가 발견되지 않았고, 저장할 내용이 없습니다. Failed to save the report. 결과 저장 실패. %p% (%1 of %2 files checked) %p% (%2 중 %1 파일 검사됨) Cppcheck Cppcheck No errors found. 에러가 발견되지 않았습니다. Errors were found, but they are configured to be hidden. To toggle what kind of errors are shown, open view menu. 에러가 발견되었지만, 감추도록 설정되어 있습니다. 에러 종류를 표시하도록 설정하려면, 보기 메뉴를 선택하세요. Failed to read the report. 결과 불러오기 실패. Summary 요약 Message 내용 Id ScratchPad Scratchpad filename Check 검사 Settings Preferences 설정 General 일반 Number of threads: 쓰레드 수: Ideal count: 최적 값: Force checking all #ifdef configurations 모든 #ifdef 설정을 강제로 검사 Show full path of files 파일의 전체 경로 표시 Show "No errors found" message when no errors found 에러가 발견되지 않는 경우 "에러가 없습니다." 메시지 표시 Enable inline suppressions Inline suppression 사용 Paths 경로 Include paths: Include 경로: Add... 추가... Edit 편집 Remove 제거 Applications 응용 프로그램 Edit... 편집... Set as default 기본으로 지정 Reports 보고서 Save all errors when creating report 보고서 생성 시 모든 에러 저장 Save full path to files in reports 보고서에 파일의 전체 경로 저장 Language 언어 Advanced 고급 &Show inconclusive errors 불확실한 에러 표시(&S) S&how internal warnings in log 로그에 내부 경고 표시(&H) Display error Id in column "Id" SettingsDialog N/A N/A Add a new application 새 응용 프로그램 추가 Modify an application 응용 프로그램 편집 [Default] [기본] Select include directory Include 디렉토리 선택 StatsDialog Statistics 통계 Project 프로젝트 Project: 프로젝트: Paths: 경로: Include paths: Include 경로: Defines: Defines: Previous Scan 직전 검사 Path Selected: 선택된 경로: Number of Files Scanned: 검사된 파일 수: Scan Duration: 검사 시간: Errors: 에러: Warnings: 경고: Stylistic warnings: 스타일 경고: Portability warnings: 이식성 경고: Performance issues: 성능 경고: Information messages: 정보 메시지: Copy to Clipboard 클립보드에 복사 1 day 1일 %1 days %1일 1 hour 1시간 %1 hours %1시간 1 minute 1분 %1 minutes %1분 1 second 1초 %1 seconds %1초 0.%1 seconds 0.%1초 and Project Settings 프로젝트 설정 Paths 경로 Include paths Include 경로 Defines Defines Path selected 선택된 경로 Number of files scanned 검사된 파일 수 Scan duration 검사 시간 Errors 에러 Warnings 경고 Style warnings 스타일 경고 Portability warnings 이식성 경고 Performance warnings 성능 경고 Information messages 정보 메시지 ThreadResult %1 of %2 files checked %2 중 %1 파일 검사됨 TranslationHandler Failed to change the user interface language: %1 The user interface language has been reset to English. Open the Preferences-dialog to select any of the available languages. 언어 변경 실패: %1 언어가 영어로 초기화 됐습니다. 설정창을 열어서 설정 가능한 언어를 선택하세요. Cppcheck Cppcheck TxtReport inconclusive 불확실 cppcheck-1.61/gui/cppcheck_nl.ts000066400000000000000000001635251217722632100166450ustar00rootroot00000000000000 About About Cppcheck Over Cppcheck Version %1 Versie %1 Cppcheck - A tool for static C/C++ code analysis. Cppcheck - Een tool voor statische C/C++ code analyse. Copyright © 2007-2013 Daniel Marjamäki and cppcheck team. Copyright © 2007-2012 Daniel Marjamäki and cppcheck team. Copyright (C) 2007-2009 Daniel Marjamäki en het cppcheck. This program is licensed under the terms of the GNU General Public License version 3 Dit programma is beschikbaar onder te termen van de GNU General Public License versie 3 Visit Cppcheck homepage at %1 Bezoek de Cppcheck homepage op %1 ApplicationDialog Add an application Voeg een nieuwe applicatie toe Here you can add an application that can open error files. Specify a name for the application, the application executable and command line parameters for the application. The following texts in parameters are replaced with appropriate values when application is executed: (file) - Filename containing the error (line) - Line number containing the error (message) - Error message (severity) - Error severity Example opening a file with Kate and make Kate scroll to the correct line: Executable: kate Parameters: -l(line) (file) &Name: &Executable: &Parameters: Browse Bladeren Executable files (*.exe);;All files(*.*) Uitvoerbare bestanden (*.exe);;Alle bestanden(*.*) Select viewer application Selecteer applicatie Cppcheck Cppcheck You must specify a name, a path and optionally parameters for the application! FileViewDialog Could not find the file: %1 Could not find the file: Kon het bestand niet vinden: %1 Cppcheck Cppcheck Could not read the file: %1 Kon het bestand niet lezen: %1 LogView Checking Log Clear Save Log Text files (*.txt *.log);;All files (*.*) Cppcheck Cppcheck Could not open file for writing: "%1" MainWindow Cppcheck Cppcheck Standard Standaard &File &Bestand &View &Weergave &Toolbars &Check &Controleer C++ standard C standard &Edit Be&werken &License... &Licentie... A&uthors... A&uteurs... &About... &Over... &Files... &Bestanden... Check files Ctrl+F Ctrl+F &Directory... &Mappen... Check directory Ctrl+D Ctrl+D &Recheck files &Opnieuw controleren Ctrl+R Ctrl+R &Stop &Stop Stop checking Esc Esc &Save results to file... &Resultaten opslaan... Ctrl+S Ctrl+S &Quit &Afsluiten &Clear results &Resultaten wissen &Preferences &Voorkeuren Errors Show errors Show S&cratchpad... Warnings Show warnings Performance warnings Show performance warnings Show &hidden Information Show information messages Portability Show portability warnings &Filter Filter results Windows 32-bit ANSI Windows 32-bit Unicode Unix 32-bit Unix 64-bit Windows 64-bit Platforms C++11 C99 Posix C11 C89 C++03 &Check all &Selecteer alles Filter &Uncheck all Selecteer &niets Collapse &all Alles Inkl&appen &Expand all Alles &Uitklappen &Standard Standard items Toolbar &Categories Error categories &Open XML... Open P&roject File... &New Project File... &Log View Log View C&lose Project File &Edit Project File... &Statistics &Contents Categories Style warnings Show style warnings Open the help contents F1 &Help &Help Select directory to check Selecteer een map om te controleren No suitable files found to check! Geen geschikte bestanden gevonden om te controleren! Quick Filter: Found project file: %1 Do you want to load this project file instead? Found project files from the directory. Do you want to proceed checking without using any of these project files? License Licentie Authors Auteurs XML files version 2 (*.xml);;XML files version 1 (*.xml);;Text files (*.txt);;CSV files (*.csv) XML files (*.xml);;Text files (*.txt);;CSV files (*.csv) XML bestanden (*.xml);;Tekst bestanden (*.txt);;CSV bestanden (*.csv) Save the report file Rapport opslaan XML files (*.xml) XML bestanden (*.xml) There was a problem with loading the editor application settings. This is probably because the settings were changed between the Cppcheck versions. Please check (and fix) the editor application settings, otherwise the editor program might not start correctly. You must close the project file before selecting new files or directories! Select files to check Selecteer bestanden om te controleren Current results will be cleared. Opening a new XML file will clear current results.Do you want to proceed? Open the report file Checking is running. Do you want to stop the checking and exit Cppcheck?. XML files version 1 (*.xml) XML files version 2 (*.xml) Text files (*.txt) Tekst bestanden (*.txt) CSV files (*.csv) Cppcheck - %1 Cppcheck - %1 Project files (*.cppcheck);;All files(*.*) Select Project File Project: Select Project Filename No project file loaded The project file %1 could not be found! Do you want to remove the file from the recently used projects -list? Finnish Fins English Engels Chinese (Simplified) Dutch Nederlands French Italian Korean Spanish Swedish Zweeds German Duits Russian Russisch Japanese Japanease Serbian Cppcheck GUI. Syntax: cppcheck-gui [OPTIONS] [files or paths] Options: -h, --help Print this help -p <file> Open given project file and start checking it -l <file> Open given results xml file -d <directory> Specify the directory that was checked to generate the results xml specified with -l -v, --version Show program version Cppcheck GUI - Command line parameters Platforms Built-in Unix 32-bit Unix 64-bit Windows 32-bit ANSI Windows 32-bit Unicode Windows 64-bit Project Cppcheck Cppcheck Could not read the project file. Could not write the project file. ProjectFile Project File Project Root: Paths: Add... Edit Remove Includes Include directories: Up Down Exclude Defines: ProjectFileDialog Project file: %1 Select include directory Select a directory to check Select directory to ignore QDialogButtonBox OK Cancel Close Save QObject Unknown language specified! Language file %1 not found! Language file %1.qm not found! Kon het taalbestand niet vinden: %1! Failed to load translation for language %1 from file %2 Failed to load translation for language %1 from file %2.qm Kon de vertaling voor taal %1 in bestand %2 niet laden ResultsTree File Bestand Severity Ernst Line Regel Summary Undefined file Niet gedefinieerd bestand [Inconclusive] debug Copy filename Kopier bestandsnaam Copy full path Kopieer volledig pad Copy message Copy message id Hide Hide all with id Cppcheck Cppcheck No editor application configured. Configure the editor application for Cppcheck in preferences/Applications. Configure the text file viewer program in Cppcheck preferences/Applications. U dient een applicatie te configureren in de instellingen om deze fout in te openen. No default editor application selected. Please select the default editor application in preferences/Applications. Could not find the file! Could not start %1 Please check the application path and parameters are correct. Kon applicatie %1 niet starten Gelieve te controleren of de het pad en de parameters correct zijn. Could not find file: %1 Please select the directory where file is located. Select Directory Id style Stijlfouten error Fouten warning performance portability information ResultsView %p% (%1 of %2 files checked) Cppcheck Cppcheck No errors found. Geen fouten gevonden. Errors were found, but they are configured to be hidden. To toggle what kind of errors are shown, open view menu. Fouten werden gevonden, maar volgens de configuratie zijn deze verborgen. Gebruik het uitzicht menu om te selecteren welke fouten getoond worden. Failed to read the report. Summary Message Id No errors found, nothing to save. Geen fouten gevonden; geen data om op te slaan. Failed to save the report. Kon het rapport niet opslaan. Results Resultaten ScratchPad Scratchpad filename Check Settings Preferences Instellingen General Algemeen Include paths: Add... Number of threads: Aantal threads: Ideal count: Force checking all #ifdef configurations Check all #ifdef configurations Controleer alle #ifdef combinaties Show full path of files Toon het volledige pad van bestanden Show "No errors found" message when no errors found Toon "Geen fouten gevonden" indien geen fouten gevonden werden Display error Id in column "Id" Enable inline suppressions Paths Edit Remove Applications Applicaties Edit... Set as default Reports Rapporten Save all errors when creating report Alle fouten opslaan Save full path to files in reports Volledig pad opslaan Language Advanced &Show inconclusive errors S&how internal warnings in log SettingsDialog N/A Add a new application Nieuwe applicatie toevoegen Modify an application Applicatie wijzigen [Default] Select include directory StatsDialog Statistics Project Project: Paths: Include paths: Defines: Previous Scan Path Selected: Number of Files Scanned: Scan Duration: Errors: Warnings: Stylistic warnings: Portability warnings: Performance issues: Information messages: Copy to Clipboard 1 day %1 days 1 hour %1 hours 1 minute %1 minutes 1 second %1 seconds 0.%1 seconds and Project Settings Paths Include paths Defines Path selected Number of files scanned Scan duration Errors Warnings Style warnings Portability warnings Performance warnings Information messages ThreadResult %1 of %2 files checked TranslationHandler Failed to change the user interface language: %1 The user interface language has been reset to English. Open the Preferences-dialog to select any of the available languages. Cppcheck Cppcheck TxtReport inconclusive cppcheck-1.61/gui/cppcheck_ru.ts000066400000000000000000002017621217722632100166560ustar00rootroot00000000000000 About About Cppcheck О Cppcheck Version %1 Версия %1 Cppcheck - A tool for static C/C++ code analysis. Cppcheck - программа для статического анализа кода на языках С/С++. Copyright © 2007-2013 Daniel Marjamäki and cppcheck team. Copyright © 2007-2012 Daniel Marjamäki and cppcheck team. Copyright © 2007-2013 Daniel Marjamäki and cppcheck team. This program is licensed under the terms of the GNU General Public License version 3 Эта программа распространяется на условиях лицензии GNU General Public License, версии 3 Visit Cppcheck homepage at %1 Посетите домашнюю страницу: %1 ApplicationDialog Add an application Добавление приложения Here you can add an application that can open error files. Specify a name for the application, the application executable and command line parameters for the application. The following texts in parameters are replaced with appropriate values when application is executed: (file) - Filename containing the error (line) - Line number containing the error (message) - Error message (severity) - Error severity Example opening a file with Kate and make Kate scroll to the correct line: Executable: kate Parameters: -l(line) (file) Вы можете добавить приложение, которое можно будет использовать для открытия файла с ошибками. Задайте название приложения, путь до него и параметры командной строки. Следующие текстовые параметры будут заменены реальными значениями при запуске приложения: (file) - файл, содержащий ошибку (line) - номер строки с ошибкой (message) - текст ошибки (severity) - тип ошибки Пример открытия файла с помощью Kate (скролл переместится на нужную строчку): Программа: kate Параметры: -l(line) (file) &Name: &Название: &Executable: &Программа: &Parameters: &Параметры: Browse Просмотреть Executable files (*.exe);;All files(*.*) Выполняемые файлы (*.exe);;Все файлы(*.*) Select viewer application Выберите приложение Cppcheck Cppcheck You must specify a name, a path and optionally parameters for the application! Вы должны задать название и путь к приложению! FileViewDialog Could not find the file: %1 Could not find the file: Невозможно найти файл: %1 Cppcheck Cppcheck Could not read the file: %1 Невозможно прочитать файл: %1 LogView Checking Log Лог проверки Clear Очистить Save Log Сохранить Text files (*.txt *.log);;All files (*.*) Текстовые файлы (*.txt *.log);;Все файлы (*.*) Cppcheck Cppcheck Could not open file for writing: "%1" Не удалось записать в файл: "%1" MainWindow Cppcheck Cppcheck Standard Стандартные &File &Файл &View &Вид &Toolbars &Панель инструментов &Check &Проверить C++ standard Стандарт C++ C standard Стандарт C &Edit &Правка &License... &Лицензия... A&uthors... &Авторы... &About... &О программе... &Files... &Файлы... Check files Проверить файлы Ctrl+F Ctrl+F &Directory... &Каталог... Check directory Проверка директории Ctrl+D Ctrl+D &Recheck files &Перепроверить файлы Ctrl+R Ctrl+R &Stop Остановить Stop checking Остановить проверку Esc Esc &Save results to file... Сохранить отчёт в файл... Ctrl+S Ctrl+S &Quit Выход &Clear results Очистить отчёт &Preferences Параметры Errors Ошибки Show errors Показать ошибки Show S&cratchpad... Показать блокнот Warnings Предупреждения Show warnings Показать предупреждения Performance warnings Предупреждения производительности Show performance warnings Показать предупреждения производительности Show &hidden Показать скрытые Information Информационные сообщения Show information messages Показать информационные сообщения Portability Переносимость Show portability warnings Показать предупреждения переносимости &Filter Фильтры Filter results Результат фильтрации Windows 32-bit ANSI Windows 32-bit ANSI Windows 32-bit Unicode Windows 32-bit Unicode Unix 32-bit Unix 32-bit Unix 64-bit Unix 64-bit Windows 64-bit Windows 64-bit Platforms Платформы C++11 C++11 C99 C99 Posix Posix C11 C11 C89 C89 C++03 C++03 &Check all Отметить все Filter Фильтр &Uncheck all Сбросить все Collapse &all Свернуть все &Expand all Развернуть все &Standard Стандартные Standard items Стандартные элементы Toolbar Панель инструментов &Categories Категории Error categories Категории ошибок &Open XML... &Открыть XML... Open P&roject File... Открыть файл &проекта... &New Project File... &Новый файл проекта... &Log View Посмотреть &лог Log View Посмотреть лог C&lose Project File &Закрыть файл проекта &Edit Project File... &Изменить файл проекта... &Statistics &Статистика &Contents Помощь Categories Категории Style warnings Стилистические предупреждения Show style warnings Показать стилистические предупреждения Open the help contents Открыть помощь F1 F1 &Help Помощь Select directory to check Выберите каталог для проверки No suitable files found to check! Не найдено подходящих файлов для проверки! Quick Filter: Быстрый фильтр: Found project file: %1 Do you want to load this project file instead? Найден файл проекта: %1 Вы хотите загрузить этот проект? Found project files from the directory. Do you want to proceed checking without using any of these project files? Найдены файлы проекта из каталога. Вы хотите продолжить проверку, не используя ни одного из этих файлов проекта? License Лицензия Authors Авторы XML files version 2 (*.xml);;XML files version 1 (*.xml);;Text files (*.txt);;CSV files (*.csv) XML files (*.xml);;Text files (*.txt);;CSV files (*.csv) XML файлы версии 2 (*.xml);;XML файлы версии 1 (*.xml);;Текстовые файлы (*.txt);;CSV файлы (*.csv) Save the report file Сохранить файл с отчетом XML files (*.xml) XML-файлы (*.xml) There was a problem with loading the editor application settings. This is probably because the settings were changed between the Cppcheck versions. Please check (and fix) the editor application settings, otherwise the editor program might not start correctly. Возникла проблема при загрузке настроек программы. Возможно, это связано с изменениями в версии программы. Пожалуйста, проверьте (и исправьте) настройки приложения. You must close the project file before selecting new files or directories! Вы должны закрыть проект перед выбором новых файлов или директорий! Select files to check Выберите файлы для проверки Current results will be cleared. Opening a new XML file will clear current results.Do you want to proceed? Текущие результаты будут удалены. Открытые нового XML файла приведет к очистке текущих результатов. Продолжить? Open the report file Открыть файл с отчетом Checking is running. Do you want to stop the checking and exit Cppcheck?. Идет проверка. Вы хотите завершить проверку и выйти? XML files version 1 (*.xml) XML файлы версии 1 (*.xml) XML files version 2 (*.xml) XML файлы версии 2 (*.xml) Text files (*.txt) Текстовые файлы (*.txt) CSV files (*.csv) CSV файлы(*.csv) Cppcheck - %1 Cppcheck - %1 Failed to change the user interface language: %1 The user interface language has been reset to English. Open the Preferences-dialog to select any of the available languages. Failed to change the user interface language: %1 The user interface language has been reset to English. Open the Preferences-dialog to select any of the available languages. Project files (*.cppcheck);;All files(*.*) Файлы проекта (*.cppcheck);;Все файлы(*.*) Select Project File Выберите файл проекта Project: Проект: Select Project Filename Выберите имя файла для проекта No project file loaded Файл с проектом не загружен The project file %1 could not be found! Do you want to remove the file from the recently used projects -list? Файл с проектом %1 не найден! Хотите удалить его из списка проектов? Finnish Финский English Английский Chinese (Simplified) Китайский (упрощенный) Dutch Голландский French Французский Italian Итальянский Korean Корейский Spanish Испанский Swedish Шведский German Немецкий Russian Русский Japanese Japanease Японский Serbian Сербский Cppcheck GUI. Syntax: cppcheck-gui [OPTIONS] [files or paths] Options: -h, --help Print this help -p <file> Open given project file and start checking it -l <file> Open given results xml file -d <directory> Specify the directory that was checked to generate the results xml specified with -l -v, --version Show program version Cppcheck Графический Интерфейс Пользователя . Синтаксис: cppcheck-gui [ОПЦИИ] [файлы или пути] Опции: -h, --help Показать эту справку -p <file> Откройте данный файл проекта и начните проверять его -l <file> Откройте данные результаты xml файл -d <directory> Укажите каталог, который был проверен, чтобы генерировать результаты xml определенный с -l -v, --version Показать версию программы Cppcheck GUI - Command line parameters Cppcheck GUI - параметры Командной строки Platforms Built-in Встроенная Unix 32-bit Unix 32-bit Unix 64-bit Unix 64-bit Windows 32-bit ANSI Windows 32-bit ANSI Windows 32-bit Unicode Windows 32-bit Unicode Windows 64-bit Windows 64-bit Project Cppcheck Cppcheck Could not read the project file. Не удалось прочитать файл проекта. Could not write the project file. Не удалось записать файл проекта. ProjectFile Project File Файл проекта Project Проект Root: Корневая директория: Paths: Пути: Add... Добавить... Edit Изменить Remove Удалить Includes Пути для заголовочных файлов Include directories: Пути для поиска заголовочных файлов: Up Вверх Down Вниз Exclude Исключенные пути Defines: Макросы: ProjectFileDialog Project file: %1 Файл проекта: %1 Select include directory Выберите директорию для поиска заголовочных файлов Select a directory to check Выберите директорию для проверки Select directory to ignore Выберите директорию, которую надо проигнорировать QDialogButtonBox OK OK Cancel Отмена Close Закрыть Save Сохранить QObject Unknown language specified! Неизвестный язык! Language file %1 not found! Language file %1.qm not found! Языковой файл %1 не найден! Failed to load translation for language %1 from file %2 Failed to load translation for language %1 from file %2.qm Ошибка загрузки переводов для языка %1 из файла %2 ResultsTree File Файл Severity Важность Line Строка Summary Кратко Undefined file Неопределенный файл [Inconclusive] [Неубедительный] debug отлаживать Copy filename Скопировать имя файла Copy full path Скопировать полный путь Copy message Скопировать сообщение Copy message id Скопировать номер сообщения Hide Скрыть Hide all with id Скрыть все с id Cppcheck Cppcheck No editor application configured. Configure the editor application for Cppcheck in preferences/Applications. Configure the text file viewer program in Cppcheck preferences/Applications. Никакое приложение редактора не сконфигурировано. Сконфигурируйте приложение редактора для Cppcheck в предпочтениях/Приложениях. No default editor application selected. Please select the default editor application in preferences/Applications. Никакое приложение редактора по умолчанию не выбрано. Выберите приложение редактора по умолчанию в предпочтениях/Приложениях. Could not find the file! Не удается найти файл! Could not start %1 Please check the application path and parameters are correct. Не удалось запустить %1 Пожалуйста, проверьте путь приложения, и верны ли параметры. Could not find file: %1 Please select the directory where file is located. Не удается найти файл: %1 Пожалуйста, выберите каталог, в котором находится файл. Select Directory Выберите директорию Id Id style стиль error ошибка warning предупреждение performance производительность portability переносимость information информация ResultsView %p% (%1 of %2 files checked) %p% (%1 из %2 файлов проверено) Cppcheck Cppcheck No errors found. Ошибок не найдено. Errors were found, but they are configured to be hidden. To toggle what kind of errors are shown, open view menu. Были обнаружены ошибки, но они настроены быть скрыты. Для переключения какие ошибки отображаются, откройте меню представления. Failed to read the report. Не удалост прочитать отчет. Summary Кратко Message Сообщение Id Id No errors found, nothing to save. Ошибки не найдены, нечего сохранять. Failed to save the report. Не удалось сохранить отчет. Results Результаты ScratchPad Scratchpad Блокнот filename имя файла Check Проверить Settings Preferences Параметры General Общие Include paths: Пути для поиска заголовочных файлов: Add... Добавить... Number of threads: Количество потоков исполнения: Ideal count: Рекомендуемое значение: Force checking all #ifdef configurations Check all #ifdef configurations Проверять все варианты #ifdef конфигураций Show full path of files Показывать полные пути к файлам Show "No errors found" message when no errors found Показывать сообщение, если ошибок не найдено Display error Id in column "Id" Отображать номер ошибки в колонке "id" Enable inline suppressions Включить inline-подавление ошибок Paths Пути Edit Изменить Remove Удалить Applications Приложения Edit... Изменить... Set as default Установить по умолчанию Reports Отчёты Save all errors when creating report Сохранять все ошибки при создании отчёта Save full path to files in reports Сохранять полные пути к файлам в отчётах Language Язык Advanced Прочие &Show inconclusive errors &Показывать незначительные ошибки S&how internal warnings in log &Записывать внутренние предупреждения в лог SettingsDialog N/A Нет данных Add a new application Добавить новое приложение Modify an application Изменить приложение [Default] [По умолчанию] Select include directory Выберите директорию StatsDialog Statistics Статистика Project Проект Project: Проект: Paths: Пути: Include paths: Включенные пути: Defines: Макросы: Previous Scan Последние сканирование Path Selected: Выбранный путь: Number of Files Scanned: Количество просканированных файлов: Scan Duration: Продолжительность сканирования: Errors: Ошибки: Warnings: Предупреждения: Stylistic warnings: Стилистические предупреждения: Portability warnings: Предупреждения переносимости: Performance issues: Проблемы с производительностью: Information messages: Информационные сообщения: Copy to Clipboard Скопировать в буфер обмена 1 day 1 день %1 days %1 дней 1 hour 1 час %1 hours %1 часов 1 minute 1 минута %1 minutes %1 минут 1 second 1 секунда %1 seconds %1 секунд 0.%1 seconds 0.1%1 секунд and и Project Settings Настройки проекта Paths Пути Include paths Включенные пути Defines Макросы Path selected Выбранные пути Number of files scanned Количество просканированных файлов Scan duration Продолжительность сканирования Errors Ошибки Warnings Предупреждения Style warnings Стилистические предупреждения Portability warnings Предупреждения переносимости Performance warnings Предупреждения производительности Information messages Информационные сообщения ThreadResult %1 of %2 files checked %1 из %2 файлов проверены TranslationHandler Failed to change the user interface language: %1 The user interface language has been reset to English. Open the Preferences-dialog to select any of the available languages. Не удалось изменить язык пользовательского интерфейса: %1 Язык пользовательского интерфейса был сброшен на английский. Откройте Настройки-диалог для выбора любой из доступных языков. Cppcheck Cppcheck TxtReport inconclusive незначительная cppcheck-1.61/gui/cppcheck_sr.ts000066400000000000000000001643371217722632100166620ustar00rootroot00000000000000 About About Cppcheck About Cppcheck Version %1 Version %1 Cppcheck - A tool for static C/C++ code analysis. Cppcheck - A tool for static C/C++ code analysis. Copyright © 2007-2013 Daniel Marjamäki and cppcheck team. Copyright © 2007-2012 Daniel Marjamäki and cppcheck team. Copyright (C) 2007-2009 Daniel Marjamäki and cppcheck team. This program is licensed under the terms of the GNU General Public License version 3 This program is licensed under the terms of the GNU General Public License version 3 Visit Cppcheck homepage at %1 Visit Cppcheck homepage at %1 ApplicationDialog Add an application Add a new application Here you can add an application that can open error files. Specify a name for the application, the application executable and command line parameters for the application. The following texts in parameters are replaced with appropriate values when application is executed: (file) - Filename containing the error (line) - Line number containing the error (message) - Error message (severity) - Error severity Example opening a file with Kate and make Kate scroll to the correct line: Executable: kate Parameters: -l(line) (file) &Name: &Executable: &Parameters: Browse Browse Executable files (*.exe);;All files(*.*) Executable files (*.exe);;All files(*.*) Select viewer application Select viewer application Cppcheck Cppcheck You must specify a name, a path and optionally parameters for the application! FileViewDialog Could not find the file: %1 Could not find the file: %1 Cppcheck Cppcheck Could not read the file: %1 Could not read the file: %1 LogView Checking Log Clear Save Log Text files (*.txt *.log);;All files (*.*) Cppcheck Cppcheck Could not open file for writing: "%1" MainWindow Cppcheck Cppcheck Standard Standard &File &File &View &View &Toolbars &Check &Check C++ standard C standard &Edit &Edit &License... &License... A&uthors... A&uthors... &About... &About... &Files... &Files... Check files Ctrl+F Ctrl+F &Directory... &Directory... Check directory Ctrl+D Ctrl+D &Recheck files &Recheck files Ctrl+R Ctrl+R &Stop &Stop Stop checking Esc Esc &Save results to file... &Save results to file... Ctrl+S Ctrl+S &Quit &Quit &Clear results &Clear results &Preferences &Preferences Errors Show errors Show S&cratchpad... Warnings Show warnings Performance warnings Show performance warnings Show &hidden Information Show information messages Portability Show portability warnings &Filter Filter results Windows 32-bit ANSI Windows 32-bit ANSI Windows 32-bit Unicode Windows 32-bit Unicode Unix 32-bit Unix 32-bit Unix 64-bit Unix 64-bit Windows 64-bit Windows 64-bit Platforms C++11 C++11 C99 C99 Gtk Gtk Posix Posix C11 C11 C89 C89 C++03 C++03 &Check all &Check all Filter &Uncheck all &Uncheck all Collapse &all Collapse &all &Expand all &Expand all &Standard Standard items Toolbar &Categories Error categories &Open XML... Open P&roject File... &New Project File... &Log View Log View C&lose Project File &Edit Project File... &Statistics &Contents Categories Style warnings Show style warnings Open the help contents F1 F1 &Help &Help Select directory to check Select directory to check No suitable files found to check! No suitable files found to check! Quick Filter: Found project file: %1 Do you want to load this project file instead? Found project files from the directory. Do you want to proceed checking without using any of these project files? License License Authors Authors XML files version 2 (*.xml);;XML files version 1 (*.xml);;Text files (*.txt);;CSV files (*.csv) XML files (*.xml);;Text files (*.txt);;CSV files (*.csv) Save the report file Save the report file XML files (*.xml) XML files (*.xml) There was a problem with loading the editor application settings. This is probably because the settings were changed between the Cppcheck versions. Please check (and fix) the editor application settings, otherwise the editor program might not start correctly. You must close the project file before selecting new files or directories! Select files to check Select files to check Current results will be cleared. Opening a new XML file will clear current results.Do you want to proceed? Open the report file Checking is running. Do you want to stop the checking and exit Cppcheck?. XML files version 1 (*.xml) XML files version 2 (*.xml) Text files (*.txt) Text files (*.txt) CSV files (*.csv) Cppcheck - %1 Cppcheck - %1 Project files (*.cppcheck);;All files(*.*) Select Project File Project: Select Project Filename No project file loaded The project file %1 could not be found! Do you want to remove the file from the recently used projects -list? Finnish Finski English Engleski Chinese (Simplified) Kineski (Pojednostavljeni) Dutch Holandski French Francuski Italian Italijanski Korean Korejski Spanish Španski Swedish Švedski German Nemački Russian Ruski Japanese Japanski Serbian Srpski Cppcheck GUI. Syntax: cppcheck-gui [OPTIONS] [files or paths] Options: -h, --help Print this help -p <file> Open given project file and start checking it -l <file> Open given results xml file -d <directory> Specify the directory that was checked to generate the results xml specified with -l -v, --version Show program version Cppcheck GUI - Command line parameters Platforms Built-in Unix 32-bit Unix 32-bit Unix 64-bit Unix 64-bit Windows 32-bit ANSI Windows 32-bit ANSI Windows 32-bit Unicode Windows 32-bit Unicode Windows 64-bit Windows 64-bit Project Cppcheck Cppcheck Could not read the project file. Could not write the project file. ProjectFile Project File Project Root: Paths: Add... Edit Remove Includes Include directories: Up Down Exclude Defines: ProjectFileDialog Project file: %1 Select include directory Select a directory to check Select directory to ignore QDialogButtonBox OK Cancel Close Save QObject Unknown language specified! Language file %1 not found! Could not find the file: %1! Failed to load translation for language %1 from file %2 Failed to load translation for language %1 from file %2 ResultsTree File File Severity Severity Line Line Summary Undefined file Undefined file [Inconclusive] debug Copy filename Copy filename Copy full path Copy full path Copy message Copy message id Hide Hide all with id Cppcheck Cppcheck No editor application configured. Configure the editor application for Cppcheck in preferences/Applications. You can open this error by specifying applications in program's settings. No default editor application selected. Please select the default editor application in preferences/Applications. Could not find the file! Could not start %1 Please check the application path and parameters are correct. Could not start %1 Please check the application path and parameters are correct. Could not find file: %1 Please select the directory where file is located. Select Directory Id style Style error Error warning performance portability information ResultsView %p% (%1 of %2 files checked) Cppcheck Cppcheck No errors found. No errors found. Errors were found, but they are configured to be hidden. To toggle what kind of errors are shown, open view menu. Errors were found, but they are configured to be hidden. To toggle what kind of errors are shown, open view menu. Failed to read the report. Summary Message Id No errors found, nothing to save. No errors found, nothing to save. Failed to save the report. Failed to save the report. Results Results ScratchPad Scratchpad filename Check Settings Preferences Preferences General General Include paths: Add... Number of threads: Number of threads: Ideal count: Force checking all #ifdef configurations Check all #ifdef configurations Show full path of files Show full path of files Show "No errors found" message when no errors found Show "No errors found" message when no errors found Display error Id in column "Id" Enable inline suppressions Paths Edit Remove Applications Applications Edit... Set as default Reports Reports Save all errors when creating report Save all errors when creating report Save full path to files in reports Save full path to files in reports Language Advanced &Show inconclusive errors S&how internal warnings in log SettingsDialog N/A Add a new application Add a new application Modify an application Modify an application [Default] Select include directory StatsDialog Statistics Project Project: Paths: Include paths: Defines: Previous Scan Path Selected: Number of Files Scanned: Scan Duration: Errors: Warnings: Stylistic warnings: Portability warnings: Performance issues: Information messages: Copy to Clipboard 1 day %1 days 1 hour %1 hours 1 minute %1 minutes 1 second %1 seconds 0.%1 seconds and Project Settings Paths Include paths Defines Path selected Number of files scanned Scan duration Errors Warnings Style warnings Portability warnings Performance warnings Information messages ThreadResult %1 of %2 files checked TranslationHandler Failed to change the user interface language: %1 The user interface language has been reset to English. Open the Preferences-dialog to select any of the available languages. Cppcheck Cppcheck TxtReport inconclusive cppcheck-1.61/gui/cppcheck_sv.ts000066400000000000000000001665431217722632100166670ustar00rootroot00000000000000 About About Cppcheck Om Cppcheck Version %1 Version %1 Cppcheck - A tool for static C/C++ code analysis. Cppcheck - Ett verktyg för statisk analys av C/C++ kod. Copyright © 2007-2013 Daniel Marjamäki and cppcheck team. Copyright © 2007-2012 Daniel Marjamäki and cppcheck team. Copyright (C) 2007-2013 Daniel Marjamäki and cppcheck team. This program is licensed under the terms of the GNU General Public License version 3 This program is licensed under the terms of the GNU General Public License version 3 Visit Cppcheck homepage at %1 Hemsida: %1 ApplicationDialog Add an application Lägg till program Here you can add an application that can open error files. Specify a name for the application, the application executable and command line parameters for the application. The following texts in parameters are replaced with appropriate values when application is executed: (file) - Filename containing the error (line) - Line number containing the error (message) - Error message (severity) - Error severity Example opening a file with Kate and make Kate scroll to the correct line: Executable: kate Parameters: -l(line) (file) Här kan du ange en applikation som kan användas för att visa fel. Ange applikationens namn, körbara fil samt kommandorads parametrar. Följande texter i parametrarna ersätts med motsvarande värden när applikationen körs: (file) - filnamn för källkodsfil (line) - radnummer (message) - felmeddelande (severity) - typ / svårighetsgrad Exempel för att öppna en fil med Kate och ange att Kate skall skrolla till rätt rad: Körbar fil: kate Parametrar: -l(line) (file) &Name: Namn: &Executable: Körbar fil: &Parameters: Parametrar: Browse Bläddra Executable files (*.exe);;All files(*.*) Exekverbara filer (*.exe);;Alla filer(*.*) Select viewer application Välj program Cppcheck Cppcheck You must specify a name, a path and optionally parameters for the application! Du måste ange namn, sökväg samt eventuellt parametrar för applikationen! You must specify a name, a path and parameters for the application! Du måste ange ett namn, en sökväg samt parametrar för programmet! FileViewDialog Could not find the file: %1 Could not find the file: Kunde inte hitta filen: %1 Cppcheck Cppcheck Could not read the file: %1 Kunde inte läsa filen: %1 LogView Checking Log Analys logg &Save &Spara Clear Töm Close Stäng Save Log Spara logg Text files (*.txt *.log);;All files (*.*) Text filer (*.txt *.log);;Alla filer (*.*) Cppcheck Cppcheck Could not open file for writing: "%1" Kunde ej öppna fil för skrivning: "%1" MainWindow Cppcheck Cppcheck Standard Standard &File &Arkiv &View &Visa &Toolbars Verktygsfält &Check &Check C++ standard C++ standard C standard C standard &Edit &Redigera &License... &Licens... A&uthors... &Utvecklat av... &About... &Om... &Files... &Filer... Check files Analysera filer Ctrl+F Ctrl+F &Directory... &Katalog... Check directory Analysera mapp Ctrl+D Ctrl+D &Recheck files Starta &om check Ctrl+R Ctrl+R &Stop &Stoppa Stop checking Stoppa analys Esc Esc &Save results to file... &Spara resultat till fil... Ctrl+S Ctrl+S &Quit &Avsluta &Clear results &Töm resultat &Preferences &Inställningar Errors Fel Show errors Visa fel Show S&cratchpad... Visa s&cratchpad... Warnings Varningar Show warnings Visa varningar Performance warnings Prestanda varningar Show performance warnings Visa prestanda varningar Show &hidden Visa dolda Information Information Show information messages Visa informations meddelanden Portability Portabilitet Show portability warnings Visa portabilitets varningar &Filter &Filter Filter results Filtrera resultat Windows 32-bit ANSI Windows 32-bit ANSI Windows 32-bit Unicode Windows 32-bit Unicode Unix 32-bit Unix 32-bit Unix 64-bit Unix 64-bit Windows 64-bit Windows 64-bit Platforms Plattformar C++11 C++11 C99 C99 Posix Posix C11 C11 C89 C89 C++03 C++03 &Check all &Kryssa alla Filter Filter &Uncheck all Kryssa &ur alla Collapse &all Ingen bra översättning! &Fäll ihop alla &Expand all &Expandera alla &Standard &Standard Standard items Standard poster Toolbar Verktygsfält &Categories &Kategorier Error categories Fel kategorier &Open XML... &Öppna XML... Open P&roject File... Öppna Projektfil... &New Project File... Ny projektfil... &Log View Log View Logg vy C&lose Project File Stäng projektfil &Edit Project File... Redigera projektfil... &Statistics Statistik &Contents &Innehåll Categories Kategorier Style warnings Stil varningar Show style warnings Visa stil varningar Open the help contents Öppna hjälp F1 F1 &Help &Hjälp Select directory to check Välj katalog som skall kontrolleras No suitable files found to check! Inga lämpliga filer hittades! Quick Filter: Snabbfilter: Found project file: %1 Do you want to load this project file instead? Hittade projektfil: %1 Vill du ladda denna projektfil istället? Found project files from the directory. Do you want to proceed checking without using any of these project files? Hittade projektfil(er) i mappen. Vill du fortsätta analysen utan att använda någon av dessa projektfiler? License Licens Authors Utvecklare XML files version 2 (*.xml);;XML files version 1 (*.xml);;Text files (*.txt);;CSV files (*.csv) XML files (*.xml);;Text files (*.txt);;CSV files (*.csv) XML filer version 2 (*.xml);;XML filer version 1 (*.xml);;Text filer (*.txt);;CSV filer (*.csv) Save the report file Spara rapport XML files (*.xml) XML filer (*.xml) There was a problem with loading the editor application settings. This is probably because the settings were changed between the Cppcheck versions. Please check (and fix) the editor application settings, otherwise the editor program might not start correctly. Det uppstod ett problem när programinställningarna skulle laddas. En trolig orsak är att inställningarna ändrats för olika Cppcheck versioner. Kontrollera programinställningarna. You must close the project file before selecting new files or directories! Du måste stänga projektfilen innan nya filer eller sökvägar kan väljas! Select files to check Välj filer att kontrollera Current results will be cleared. Opening a new XML file will clear current results.Do you want to proceed? Nuvarande resultat kommer rensas bort. När en ny XML fil öppnas så tas alla nuvarande resultat bort. Vill du fortsätta? Open the report file Öppna rapportfilen Checking is running. Do you want to stop the checking and exit Cppcheck?. Cppcheck kör. Vill du stoppa analysen och avsluta Cppcheck? XML files version 1 (*.xml) XML filer version 1 (*.xml) XML files version 2 (*.xml) XML filer version 2 (*.xml) Text files (*.txt) Text filer (*.txt) CSV files (*.csv) CSV filer (*.csv) Cppcheck - %1 Cppcheck - %1 Failed to change the user interface language: %1 The user interface language has been reset to English. Open the Preferences-dialog to select any of the available languages. Misslyckades att ändra språk: %1 Språket har nollställts till Engelska. Öppna Preferences och välj något av de tillgängliga språken. Project files (*.cppcheck);;All files(*.*) Projektfiler (*.cppcheck);;Alla filer(*.*) Select Project File Välj projektfil Project: Projekt: Select Project Filename Välj Projektfil No project file loaded Inget projekt laddat The project file %1 could not be found! Do you want to remove the file from the recently used projects -list? Projektfilen %1 kunde inte hittas! Vill du ta bort filen från 'senast använda projekt'-listan? Finnish Finska English Engelska Chinese (Simplified) Kinesiska (Förenklad) Dutch Nederländska French Franska Italian Italienska Korean Koreanska Spanish Spanska Swedish Svenska German Tyska Russian Ryska Japanese Japanease Japanska Serbian Serbiska Cppcheck GUI. Syntax: cppcheck-gui [OPTIONS] [files or paths] Options: -h, --help Print this help -p <file> Open given project file and start checking it -l <file> Open given results xml file -d <directory> Specify the directory that was checked to generate the results xml specified with -l -v, --version Show program version Cppcheck GUI. Syntax: cppcheck-gui [OPTIONS] [files or paths] Options: -h, --help Print this help -p <file> Open given project file and start checking it -l <file> Open given results xml file -d <directory> Specify the directory that was checked to generate the results xml specified with -l -v, --version Show program version Cppcheck GUI - Command line parameters Cppcheck GUI - Command line parameters Platforms Built-in Generell Unix 32-bit Unix 32-bit Unix 64-bit Unix 64-bit Windows 32-bit ANSI Windows 32-bit ANSI Windows 32-bit Unicode Windows 32-bit Unicode Windows 64-bit Windows 64-bit Project Cppcheck Cppcheck Could not read the project file. Kunde ej läsa projektfilen. Could not write the project file. Kunde ej skriva projektfilen ProjectFile Project File Projektfil Project Projekt Root: Rot: Paths: Sökvägar: Add... Lägg till... Edit Redigera Remove Ta bort Includes Include Include directories: Include sökvägar Up Upp Down Ned Exclude Exkludera Defines: Defines: ProjectFileDialog Project file: %1 Projektfil: %1 Select include directory Välj include sökväg Select a directory to check Välj mapp att analysera Select directory to ignore Välj sökväg att ignorera QDialogButtonBox OK OK Cancel Avbryt Close Stäng Save Spara QObject Unknown language specified! Okänt språk valt! Language file %1 not found! Language file %1.qm not found! Språk filen %1 hittades ej! Failed to load translation for language %1 from file %2 Failed to load translation for language %1 from file %2.qm Misslyckades med att ladda översättningen för %1 från filen %2 ResultsTree File Fil Severity Typ Line Rad Summary Sammanfattning Undefined file Odefinierad fil [Inconclusive] [Inconclusive] debug debug Copy filename Kopiera filnamn Copy full path Kopiera full sökväg Copy message Kopiera meddelande Copy message id Kopiera meddelande id Hide Dölj Hide all with id Dölj alla med id Cppcheck Cppcheck No editor application configured. Configure the editor application for Cppcheck in preferences/Applications. Configure the text file viewer program in Cppcheck preferences/Applications. Ingen editor konfigurerad. Konfigurera program i inställningar/program. No default editor application selected. Please select the default editor application in preferences/Applications. Ingen standard editor vald. Vänligen välj standard editor i inställningar/Program. Could not find the file! Kunde inte hitta filen! Could not start %1 Please check the application path and parameters are correct. Kunde inte starta %1 Kontrollera att sökvägen och parametrarna är korrekta. Could not find file: %1 Please select the directory where file is located. Kunde inte hitta filen: %1 Välj mappen där filen finns. Select Directory Välj mapp Id Id style stil error fel warning varning performance prestanda portability portabilitet information information ResultsView %p% (%1 of %2 files checked) %p% (%1 av %2 filer analyserade) Cppcheck Cppcheck No errors found. Inga fel hittades. Errors were found, but they are configured to be hidden. To toggle what kind of errors are shown, open view menu. Fel hittades, men de visas ej. För att ställa in vilka fel som skall visas använd visa menyn. Failed to read the report. Misslyckades att läsa rapporten. Summary Sammanfattning Message Meddelande Id Id No errors found, nothing to save. Inga fel hittades, ingenting att spara. Failed to save the report. Misslyckades med att spara rapporten. Results Resultat ScratchPad Scratchpad Scratchpad filename Filnamn Check Analysera Settings Preferences Inställningar General Allmänt Include paths: Include sökvägar: Add... Lägg till... Number of threads: Antal trådar: Ideal count: Optimalt värde: Force checking all #ifdef configurations Check all #ifdef configurations Kontrollera alla #ifdef konfigurationer Show full path of files Visa den fulla sökvägen för filer Show "No errors found" message when no errors found Visa "Inga fel hittades" meddelande när inga fel hittas Display error Id in column "Id" Visa meddelande id i kolumn "Id" Enable inline suppressions Använd inline suppressions Paths Sökvägar Edit Redigera Remove Ta bort Applications Program Edit... Redigera... Set as default Sätt förvald Reports Rapporter Save all errors when creating report Spara alla fel Save full path to files in reports Spara fulla sökvägar Language Språk Advanced Avancerade &Show inconclusive errors Visa inconclusive meddelanden S&how internal warnings in log Visa interna fel i loggen SettingsDialog N/A Ej tillgängligt Add a new application Lägg till program Modify an application Ändra program [Default] [Förvald] Select include directory Välj include mapp StatsDialog Statistics Statistik Project Projekt Project: Projekt: Paths: Sökvägar: Include paths: Include sökvägar: Defines: Defines: Previous Scan Föregående analys Path Selected: Vald sökväg: Number of Files Scanned: Antal analyserade filer: Scan Duration: Analys tid: Errors: Fel: Warnings: Varningar: Stylistic warnings: Stil varningar: Portability warnings: Portabilitets varningar: Performance issues: Prestanda varningar: Information messages: Informations meddelanden: Copy to Clipboard Kopiera 1 day 1 dag %1 days %1 dagar 1 hour 1 timme %1 hours %1 timmar 1 minute 1 minut %1 minutes %1 minuter 1 second 1 sekund %1 seconds %1 sekunder 0.%1 seconds 0.%1 sekunder and och Project Settings Projekt inställningar Paths Sökvägar Include paths Include sökvägar Defines Definitioner Path selected Vald sökväg Number of files scanned Antal analyserade filer Scan duration Tid Errors Fel Warnings Varningar Style warnings Stil varningar Portability warnings Portabilitetsvarningar Performance warnings Prestanda varningar Information messages Informationsmeddelanden ThreadResult %1 of %2 files checked %1 av %2 filer analyserade TranslationHandler Failed to change the user interface language: %1 The user interface language has been reset to English. Open the Preferences-dialog to select any of the available languages. Misslyckades att ändra språk: %1 Språket har nollställts till Engelska. Öppna Preferences och välj något av de tillgängliga språken. Cppcheck Cppcheck TxtReport inconclusive inconclusive cppcheck-1.61/gui/cppcheck_zh_CN.ts000066400000000000000000001643141217722632100172320ustar00rootroot00000000000000 About About Cppcheck 关于 Cppcheck Version %1 版本 %1 Cppcheck - A tool for static C/C++ code analysis. Cppcheck - C/C++ 静态代码分析工具。 Copyright © 2007-2013 Daniel Marjamäki and cppcheck team. Copyright © 2007-2012 Daniel Marjamäki and cppcheck team. 版权所有 © 2007-2012 Daniel Marjamäki 与 Cppcheck 团队。 This program is licensed under the terms of the GNU General Public License version 3 该程序在 GNU 通用公共授权版本 3 的条款下发布 Visit Cppcheck homepage at %1 访问 Cppcheck 主页: %1 ApplicationDialog Add an application 添加应用程序 Here you can add an application that can open error files. Specify a name for the application, the application executable and command line parameters for the application. The following texts in parameters are replaced with appropriate values when application is executed: (file) - Filename containing the error (line) - Line number containing the error (message) - Error message (severity) - Error severity Example opening a file with Kate and make Kate scroll to the correct line: Executable: kate Parameters: -l(line) (file) 在这里,你可以添加一个应用程序,用于打开错误文件。请为该应用程序指定一个名称、可执行文件和命令行参数。 当应用程序执行时,在参数中的以下文本将会替换为适当的值: (file) - 包含错误的文件名称 (line) - 包含错误的行号 (message) - 错误消息 (severity) - 错误严重性 示例:使用 Kate 打开一个文件,并使之滚动到相应的行: 可执行文件: kate 参数: -l(line) (file) &Name: 名称(&N): &Executable: 可执行文件(&E): &Parameters: 参数(&P): Browse 浏览 Executable files (*.exe);;All files(*.*) 可执行文件(*.exe);;所有文件(*.*) Select viewer application 选择查看应用程序 Cppcheck Cppcheck You must specify a name, a path and optionally parameters for the application! 你必须为应用程序指定名称、路径以及可选参数! FileViewDialog Could not find the file: %1 无法找到文件: %1 Cppcheck Cppcheck Could not read the file: %1 无法读取文件: %1 LogView Checking Log 正在检查记录 Clear 清空 Save Log 保存记录 Text files (*.txt *.log);;All files (*.*) 文本文件(*.txt *.log);;所有文件(*.*) Cppcheck Cppcheck Could not open file for writing: "%1" 无法打开并写入文件: “%1” MainWindow Cppcheck Cppcheck &File 文件(&F) &View 查看(&V) &Toolbars 工具栏(&T) &Help 帮助(&H) &Check 检查(&C) C++ standard C standard &Edit 编辑(&E) Standard 标准 Categories 分类 &License... 许可证(&L)... A&uthors... 作者(&U)... &About... 关于(&A)... &Files... 文件(&F)... Check files 检查文件 Ctrl+F Ctrl+F &Directory... 目录(&D)... Check directory 检查目录 Ctrl+D Ctrl+D &Recheck files 重新检查文件(&R) Ctrl+R Ctrl+R &Stop 停止(&S) Stop checking 停止检查 Esc Esc &Save results to file... 保存结果到文件(&S)... Ctrl+S Ctrl+S &Quit 退出(&Q) &Clear results 清空结果(&C) &Preferences 首选项(&P) Style warnings 风格警告 Show style warnings 显示风格警告 Errors 错误 Show errors 显示错误 Show S&cratchpad... 显示便条(&C)... Information 信息 Show information messages 显示信息消息 Portability 移植可能性 Show portability warnings 显示可移植性警告 &Filter 滤器(&F) Filter results 过滤结果 Windows 32-bit ANSI Windows 32-bit Unicode Unix 32-bit Unix 64-bit Windows 64-bit Platforms 平台 C++11 C++11 C99 C99 Posix Posix C11 C11 C89 C89 C++03 C++03 C&lose Project File 关闭项目文件(&L) &Edit Project File... 编辑项目文件(&E)... &Statistics 统计(&S) Warnings 警告 Show warnings 显示警告 Performance warnings 性能警告 Show performance warnings 显示性能警告 Show &hidden 显示隐藏项(&H) &Check all 全部选中(&C) Filter 滤器 &Uncheck all 全部取消选中(&U) Collapse &all 全部折叠(&A) &Expand all 全部展开(&E) &Standard 标准(&S) Standard items 标准项 &Contents 内容(&C) Open the help contents 打开帮助内容 F1 F1 Toolbar 工具栏 &Categories 分类(&C) Error categories 错误分类 &Open XML... 打开 XML (&O)... Open P&roject File... 打开项目文件(&R)... &New Project File... 新建项目文件(&N)... &Log View 日志视图(&L) Log View 日志视图 There was a problem with loading the editor application settings. This is probably because the settings were changed between the Cppcheck versions. Please check (and fix) the editor application settings, otherwise the editor program might not start correctly. 加载编辑器应用程序设置出错。 这可能是因为 Cppcheck 不同版本间的设置有所不同。请检查(并修复)编辑器应用程序设置,否则编辑器程序可能不会正确启动。 No suitable files found to check! 未发现适合检查的文件! You must close the project file before selecting new files or directories! 在选择新的文件或目录之前,你必须先关闭此项目文件! Select directory to check 选择目录来检查 Quick Filter: 快速滤器: Select files to check 选择要检查的文件 Found project file: %1 Do you want to load this project file instead? 找到项目文件: %1 你是否想加载该项目文件? Found project files from the directory. Do you want to proceed checking without using any of these project files? 在目录中找到项目文件。 你是否想在不使用这些项目文件的情况下,执行检查? Current results will be cleared. Opening a new XML file will clear current results.Do you want to proceed? 当前结果将被清空。 打开一个新的 XML 文件将会清空当前结果。你要继续吗? XML files (*.xml) XML 文件(*.xml) Open the report file 打开报告文件 Checking is running. Do you want to stop the checking and exit Cppcheck?. 检查正在执行。 你是否需要停止检查并退出 Cppcheck? License 许可证 Authors 作者 XML files version 2 (*.xml);;XML files version 1 (*.xml);;Text files (*.txt);;CSV files (*.csv) XML files (*.xml);;Text files (*.txt);;CSV files (*.csv) XML 文件版本 2 (*.xml);;XML 文件版本 1 (*.xml);; 文本文件(*.txt);; CSV 文件(*.csv) Save the report file 保存报告文件 XML files version 1 (*.xml) XML 文件版本 1 (*.xml) XML files version 2 (*.xml) XML 文件版本 2 (*.xml) Text files (*.txt) 文本文件(*.txt) CSV files (*.csv) CSV 文件(*.csv) Cppcheck - %1 Cppcheck - %1 Failed to change the user interface language: %1 The user interface language has been reset to English. Open the Preferences-dialog to select any of the available languages. 更改用户界面语言失败: %1 用户界面语言已被重置为英语。打开“首选项”对话框,选择任何可用的语言。 Project files (*.cppcheck);;All files(*.*) 项目文件(*.cppcheck);;所有文件(*.*) Select Project File 选择项目文件 Project: 项目: Select Project Filename 选择项目文件名 No project file loaded 项目文件未加载 The project file %1 could not be found! Do you want to remove the file from the recently used projects -list? 项目文件 %1 未找到! 你要从最近使用的项目列表中删除此文件吗? English 英語 Dutch 荷兰语 Chinese (Simplified) Finnish 芬兰语 French 法语 Italian 意大利语 Korean 韩文 Spanish 西班牙语 Swedish 瑞典语 German 德语 Russian 俄语 Japanese Japanease 日语 Serbian 塞尔维亚语 Cppcheck GUI. Syntax: cppcheck-gui [OPTIONS] [files or paths] Options: -h, --help Print this help -p <file> Open given project file and start checking it -l <file> Open given results xml file -d <directory> Specify the directory that was checked to generate the results xml specified with -l -v, --version Show program version Cppcheck GUI - Command line parameters Platforms Built-in 内置 Unix 32-bit Unix 64-bit Windows 32-bit ANSI Windows 32-bit Unicode Windows 64-bit Project Cppcheck Cppcheck Could not read the project file. 无法读取项目文件。 Could not write the project file. 无法写入项目文件。 ProjectFile Project File 项目文件 Project 项目 Root: 根目录: Paths: 路径: Add... 添加... Edit 编辑 Remove 移除 Includes 包含 Include directories: Include 目录: Up 向上 Down 向下 Exclude 排除 Defines: 定义: ProjectFileDialog Project file: %1 项目文件: %1 Select include directory 选择 Include 目录 Select a directory to check 选择一个检查目录 Select directory to ignore 选择忽略的目录 QDialogButtonBox OK Cancel Close 关闭 Save QObject Unknown language specified! 指定了未知语言! Language file %1 not found! 语言文件 %1 不存在! Failed to load translation for language %1 from file %2 无法从文件 %2 中为语言 %1 加载翻译文件 ResultsTree File 文件 Severity 严重性 Line Summary 概要 Undefined file 未定义文件 [Inconclusive] [不确定的] debug 调试 Copy filename 复制文件名 Copy full path 复制完整路径 Copy message 复制消息 Copy message id 复制消息 ID Hide 隐藏 Hide all with id Cppcheck Cppcheck No editor application configured. Configure the editor application for Cppcheck in preferences/Applications. Configure the text file viewer program in Cppcheck preferences/Applications. 编辑应用程序未配置。 在“首先项 / 应用程序”中为 Cppcheck 配置编辑应用程序。 No default editor application selected. Please select the default editor application in preferences/Applications. 未选中默认编辑应用程序。 请在“首先项 / 应用程序”中选择默认应用程序。 Could not find the file! 找不到文件! Could not start %1 Please check the application path and parameters are correct. 无法启动 %1 请检查此应用程序的路径与参数是否正确。 Could not find file: %1 Please select the directory where file is located. 无法找到文件: %1 请选择文件所在目录。 Select Directory 选择目录 Id Id style 风格 error 错误 warning 警告 performance 性能 portability 移植可能性 information 信息 ResultsView Results 结果 No errors found, nothing to save. 未发现错误,没有结果可保存。 Failed to save the report. 保存报告失败。 %p% (%1 of %2 files checked) %p% (%2 个文件已检查 %1 个) Cppcheck Cppcheck No errors found. 未发现错误。 Errors were found, but they are configured to be hidden. To toggle what kind of errors are shown, open view menu. 发现错误,但它们被设为隐藏。 打开“查看”菜单,切换需要显示的错误。 Failed to read the report. 读取报告失败。 Summary 概要 Message 消息 Id Id ScratchPad Scratchpad 便条 filename 文件名 Check 检查 Settings Preferences 首选项 General 常规 Include paths: Include 路径: Add... 添加... Number of threads: 线程个数: Ideal count: 理想个数: Force checking all #ifdef configurations Check all #ifdef configurations 强制检查所有 #ifdef 配置 Show full path of files 显示文件的完整路径 Show "No errors found" message when no errors found 当未找到错误,显示“未发现错误”消息 Display error Id in column "Id" 在列“Id”中显示错误 Id Enable inline suppressions 启用内联方案 Paths 路径 Edit 编辑 Remove 移除 Applications 应用程序 Edit... 编辑... Set as default 设为默认 Reports 报告 Save all errors when creating report 创建报告时,保存所有错误 Save full path to files in reports 在报告中保存文件的完整路径 Language 语言 Advanced 高级 &Show inconclusive errors 显示不确定的错误(&S) S&how internal warnings in log 在日记中显示内部警告(&H) SettingsDialog N/A N/A Add a new application 添加一个新的应用程序 Modify an application 修改一个应用程序 [Default] [默认] Select include directory 选择包含目录 StatsDialog Statistics 统计 Project 项目 Project: 项目: Paths: 路径: Include paths: 包含路径: Defines: 定义: Previous Scan 上一次扫描 Path Selected: 选中的路径: Number of Files Scanned: 扫描的文件数: Scan Duration: 扫描时间: Errors: 错误: Warnings: 警告: Stylistic warnings: Stylistic 警告: Portability warnings: 可移植性警告: Performance issues: 性能警告: Information messages: 信息: Copy to Clipboard 复制到剪贴板 1 day 1 天 %1 days %1 天 1 hour 1 小时 %1 hours %1 小时 1 minute 1 分钟 %1 minutes %1 分钟 1 second 1 秒 %1 seconds %1 秒 0.%1 seconds 0.%1 秒 and Project Settings 项目设置 Paths 路径 Include paths 包含路径 Defines 定义 Path selected 选中的路径 Number of files scanned 扫描的文件数 Scan duration 扫描时间 Errors 错误 Warnings 警告 Style warnings 风格警告 Portability warnings 移植可能性警告 Performance warnings 性能警告 Information messages 信息 ThreadResult %1 of %2 files checked %2 个文件已检查 %1 个 TranslationHandler Failed to change the user interface language: %1 The user interface language has been reset to English. Open the Preferences-dialog to select any of the available languages. 更改用户界面语言失败: %1 用户界面语言已被重置为英语。打开“首选项”对话框,选择任何可用的语言。 Cppcheck Cppcheck TxtReport inconclusive 不确定的 cppcheck-1.61/gui/csvreport.cpp000066400000000000000000000033221217722632100165430ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include #include #include #include "report.h" #include "csvreport.h" CsvReport::CsvReport(const QString &filename) : Report(filename) { } CsvReport::~CsvReport() { } bool CsvReport::Create() { if (Report::Create()) { mTxtWriter.setDevice(Report::GetFile()); return true; } return false; } void CsvReport::WriteHeader() { // No header for CSV report } void CsvReport::WriteFooter() { // No footer for CSV report } void CsvReport::WriteError(const ErrorItem &error) { /* Error as CSV line gui/test.cpp,23,error,Mismatching allocation and deallocation: k */ const QString file = QDir::toNativeSeparators(error.files[error.files.size() - 1]); QString line = QString("%1,%2,").arg(file).arg(error.lines[error.lines.size() - 1]); line += QString("%1,%2").arg(GuiSeverity::toString(error.severity)).arg(error.summary); mTxtWriter << line << endl; } cppcheck-1.61/gui/csvreport.h000066400000000000000000000034541217722632100162160ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #ifndef CSV_REPORT_H #define CSV_REPORT_H #include #include #include "report.h" /// @addtogroup GUI /// @{ /** * @brief CSV text file report. * This report exports results as CSV (comma separated values). CSV files are * easy to import to many other programs. * @todo This class should be inherited from TxtReport? */ class CsvReport : public Report { public: CsvReport(const QString &filename); virtual ~CsvReport(); /** * @brief Create the report (file). * @return true if succeeded, false if file could not be created. */ virtual bool Create(); /** * @brief Write report header. */ virtual void WriteHeader(); /** * @brief Write report footer. */ virtual void WriteFooter(); /** * @brief Write error to report. * @param error Error data. */ virtual void WriteError(const ErrorItem &error); private: /** * @brief Text stream writer for writing the report in text format. */ QTextStream mTxtWriter; }; /// @} #endif // CSV_REPORT_H cppcheck-1.61/gui/erroritem.cpp000066400000000000000000000030121217722632100165200ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include "erroritem.h" ErrorItem::ErrorItem() : severity(Severity::none) , inconclusive(false) { } ErrorItem::ErrorItem(const ErrorLine &line) : file(line.file) , files(line.file) , errorId(line.errorId) , severity(line.severity) , inconclusive(line.inconclusive) , summary(line.summary) , message(line.message) { lines.append(line.line); } QString ErrorItem::ToString() const { QString str = file + " - " + errorId + " - "; if (inconclusive) str += "inconclusive "; str += GuiSeverity::toString(severity) +"\n"; str += summary + "\n"; str += message + "\n"; for (int i = 0; i < files.size(); i++) { str += " " + files[i] + ": " + QString::number(lines[i]) + "\n"; } return str; } cppcheck-1.61/gui/erroritem.h000066400000000000000000000047401217722632100161760ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #ifndef ERRORITEM_H #define ERRORITEM_H #include #include #include #include "errorlogger.h" class ErrorLine; /// @addtogroup GUI /// @{ /** * @brief GUI versions of severity conversions. * GUI needs wrappers for conversion functions since GUI uses Qt's QString * instead of the std::string used by lib/cli. */ class GuiSeverity { public: static QString toString(Severity::SeverityType severity) { return QString(Severity::toString(severity).c_str()); } static Severity::SeverityType fromString(const QString &severity) { return Severity::fromString(severity.toStdString()); } }; /** * @brief A class containing error data for one error. * * The paths are stored with internal ("/") separators. Only when we show the * path or copy if for user (to clipboard) we convert to native separators. * Full path is stored instead of relative path for flexibility. It is easy * to get the relative path from full path when needed. */ class ErrorItem { public: ErrorItem(); ErrorItem(const ErrorLine &line); /** * @brief Convert error item to string. * @return Error item as string. */ QString ToString() const; QString file; QStringList files; QString file0; QList lines; QString errorId; Severity::SeverityType severity; bool inconclusive; QString summary; QString message; }; Q_DECLARE_METATYPE(ErrorItem); /** * @brief A class containing error data for one shown error line. */ class ErrorLine { public: QString file; unsigned int line; QString errorId; bool inconclusive; Severity::SeverityType severity; QString summary; QString message; }; /// @} #endif // ERRORITEM_H cppcheck-1.61/gui/file.ui000066400000000000000000000030171217722632100152670ustar00rootroot00000000000000 Fileview 0 0 400 300 Fileview true Qt::Horizontal QDialogButtonBox::Close mButtons accepted() Fileview accept() 248 254 157 274 mButtons rejected() Fileview reject() 316 260 286 274 cppcheck-1.61/gui/filelist.cpp000066400000000000000000000073071217722632100163360ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include #include #include #include "filelist.h" QStringList FileList::GetDefaultFilters() { QStringList extensions; extensions << "*.cpp" << "*.cxx" << "*.cc" << "*.c" << "*.c++" << "*.txx" << "*.tpp"; return extensions; } bool FileList::FilterMatches(const QFileInfo &inf) { if (inf.isFile()) { const QStringList filters = FileList::GetDefaultFilters(); QString ext("*."); ext += inf.suffix(); if (filters.contains(ext)) return true; } return false; } void FileList::AddFile(const QString &filepath) { QFileInfo inf(filepath); if (FilterMatches(inf)) mFileList << inf; } void FileList::AddDirectory(const QString &directory, bool recursive) { QDir dir(directory); dir.setSorting(QDir::Name); const QStringList filters = FileList::GetDefaultFilters(); const QStringList origNameFilters = dir.nameFilters(); dir.setNameFilters(filters); if (!recursive) { dir.setFilter(QDir::Files | QDir::NoDotAndDotDot); QFileInfoList items = dir.entryInfoList(); mFileList += items; } else { dir.setFilter(QDir::Files | QDir::NoDotAndDotDot); QFileInfoList items = dir.entryInfoList(); mFileList += items; dir.setNameFilters(origNameFilters); dir.setFilter(QDir::Dirs | QDir::NoDotAndDotDot); QFileInfoList list = dir.entryInfoList(); QFileInfo item; foreach(item, list) { const QString path = item.canonicalFilePath(); AddDirectory(path, recursive); } } } void FileList::AddPathList(const QStringList &paths) { QString path; foreach(path, paths) { QFileInfo inf(path); if (inf.isFile()) AddFile(path); else AddDirectory(path, true); } } QStringList FileList::GetFileList() const { if (mExcludedPaths.empty()) { QStringList names; foreach(QFileInfo item, mFileList) { QString name = QDir::fromNativeSeparators(item.canonicalFilePath()); names << name; } return names; } else { return ApplyExcludeList(); } } void FileList::AddExcludeList(const QStringList &paths) { mExcludedPaths = paths; } QStringList FileList::ApplyExcludeList() const { QStringList paths; foreach(QFileInfo item, mFileList) { QString name = QDir::fromNativeSeparators(item.canonicalFilePath()); if (!Match(name)) paths << name; } return paths; } bool FileList::Match(const QString &path) const { for (int i = 0; i < mExcludedPaths.size(); i++) { if (mExcludedPaths[i].endsWith('/')) { const QString pathexclude("/" + mExcludedPaths[i]); if (path.indexOf(pathexclude) != -1) return true; } else { if (path.endsWith(mExcludedPaths[i])) return true; } } return false; } cppcheck-1.61/gui/filelist.h000066400000000000000000000065331217722632100160030ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #ifndef FILELIST_H #define FILELIST_H #include #include /** * @brief A class for listing files and directories to check. * This class creates a list of files to check. If directory name is given then * all files in the directory matching the filter will be added. The directory * can be also added recursively when all files in subdirectories are added too. * The filenames are matched against the filter and only those files whose * filename extension is included in the filter list are added. * * This class also handles filtering of paths against ignore filters given. If * there is ignore filters then only paths not matching those filters are * returned. */ class FileList { public: /** * @brief Add filename to the list. * @param filepath Full path to the file. */ void AddFile(const QString &filepath); /** * @brief Add files in the directory to the list. * @param directory Full pathname to directory to add. * @param recursive If true also files in subdirectories are added. */ void AddDirectory(const QString &directory, bool recursive = false); /** * @brief Add list of filenames and directories to the list. * @param paths List of paths to add. */ void AddPathList(const QStringList &paths); /** * @brief Return list of filenames (to check). * @return list of filenames to check. */ QStringList GetFileList() const; /** * @brief Add list of paths to exclusion list. * @param paths Paths to exclude. */ void AddExcludeList(const QStringList &paths); protected: /** * @brief Return list of default filename extensions included. * @return list of default filename extensions included. */ static QStringList GetDefaultFilters(); /** * @brief Test if filename matches the filename extensions filtering. * @return true if filename matches filtering. */ static bool FilterMatches(const QFileInfo &inf); /** * @brief Get filtered list of paths. * This method takes the list of paths and applies the exclude lists to * it. And then returns the list of paths that did not match the * exclude filters. * @return Filtered list of paths. */ QStringList ApplyExcludeList() const; /** * @brief Test if path matches any of the exclude filters. * @param path Path to test against exclude filters. * @return true if any of the filters matches, false otherwise. */ bool Match(const QString &path) const; private: QFileInfoList mFileList; QStringList mExcludedPaths; }; #endif // FILELIST_H cppcheck-1.61/gui/fileviewdialog.cpp000066400000000000000000000043151217722632100175110ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include #include #include #include "fileviewdialog.h" FileViewDialog::FileViewDialog(const QString &file, const QString &title, QWidget *parent) : QDialog(parent) { mUI.setupUi(this); setWindowTitle(title); connect(mUI.mButtons, SIGNAL(accepted()), this, SLOT(accept())); LoadTextFile(file, mUI.mText); } void FileViewDialog::LoadTextFile(const QString &filename, QTextEdit *edit) { QFile file(filename); if (!file.exists()) { QString msg(tr("Could not find the file: %1")); msg = msg.arg(filename); QMessageBox msgbox(QMessageBox::Critical, tr("Cppcheck"), msg, QMessageBox::Ok, this); msgbox.exec(); return; } file.open(QIODevice::ReadOnly | QIODevice::Text); if (!file.isReadable()) { QString msg(tr("Could not read the file: %1")); msg = msg.arg(filename); QMessageBox msgbox(QMessageBox::Critical, tr("Cppcheck"), msg, QMessageBox::Ok, this); msgbox.exec(); return; } QByteArray filedata = file.readAll(); file.close(); QString filestringdata(filedata); edit->setPlainText(filestringdata); } cppcheck-1.61/gui/fileviewdialog.h000066400000000000000000000033021217722632100171510ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #ifndef FILEVIEW_DIALOG_H #define FILEVIEW_DIALOG_H #include #include #include "ui_file.h" class QWidget; class QTextEdit; /// @addtogroup GUI /// @{ /** * @brief File view -dialog. * This dialog shows text files. It is used for showing the license file and * the authors list. * */ class FileViewDialog : public QDialog { Q_OBJECT public: FileViewDialog(const QString &file, const QString &title, QWidget *parent = 0); protected: /** * @brief Load text file contents to edit control. * * @param filename File to load. * @param edit Control where to load the file contents. */ void LoadTextFile(const QString &filename, QTextEdit *edit); /** * @brief Format dialog title from filename. * * @param filename File to load. */ QString FormatTitle(const QString &filename); Ui::Fileview mUI; }; /// @} #endif // FILEVIEW_DIALOG_H cppcheck-1.61/gui/gui.cppcheck000066400000000000000000000004441217722632100163000ustar00rootroot00000000000000 cppcheck-1.61/gui/gui.pro000066400000000000000000000066531217722632100153300ustar00rootroot00000000000000TEMPLATE = app TARGET = cppcheck-gui CONFIG += warn_on DEPENDPATH += . \ ../lib INCLUDEPATH += . \ ../lib # In Qt 5 widgets are in separate module greaterThan(QT_MAJOR_VERSION, 4) { QT += widgets } contains(LINKCORE, [yY][eE][sS]) { LIBS += -l../bin/cppcheck-core DEFINES += CPPCHECKLIB_IMPORT } LIBS += -L../externals DESTDIR = . RCC_DIR = temp MOC_DIR = temp OBJECTS_DIR = temp UI_DIR = temp win32 { CONFIG += windows contains(LINKCORE, [yY][eE][sS]) { DESTDIR = ../bin RCC_DIR = temp/generated MOC_DIR = temp/generated OBJECTS_DIR = temp/generated UI_DIR = temp/generated } else { DESTDIR = ../Build/gui RCC_DIR = ../BuildTmp/gui MOC_DIR = ../BuildTmp/gui OBJECTS_DIR = ../BuildTmp/gui UI_DIR = ../BuildTmp/gui } } RESOURCES = gui.qrc FORMS = about.ui \ application.ui \ file.ui \ logview.ui \ main.ui \ projectfile.ui \ resultsview.ui \ scratchpad.ui \ settings.ui \ stats.ui TRANSLATIONS = cppcheck_de.ts \ cppcheck_es.ts \ cppcheck_fi.ts \ cppcheck_fr.ts \ cppcheck_it.ts \ cppcheck_ja.ts \ cppcheck_ko.ts \ cppcheck_nl.ts \ cppcheck_ru.ts \ cppcheck_sr.ts \ cppcheck_sv.ts \ cppcheck_zh_CN.ts # Windows-specific options CONFIG += embed_manifest_exe contains(LINKCORE, [yY][eE][sS]) { } else { BASEPATH = ../lib/ include($$PWD/../lib/lib.pri) } HEADERS += aboutdialog.h \ application.h \ applicationdialog.h \ applicationlist.h \ checkstatistics.h \ checkthread.h \ common.h \ csvreport.h \ erroritem.h \ filelist.h \ fileviewdialog.h \ logview.h \ mainwindow.h \ platforms.h \ project.h \ projectfile.h \ projectfiledialog.h \ report.h \ resultstree.h \ resultsview.h \ scratchpad.h \ settingsdialog.h \ showtypes.h \ statsdialog.h \ threadhandler.h \ threadresult.h \ translationhandler.h \ txtreport.h \ xmlreport.h \ xmlreportv1.h \ xmlreportv2.h SOURCES += aboutdialog.cpp \ application.cpp \ applicationdialog.cpp \ applicationlist.cpp \ checkstatistics.cpp \ checkthread.cpp \ common.cpp \ csvreport.cpp \ erroritem.cpp \ filelist.cpp \ fileviewdialog.cpp \ logview.cpp \ main.cpp \ mainwindow.cpp\ platforms.cpp \ project.cpp \ projectfile.cpp \ projectfiledialog.cpp \ report.cpp \ resultstree.cpp \ resultsview.cpp \ scratchpad.cpp \ settingsdialog.cpp \ showtypes.cpp \ statsdialog.cpp \ threadhandler.cpp \ threadresult.cpp \ translationhandler.cpp \ txtreport.cpp \ xmlreport.cpp \ xmlreportv1.cpp \ xmlreportv2.cpp win32 { DEFINES += _CRT_SECURE_NO_WARNINGS RC_FILE = cppcheck-gui.rc HEADERS += ../lib/version.h LIBS += -lshlwapi } cppcheck-1.61/gui/gui.qrc000066400000000000000000000022031217722632100153000ustar00rootroot00000000000000 icon.png images/dialog-error.png images/dialog-information.png images/dialog-warning.png images/edit-clear.png images/go-down.png images/help-browser.png images/media-floppy.png images/preferences-system.png images/process-stop.png images/text-x-generic.png images/view-refresh.png images/showerrors.png images/showstylewarnings.png images/openproject.png images/scratchpad.png images/showwarnings.png images/showperformance.png images/utilities-system-monitor.png ../COPYING ../AUTHORS images/go-home.png images/go-next.png images/go-previous.png images/applications-development.png images/applications-system.png cppcheck-1.61/gui/help/000077500000000000000000000000001217722632100147405ustar00rootroot00000000000000cppcheck-1.61/gui/help/buildhelp.bat000066400000000000000000000002741217722632100174030ustar00rootroot00000000000000@echo off pushd %~dp0 if exist online-help.qhc del online-help.qhc if exist online-help.qch del online-help.qch qcollectiongenerator online-help.qhcp -o online-help.qhc popd cppcheck-1.61/gui/help/manual.html000066400000000000000000000441171217722632100171120ustar00rootroot00000000000000 Cppcheck 1.46

Chapter 1. Introduction

Cppcheck is an analysis tool for C/C++ code. Unlike C/C++ compilers and many other analysis tools, it doesn't detect syntax errors. Cppcheck only detects the types of bugs that the compilers normally fail to detect. The goal is no false positives.

Supported code and platforms:

  • You can check non-standard code that includes various compiler extensions, inline assembly code, etc.

  • Cppcheck should be compilable by any C++ compiler that handles the latest C++ standard.

  • Cppcheck should work on any platform that has sufficient cpu and memory.

Accuracy

Please understand that there are limits of Cppcheck. Cppcheck is rarely wrong about reported errors. But there are many bugs that it doesn't detect.

You will find more bugs in your software by testing your software carefully, than by using Cppcheck. You will find more bugs in your software by instrumenting your software, than by using Cppcheck. But Cppcheck can still detect some of the bugs that you miss when testing and instrumenting your software.


Chapter 2. Getting started

2.1. First test

Here is a simple code

int main()
{
    char a[10];
    a[10] = 0;
    return 0;
}

If you save that into file1.c and execute:

cppcheck file1.c

The output from cppcheck will then be:

Checking file1.c...
[file1.c:4]: (error) Array 'a[10]' index 10 out of bounds

2.2. Checking all files in a folder

Normally a program has many sourcefiles. And you want to check them all. Cppcheck can check all sourcefiles in a directory:

cppcheck path

If "path" is a folder then cppcheck will check all sourcefiles in this folder.

Checking path/file1.cpp...
1/2 files checked 50% done
Checking path/file2.cpp...
2/2 files checked 100% done

2.3. Excluding a file or folder from checking

There is no command to exclude a file or folder from checking. But you can exclude a file or folder by being more careful when including files and folders in the checking.

Imagine for example that the folder "src" contain the folders "a", "b" and "c". To exclude "c" this command can be used:

cppcheck src/a src/b

All files under "src/a" and "src/b" are then checked.

The flag --file-list might also be useful.


2.4. Severities

The possible severities for messages are:

error

used when bugs are found

warning

suggestions about defensive programming to prevent bugs

style

stylistic issues related to code cleanup (unused functions, redundant code, constness, and such)

performance

suggestions for making the code faster


2.5. Enable messages

By default only error messages are shown. Through the --enable command more checks can be enabled.


2.5.1. Stylistic issues

With --enable=style you enable most warning, style and performance messages.

Here is a simple code example:

void f(int x)
{
    int i;
    if (x == 0)
    {
        i = 0;
    }
}

There are no bugs in that code so Cppcheck won't report anything by default. To enable the stylistic messages, use the --enable=style command:

cppcheck --enable=style file3.c

The output from Cppcheck is now:

Checking file3.c...
[file3.c:3]: (style) Variable 'i' is assigned a value that is never used
[file3.c:3]: (style) The scope of the variable i can be reduced


2.5.2. Unused functions

This check will try to find unused functions. It is best to use this when the whole program is checked, so that all usages is seen by cppcheck.

cppcheck --enable=unusedFunction path

2.5.3. Enable all checks

To enable all checks your can use the --enable=all flag:

cppcheck --enable=all path

2.6. Saving results in file

Many times you will want to save the results in a file. You can use the normal shell redirection for piping error output to a file.

cppcheck file1.c 2> err.txt

2.7. Multithreaded checking

To use 4 threads to check the files in a folder:

cppcheck -j 4 path

Chapter 3. Preprocessor configurations

By default Cppcheck will check all preprocessor configurations (except those that have #error in them). This is the recommended behaviour.

But if you want to manually limit the checking you can do so with -D.

Beware that only the macros, which are given here and the macros defined in source files and known header files are considered. That excludes all the macros defined in some system header files, which are by default not examined by cppcheck.

The usage: if you, for example, want to limit the checking so the only configuration to check should be "DEBUG=1;__cplusplus" then something like this can be used:

cppcheck -DDEBUG=1 -D__cplusplus path

Chapter 4. XML output

Cppcheck can generate the output in XML format.

Use the --xml flag when you execute cppcheck:

cppcheck --xml file1.cpp

The xml format is:

<?xml version="1.0"?>
<results>
  <error file="file1.cpp" line="123" id="someError"
               severity="error" msg="some error text"/>
</results>

Attributes:

file

filename. Both relative and absolute paths are possible

line

a number

id

id of error. These are always valid symbolnames.

severity

either error or style. warning and performance are saved as style.

msg

the error message


Chapter 5. Reformatting the output

If you want to reformat the output so it looks different you can use templates.

To get Visual Studio compatible output you can use "--template vs":

cppcheck --template vs gui/test.cpp

This output will look like this:

Checking gui/test.cpp...
gui/test.cpp(31): error: Memory leak: b
gui/test.cpp(16): error: Mismatching allocation and deallocation: k

To get gcc compatible output you can use "--template gcc":

cppcheck --template gcc gui/test.cpp

The output will look like this:

Checking gui/test.cpp...
gui/test.cpp:31: error: Memory leak: b
gui/test.cpp:16: error: Mismatching allocation and deallocation: k

You can write your own pattern (for example a comma-separated format):

cppcheck --template "{file},{line},{severity},{id},{message}" gui/test.cpp

The output will look like this:

Checking gui/test.cpp...
gui/test.cpp,31,error,memleak,Memory leak: b
gui/test.cpp,16,error,mismatchAllocDealloc,Mismatching allocation and deallocation: k


Chapter 6. Suppressions

If you want to filter out certain errors you can suppress these. First you need to create a suppressions file. The format is:

[error id]:[filename]:[line]
[error id]:[filename2]
[error id]

The error id is the id that you want to suppress. The easiest way to get it is to use the --xml command line flag. Copy and paste the id string from the xml output.

Here is an example:

memleak:file1.cpp
exceptNew:file1.cpp
uninitvar

You can then use the suppressions file:

cppcheck --suppressions suppressions.txt src/


Chapter 7. Leaks

Looking for memory leaks and resource leaks is a key feature of Cppcheck. Cppcheck can detect many common mistakes by default. But through some tweaking you can improve the checking.


7.1. Userdefined allocation/deallocation functions

Cppcheck understands many common allocation and deallocation functions. But not all.

Here is example code that might leak memory or resources:

void foo(int x)
{
    void *f = CreateFred();
    if (x == 1)
        return;
    DestroyFred(f);
}

If you analyse that with Cppcheck it won't find any leaks:

cppcheck --enable=possibleError fred1.cpp

You can add some custom leaks checking by providing simple implementations for the allocation and deallocation functions. Write this in a separate file:

void *CreateFred()
{
    return malloc(100);
}

void DestroyFred(void *p)
{
    free(p);
}

When Cppcheck see this it understands that CreateFred will return allocated memory and that DestroyFred will deallocate memory.

Now, execute Cppcheck this way:

cppcheck --append=fred.cpp fred1.cpp

The output from cppcheck is:

Checking fred1.cpp...
[fred1.cpp:5]: (error) Memory leak: f

Chapter 8. Exception safety

Cppcheck has a few checks that ensure that you don't break the basic guarantee of exception safety. It doesn't have any checks for the strong guarantee yet.

Example:

Fred::Fred() : a(new int[20]), b(new int[20])
{
}

By default cppcheck will not detect any problems in that code.

To enable the exception safety checking you can use --enable:

cppcheck --enable=exceptNew --enable=exceptRealloc fred.cpp

The output will be:

[fred.cpp:3]: (style) Upon exception there is memory leak: a

If an exception occurs when b is allocated, a will leak.

Here is another example:

int *p;

int a(int sz)
{
    delete [] p;
    if (sz <= 0)
        throw std::runtime_error("size <= 0");
    p = new int[sz];
}

Check that with Cppcheck:

cppcheck --enable=exceptNew --enable=exceptRealloc except2.cpp

The output from Cppcheck is:

[except2.cpp:7]: (error) Throwing exception in invalid state, p points at deallocated memory

Chapter 9. Html report

You can convert the xml output from cppcheck into a html report. You'll need python and the pygments module (http://pygments.org/) for this to work. In the Cppcheck source tree there is a folder "htmlreport" that contains a script that transforms a Cppcheck xml file into html output.

This command generates the help screen:

htmlreport/cppcheck-htmlreport -h

The output screen says:

Usage: cppcheck-htmlreport [options]

Options:
  -h, --help      show this help message and exit
  --file=FILE     The cppcheck xml output file to read defects from.
                  Default is reading from stdin.
  --report-dir=REPORT_DIR
                  The directory where the html report content is written.
  --source-dir=SOURCE_DIR
                  Base directory where source code files can be found.

An example usage:

./cppcheck gui/test.cpp --xml 2> err.xml
htmlreport/cppcheck-htmlreport --file=err.xml --report-dir=test1 --source-dir=.

Chapter 10. Graphical user interface

10.1. Introduction

A Cppcheck GUI is available.

The main screen is shown immediately when the GUI is started.


10.2. Check source code

Use the Check menu.


10.3. Inspecting results

The results are shown in a list.

You can show/hide certain types of messages through the View menu.

Results can be saved to an xml file that can later be opened. See Save results to file and Open XML.


10.4. Settings

The language can be changed at any time by using the Language menu.

More settings are available in Edit>Preferences.


10.5. Project files

The project files are used to store project specific settings. These settings are:

  • include folders

  • preprocessor defines

It isn't recommended to provide the paths to the standard C/C++ headers - Cppcheck has internal knowledge about ANSI C/C++ and it isn't recommended that this known functionality is redefined. But feel free to try it.

As you can read in chapter 3 in this manual the default is that Cppcheck checks all configurations. So only provide preprocessor defines if you want to limit the checking.

cppcheck-1.61/gui/help/online-help.qhcp000066400000000000000000000006241217722632100200310ustar00rootroot00000000000000 online-help.qhp online-help.qch online-help.qch cppcheck-1.61/gui/help/online-help.qhp000066400000000000000000000006231217722632100176650ustar00rootroot00000000000000 cppcheck.sourceforge.net doc
manual.html cppcheck-1.61/gui/icon.png000066400000000000000000000052011217722632100154440ustar00rootroot00000000000000PNG  IHDRAAE HIDATxݛ PT,_QjE1P ՈHi5 H[#7 &6jj2:hjbTkLR4jkHR4Q?W };qw{ϻs} Zv߀\Yp ԁ20 WžwS@pAC!Z0@|};RBk&NB~~).!;x{;ɩ:+iLf9r[bQ%B JXNq*"ٳZ@%{,plCA$`LaJA{^GrE͵*Zhll$@)MB5hnFDɩ޽-\YiF*"{DpiԨrC"̜yrDThh<Ͷ3zЈ]K4oo 0[,Y><a r"1UI=Bn7|]Jw$B~9l`qP^.܁mn)ܓ PXX?\်w"d~EppKv[G*[[gkl+a*Z(a0 d HY}pã16m.Q[-~G*;5"ۺA $TFi3wQ| pEl߾u֬\Icl옳E`"X:P@IOo*fzDx"6lGIB 2CDX4cm!B,@y)uvP Ġ.w\> 66]K#4Z\Qxk4>P('GMk", uIeWlcbpГU,Xo$Q*& &Ayp3Xi 4O:Y@C4Z{ϊ= S FeC6j?9ʪ+A6WF;p%0#c(u/μݼ`kE@==[UbFhC{?' bKPP -[v1}>lY#h޼ߋkYOO?6 QI5~k4 tJf36|J%!a"8cԩ?cWUf֬_K):E`d?0Yhhd/YOX˖#jsk2 MTU6>>w K!xh8;Ynq6:.sE' M6ը|c{8Dku|+i 0c67Y:˙Mp (N3>pebn@z8D!@- wϕ;&@i p[io2w{]$1΁qv .tzcKߨ)񳈜'Y'Z͠j^bn]"])+Z.=fXE;?!ݿ^! WNcyȱ~Ee5h`-_h`R^N;ی6@kJ҃8z ^ E`\q (ZGOH8n씔 .V`RخHTk/bo=ex/ML'a3ÆlF!0o8ϥs8r+Y󐵥J_åqk* ~ُ5z)]$ image/svg+xml c ++ cppcheck-1.61/gui/images/000077500000000000000000000000001217722632100152555ustar00rootroot00000000000000cppcheck-1.61/gui/images/applications-development.png000066400000000000000000000023231217722632100227710ustar00rootroot00000000000000PNG  IHDRĴl;IDATx}TU;;nZ!nbZ%Xbf QE&Z*d ²V631;3ˀ(=p^yy=̇Eg3 34%sLRp~l&gxCO|xq+cƩ93~d`&^kK{zۋqFJ hq]RaiگxuƸV n$ӶE쨍e7 T6q<.Vҭ,pEȝGSزcʫv/ՀQD03oKߖK4vl:pz~NozcĚ-`Ju?"6=)-)cE,ږlRƾ~.]4f߽ާ c  v4B㕇H65@}=ك 6umNz*h5Km|o<_F2[$R- Q&Lff5ټicp㠽2<6%:7npJ!t@x10Wc!tgjzE_xNZz^={14HKZg[B  x~oSt!VK&@ TJtʠ7QnVSA<&ho K-YՋmSd"ڎvXBBHf&So@MH=1:F(@ ĵV3 ofڛf. '1O{W'$$6UwH4y0@>;(OhmЯz X:.|Hc!^JCZ" >]Pw //[GxHc?4vP\ 107>ws ,zpE+vP)fqJWBaP",-",j.N<| $q鮥-^ iIqf kVHCē#zʅk>S[6ہq* 9o; uۖO4x,iERw=K17h 7OϺo#P@ BњOwֽnDmiI$j[XJ"rBBn{_[`  BXT_r}SeΉBZ)b?֧G}׉cqܺ}B2 z \`)B#:lʆv.5ˌ|]B򼋢LnC^ ދIqht`5]l4 pFH/ 䢄$&&~JʍJ#bR*}hU:d2Bnߺ;c1x^w,Mh1_Kd(4͒F>>R\uZ5^4iadD@&MCh3yQmbR06U9~BO$  evD>6XIbkF} 㣓hm6W$b >HW+%e#"2e6?4[Ӯ<|]: eζQl؂)Տ#|o +ɚΪoxDaKf=v`ubm[#W@KR6.U{3.hxx~FԚ~Hle$f g{f[ Zbz8X0wWxx%ψP:"fz;6B^Ȝ1ok /}{VY&#i~[ībbѴ4O+IENDB`cppcheck-1.61/gui/images/dialog-error.png000066400000000000000000000014771217722632100203620ustar00rootroot00000000000000PNG  IHDRĴl;IDATxՓ=hSQܟU64PSݝN. (8UWAA)ڟV!iMۚs|PZ/9>;/\ G8pƀ~`\`OGG9LZ |2p'?'XRg.]"yt~D|hQ5<{({ի8BjbBۨ2瑞dP8?U_]'L]NDQ[[h@ZKWEfd]bnL^22PY+saJtH60~SC'NYZFiczW)"!rخkcH~οj9B7b{M8LSlofn n&g{EmT;J&KH70-MmT*+x[ @H Pc"IVK+? r.Wc1uޞ7u$R*.ᙀea}<mmjhbZNDP$u9ʭ ؒ~ HX<n4J-@c R 77rP!p bo`.h18pH&d jKam\>ݞ/6ВHbp)`0 ^Y?iMU[ *P*@hPx! }pE1>M֔pQb# n@'["g[WDj7HIENDB`cppcheck-1.61/gui/images/dialog-information.png000066400000000000000000000021351217722632100215460ustar00rootroot00000000000000PNG  IHDRĴl;$IDATx}he}%^|U[vUg\EBŵT!*@L-&ENtVF[Yvd~IrwセapA ^~MXYBH+>@={ڀGi#GkX$IQ!K¿wn3B{'w<꟏:kJ$&a49*8? n?EWˆiw\KA c4%+ 0#_knU:Z#|2PL AɁ'"26>*Za2Mm|#\v!Med(%È;:,RBYA4Npoo%d1  jB8 cK(4p!ZBE%/1^g`l.O*EA1L %jSy)AiM Lȝɪ9e7ˍB&c0iVʹ7x\*+sv#?FO#{fz$v+V`vzoCOZKj,!{F@?L@Vʽ^i>##wB7fB6X :Z[qWZ@l0_Ӫ>V)j\ykv}v3ß0 i=XhÆMd(9)86WK~2Pv ]'abm HŶ]t,J/"ظxWw J6\`Ay/ˉo|*Vp帚Nu@m0kº΃LO VFc,["r^JZ< XfFϞJRf3?~8vtwCO3| eu*c@ܼxa!GQmiy࣮jhk0GC%cFŻXb}g<oCQ!tW](d 5Cv W.wpxIENDB`cppcheck-1.61/gui/images/dialog-warning.png000066400000000000000000000015401217722632100206650ustar00rootroot00000000000000PNG  IHDRĴl;'IDATxڥKQƟss6+SK4T V TAoD*2뮂Bn Ҩ,, J,NN_ vw;)eI>{\9JP'c̰h\O\Sx9*l `SSS5 \Ӵ Z,>JodKG"iy*5/?%Vk4gf?ֆem&z)1 SViGFM\WfaD"d2@ӧ'V]in'E(w65:(B pޭ}rI477kĸ5SB Ձl.:ي D4 /@cx_M{SNMn0MԳRVE0"82瓌N507Xⵔ(h z7(P^EvuJy#/gkEE"t<6/yA\B*IENDB`cppcheck-1.61/gui/images/edit-clear.png000066400000000000000000000022011217722632100177670ustar00rootroot00000000000000PNG  IHDRĴl;HIDAT8˥Lu$Hр X, ,l 2°Y8RHC17+#l3` O ?x}{^+Y}>y~{ٗQJbh:mhd4w{TXZ4kȏCS^ 즨жGi>|a7G?(PIl4R|P.A tĻٖ)fʌX&~s f.ƣtGC8~sz&7l>S<XL Lwmg-)MrDA?T "}La[ebTiu"SvgXBtucZs᲍Nb{N2HhHq_bX$_L9nBZPh)B)/hh@O;O&sW"Kd%B 7J:JВoJK 浘 nj65QF5SهhY$%{Ǝ*[0!ToĔ* BgΦaxD6G؂o`A}'GrNG@F$+ ܸ(VUI0Po(TFCAP8v},97V6CgꫫH쉱vO t_}|[aН@UA-U(bෟ[NjTWiyRCuLFcnЧ|(;_\Ƒ&`I* 3ċC]$7k}S9m4?f5/%,%>ǓwXݱPJEWmFn|2 ߻/dȸ!SlsCJG toZL0RnV";G={޿`cM96p[[hۓ}ٮHI.=Riw;Tpmm0YIENDB`cppcheck-1.61/gui/images/go-down.png000066400000000000000000000014021217722632100173320ustar00rootroot00000000000000PNG  IHDRĴl;IDATx[HAƿًB ԀI@1{)EWJҞ򹂤42!) F ݨ4"ݙiv(Bg!ѰA1Jpd4ĞJ0Nr&U 83uAf>,9? $#?+ 8 k~*̗# A,) KMbq$)5^yJPM9Y)1t`a3)cƥDs `4h:p0@Ξم<ȯu=0Ho: Jii`5IQNEdO^}Efb։qO#MRS8{Ģ{jV)'鄘#eGO[ڇnmo-Eb^].e|JǭX(v [Q#wt?^Џqod+z2a= ָЊIjꌊmwڤގ5: 4zZ=DHl,6tӽ+TqRhJ eU;tNZp v@$nP_yRl*Be3U$tg'yYP (|;B}^"w/\QxIENDB`cppcheck-1.61/gui/images/go-home.png000066400000000000000000000015601217722632100173200ustar00rootroot00000000000000PNG  IHDRj PLTE..,,uuuUWSuuuuu愆|vy}%%dd}4eↈywux|^^FFЙ][ޢ[[egc99{LJ"!uvv~{cc叐LLwxzġ~UU&&qxﺺɵruzJv&&ZX&&ux{QQvy|ep''llnvff_us5)tRNS3 " S\0_l5IRVGD?/ JhH7IDATx^mcwLqgj^Y۶m^7I9m˨4) HV7;BC}uV>l"])]u7H/ GW+;HD%_جpO)ԉHAxV;==4yao O1y5c0̸B!җ*ҟNg-zWA,[4~#*AJ̀Chjp}-{'1 k%9rBeOo_?<\>1֤+4&%he,kL:b5srL_ sIENDB`cppcheck-1.61/gui/images/go-next.png000066400000000000000000000015021217722632100173420ustar00rootroot00000000000000PNG  IHDRĴl; IDATxŔhMaƟwܻmhmE XEQlSRCTRDYV UA-vg#`3̖۽=wfS5yNS¿H9Q+eg^G{ݑy3\z<njQH^^T3P, /}6*E|A(`*Vjj1}QҩD5jNY3"mR>÷9\P!{m⾑x:?4b*%1akp_5.[uҚ7}}ݏ6E.^}]pyg׽ѷӟӳq㨔bno?#٨շF;i:6e5mP,o51!ѱk;`yqsnkks7?f'XAk,ADozU䆣=k^-g4#RqE>3pqUQYNqw<3e7L$ԔHjV'*(8b{^ 1R%ʾHU,bcA1V#hh ٹ㯚'&޽pӺn.L l@lIZ,M52,Q;~kkz:""ldp!JL]$_%UH$'Tqf<}[:Ǩgq*WRߘ̜EDZuA8~ݍy9ݵe}4R. E`n4E$u4bo_P'ϟ Ś ղF1@< @9P pOPx;](xyX_&s4<`@| -e/V~P<,KP WVE4PU/"B#ҢF5N*3?(;*s s(i-RBa$L؀4еzB҈L)]F7qXaIENDB`cppcheck-1.61/gui/images/help-browser.png000066400000000000000000000023371217722632100204010ustar00rootroot00000000000000PNG  IHDRĴl;IDATxڍyPeǡiʩlaђ !BJp`(uQCsaY ^ nX8ETCY&֝&w3;>`KB%vLfD_< "رxtLb.@HJ >(GHj ,Sٗ Lj@4H+n9D.AtXyf/Nܪ?05tq hO K]1j斺6zo1Eb)?\# 9_ P0Ua鞶L{6G؄)ًn"{2/Maye e ݙƕ&#T$ג!Ko292N1+y[ sL1UȪAٍkɤUMC*SXԎW8/CJ\=*R=+hZ;F<M~tXprO'I ?E5B=g}^\$4VE\ZSJk"qX%59@Qxf&5311]s)bIZPo)-P̕{{JV+CPv'L%@9 =Ó4t| W *)*}Q؂м.D"Lr?J/Tv-.?7둅ۓ9ʬFQb"7$q?y2Oo/KY$ubO=N%&K ,q}(X6k?iE*t'q=z|"SWK%2v?"I?=WpۍFEbN&9H ~8)$7/@Q+ZhS5ޙJsͮM-z!+J$M7p S(lBFU?wYOˇ m#LEOK덽't̂gy9KEk=c/rEʵGf.m7G{b6z#V츶iЪi&^cw9l3twb?MLN%;wטTԣOIENDB`cppcheck-1.61/gui/images/media-floppy.png000066400000000000000000000012451217722632100203530ustar00rootroot00000000000000PNG  IHDRĴl;lIDATxϋQ?.FPQ6kR(XJ)d3%abcRL3-5wW{/ԩSN9} L3p̮4sl96H(d3gkP`53|΁ww/stj@=ɝɛ) 䌟H[ y)v C/'vriZѰY$JArFE.()'N)(\NʌSN\s'N)Gy(*;oQK EDQU,*p0W[1q8Hl; y ccc4MFԼw:i0Jq"ybb"sssdfgg !KGEyD~rv;&,v!? PW!زTRJVWWKi,עׁ*WNEF dNw6KYLyWȑ@"=G`ee%Y[[[Gƅ8fX : \0\ L/<:f\c'u"XyF܄nj@l JJ1IIENDB`cppcheck-1.61/gui/images/openproject.png000066400000000000000000000020051217722632100203100ustar00rootroot00000000000000PNG  IHDR szzIDATxMk$EƟydqW$"Sς^?E$^&Bބ!01ndc:3z`t$ Rt"6^%-²rRJ{ H_T&PZoyޯý+Faΐ$RVWWV" (cdyy J)m X綅0GGG?)`a I.xZvNNA)_i}'yJ1kcNffɲ\gG:  XJE*$l^ Waԝ- g?2w6f_qqqEᅪ'o,ߩQ"inle2ŗ>{n?(::"$t2$68g 5tV`851Vh)Lay,#t]0EЌ(EL V'd,9)%O \ BF:)+@ 0)ԈBZ)yVvX^Cf%x|e p.s !sZk6Lq,vτF`BJK. 5Pa Ak܍cƭ Ɣ??Z5OS$q4n!P5cȹxGPB@6j+$ ɘe.BrY]bƈ L*8J~}|4~1@ &5R;*(%8砄f۽.GQN E9,5,6jUb0A -fK?ǠUmݦ}!f4S _DqUb I_ajZD 7P J)Ί$D_vঀf$#)lxr2gW@IENDB`cppcheck-1.61/gui/images/preferences-system.png000066400000000000000000000016461217722632100216150ustar00rootroot00000000000000PNG  IHDRj PLTE4eqqq,W$FqX^rch:AC6"=Hpw (`5|+W xf/B_"7N̪ | Ȃ@=' O~Aw%puQ:6 zh" .3Zk0."Q}۾}l:VKXAD"@(׋]])_{~,u;5PFd)a3PY]Fj"Nݻ?(>BHR ~ΑT8R\vM1Y_~axggQ E_4K1UUsjS]Ai{z{2 ,RwL[Z9iYyt]XiYJ|ssxT⬖Y6s,ssm@6EEDoWO~h MܲXug99bAѻ}{׍Wӛ r 䉜 ք3Cn.rvHW6>)./Mii-,ӧdk2ٔ{Ji` `JMmZ,z;in_&JFJ7^cGJmF9A&GڵKް-"bYfɲ$A+7D".& @2IC&O(!U O2v?8Q!IENDB`cppcheck-1.61/gui/images/scratchpad.png000066400000000000000000000004111217722632100200730ustar00rootroot00000000000000PNG  IHDR Tg-PLTEIIIOO>qtM̔ɰ|tRNS@fIDATx!@EgvѠ"<l- $+TT5{9:^~k}`Ӳf6u0 C 0 C=p`o0$'eWlIENDB`cppcheck-1.61/gui/images/showerrors.png000066400000000000000000000014771217722632100202110ustar00rootroot00000000000000PNG  IHDRĴl;IDATxՓ=hSQܟU64PSݝN. (8UWAA)ڟV!iMۚs|PZ/9>;/\ G8pƀ~`\`OGG9LZ |2p'?'XRg.]"yt~D|hQ5<{({ի8BjbBۨ2瑞dP8?U_]'L]NDQ[[h@ZKWEfd]bnL^22PY+saJtH60~SC'NYZFiczW)"!rخkcH~οj9B7b{M8LSlofn n&g{EmT;J&KH70-MmT*+x[ @H Pc"IVK+? r.Wc1uޞ7u$R*.ᙀea}<mmjhbZNDP$u9ʭ ؒ~ HX<n4J-@c R 77rP!p bo`.h18pH&d jKam\>ݞ/6ВHbp)`0 ^Y?iMU[ *P*@hPx! }pE1>M֔pQb# n@'["g[WDj7HIENDB`cppcheck-1.61/gui/images/showperformance.png000066400000000000000000000017151217722632100211710ustar00rootroot00000000000000PNG  IHDRj %PLTEhjekmhprmvvtlniHJF^_]<>; Jr/fcpo5q^sm󥶽j1kpn}oDnkx̗幾n}n|sslyrߖrwtBmjuo~ly喚rw#N!IyEs?l٘GvwusSo+Jscsczo`wjXZVnfI^{[daBIejalDM[o~^jlc3oigecľiq1ly{7uron~]%Up-c1k3oqt;y7u5o/i-c)\'U)^/d5r;x?;}9x3k-c)Zý_wlzAn\+`'Y^)\ev9cMdĿſ˔ tRNSMF?.))))??KLGeEIDATx^c` <"ADq 몪Z(i {fB2SKMF}PT8YRd\XJ6 0(8$t\xm22n<}|K儗*X)*#'($,NNMMpfVcNnpArQqIR! U5*+V…V+utvuAՅ'LT4yieg̜%4,<-/ذq-l | "@ 6vV ###0 :cv'1IENDB`cppcheck-1.61/gui/images/showstylewarnings.png000066400000000000000000000021351217722632100215760ustar00rootroot00000000000000PNG  IHDRĴl;$IDATx}he}%^|U[vUg\EBŵT!*@L-&ENtVF[Yvd~IrwセapA ^~MXYBH+>@={ڀGi#GkX$IQ!K¿wn3B{'w<꟏:kJ$&a49*8? n?EWˆiw\KA c4%+ 0#_knU:Z#|2PL AɁ'"26>*Za2Mm|#\v!Med(%È;:,RBYA4Npoo%d1  jB8 cK(4p!ZBE%/1^g`l.O*EA1L %jSy)AiM Lȝɪ9e7ˍB&c0iVʹ7x\*+sv#?FO#{fz$v+V`vzoCOZKj,!{F@?L@Vʽ^i>##wB7fB6X :Z[qWZ@l0_Ӫ>V)j\ykv}v3ß0 i=XhÆMd(9)86WK~2Pv ]'abm HŶ]t,J/"ظxWw J6\`Ay/ˉo|*Vp帚Nu@m0kº΃LO VFc,["r^JZ< XfFϞJRf3?~8vtwCO3| eu*c@ܼxa!GQmiy࣮jhk0GC%cFŻXb}g<oCQ!tW](d 5Cv W.wpxIENDB`cppcheck-1.61/gui/images/showwarnings.png000066400000000000000000000015401217722632100205140ustar00rootroot00000000000000PNG  IHDRĴl;'IDATxڥKQƟss6+SK4T V TAoD*2뮂Bn Ҩ,, J,NN_ vw;)eI>{\9JP'c̰h\O\Sx9*l `SSS5 \Ӵ Z,>JodKG"iy*5/?%Vk4gf?ֆem&z)1 SViGFM\WfaD"d2@ӧ'V]in'E(w65:(B pޭ}rI477kĸ5SB Ձl.:ي D4 /@cx_M{SNMn0MԳRVE0"82瓌N507Xⵔ(h z7(P^EvuJy#/gkEE"t<6/yA\B*IENDB`cppcheck-1.61/gui/images/text-x-generic.png000066400000000000000000000007111217722632100206250ustar00rootroot00000000000000PNG  IHDRj PLTEklidtRNS &*67@ACEFbP˰IDATx^u@Fand0$/fN^c^3,C#Bm 7Q\F#"ZQۀZ$Nih9׹e3&LWV 8I` \mV;\t*-ENϾkĉpz&}2[,7nOH>3#IENDB`cppcheck-1.61/gui/images/utilities-system-monitor.png000066400000000000000000000017151217722632100230110ustar00rootroot00000000000000PNG  IHDRj %PLTEhjekmhprmvvtlniHJF^_]<>; Jr/fcpo5q^sm󥶽j1kpn}oDnkx̗幾n}n|sslyrߖrwtBmjuo~ly喚rw#N!IyEs?l٘GvwusSo+Jscsczo`wjXZVnfI^{[daBIejalDM[o~^jlc3oigecľiq1ly{7uron~]%Up-c1k3oqt;y7u5o/i-c)\'U)^/d5r;x?;}9x3k-c)Zý_wlzAn\+`'Y^)\ev9cMdĿſ˔ tRNSMF?.))))??KLGeEIDATx^c` <"ADq 몪Z(i {fB2SKMF}PT8YRd\XJ6 0(8$t\xm22n<}|K儗*X)*#'($,NNMMpfVcNnpArQqIR! U5*+V…V+utvuAՅ'LT4yieg̜%4,<-/ذq-l | "@ 6vV ###0 :cv'1IENDB`cppcheck-1.61/gui/images/view-refresh.png000066400000000000000000000023561217722632100203770ustar00rootroot00000000000000PNG  IHDRĴl;IDATxڵ{PTu5JL+D0Jrz@f*/XRGʘ43>ybl02񑳰ܻ/K1@ 1YXVuWXt.C3igs=;KCh\&.P\Ӹ=KTǩ8B@b+Q8"IbN=6w 'Vqz< wKqYDetTvu7yTniqH/` I GD~Qy@L> ܛFlϗ!(j6@F8OT06C/mbB>xN,<0y#%,ìMc0Nn2:xkE7-oťP2zȔ:믍BTrk8}'ԉWgXB3")j&14GbfmbceP5L$qJ# k^6vvB9sv{ZUYB Uvw 4^uoH1ļ-$g&s%:@b]+i pB)22l }j=󕃧ݩ~>, V3acp*> KGBg|rʉv ;3~SܷҶla*\k̓)1,?jq(ehLU*Z],ayvp 5}S]n^beQz^rV[Z7F`Μ;;ذX(BU?zvGE&jCUM40S@L"DŽ`]3'En#RZqcAa\L1,1&ι-`K݃N#\w@Twup"ڦ$?֚w~Zb Sᔩ˩qK݈40fl `4o[@CrTvpJQi.*',^fqu1/[!Zz(Dpx_atOSѨl[A *Բ >a}+}~DxD͗[*$[@L2ex8:;ज़fjԳ (? EXuo>Qxz 2JbьDy<eIENDB`cppcheck-1.61/gui/logview.cpp000066400000000000000000000050551217722632100161750ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include #include #include #include #include #include "common.h" #include "logview.h" LogView::LogView(QWidget *parent) : QWidget(parent) { mUI.setupUi(this); setWindowFlags(Qt::Tool); mUI.mButtonBox->button(QDialogButtonBox::Reset)->setText(tr("Clear")); connect(mUI.mButtonBox->button(QDialogButtonBox::Close), SIGNAL(clicked()), this, SLOT(CloseButtonClicked())); connect(mUI.mButtonBox->button(QDialogButtonBox::Reset), SIGNAL(clicked()), this, SLOT(ClearButtonClicked())); connect(mUI.mButtonBox->button(QDialogButtonBox::Save), SIGNAL(clicked()), this, SLOT(SaveButtonClicked())); QSettings settings; resize(settings.value(SETTINGS_LOG_VIEW_WIDTH, 400).toInt(), settings.value(SETTINGS_LOG_VIEW_HEIGHT, 300).toInt()); } LogView::~LogView() { QSettings settings; settings.setValue(SETTINGS_LOG_VIEW_WIDTH, size().width()); settings.setValue(SETTINGS_LOG_VIEW_HEIGHT, size().height()); } void LogView::AppendLine(const QString &line) { mUI.mLogEdit->appendPlainText(line); } void LogView::CloseButtonClicked() { close(); } void LogView::ClearButtonClicked() { mUI.mLogEdit->clear(); } void LogView::SaveButtonClicked() { QString fileName = QFileDialog::getSaveFileName(this, tr("Save Log"), "", tr("Text files (*.txt *.log);;All files (*.*)")); if (!fileName.isEmpty()) { QFile file(fileName); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { QMessageBox::warning(this, tr("Cppcheck"), tr("Could not open file for writing: \"%1\"").arg(fileName)); return; } QTextStream out(&file); out << mUI.mLogEdit->toPlainText(); } } cppcheck-1.61/gui/logview.h000066400000000000000000000030421217722632100156340ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #ifndef LOGVIEW_H #define LOGVIEW_H #include #include "ui_logview.h" /// @addtogroup GUI /// @{ /** * @brief A tool window that shows checking log. * */ class LogView : public QWidget { Q_OBJECT public: LogView(QWidget *parent = 0); ~LogView(); /** * @brief Append new log file to view. * @param line String to add. * */ void AppendLine(const QString &line); protected slots: /** * @brief Called when close button is clicked. * */ void CloseButtonClicked(); /** * @brief Called when clear button is clicked. * */ void ClearButtonClicked(); /** * @brief Called when save button is clicked. * */ void SaveButtonClicked(); private: Ui::LogView mUI; }; /// @} #endif // LOGVIEW_H cppcheck-1.61/gui/logview.ui000066400000000000000000000017661217722632100160350ustar00rootroot00000000000000 LogView 0 0 400 300 Qt::NoContextMenu Checking Log false true QDialogButtonBox::Close|QDialogButtonBox::Reset|QDialogButtonBox::Save cppcheck-1.61/gui/main.cpp000066400000000000000000000101641217722632100154420ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include #include #include #include #include #ifdef _WIN32 #include #else #include #endif #include "cppcheck.h" #include "common.h" #include "mainwindow.h" #include "erroritem.h" #include "aboutdialog.h" #include "translationhandler.h" void ShowUsage(); void ShowVersion(); bool CheckArgs(const QStringList &args); int main(int argc, char *argv[]) { QApplication app(argc, argv); #if QT_VERSION < 0x050000 // Set codecs so that UTF-8 strings in sources are handled correctly. // This is ONLY needed for Qt versions 4.x. // Qt 5.x assumes UTF-8 by default. QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8")); QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); #endif QCoreApplication::setOrganizationName("Cppcheck"); QCoreApplication::setApplicationName("Cppcheck-GUI"); TranslationHandler* th = new TranslationHandler(&app); QSettings* settings = new QSettings("Cppcheck", "Cppcheck-GUI", &app); th->SetLanguage(settings->value(SETTINGS_LANGUAGE, th->SuggestLanguage()).toString()); if (!CheckArgs(app.arguments())) return 0; app.setWindowIcon(QIcon(":icon.png")); // Register this metatype that is used to transfer error info qRegisterMetaType("ErrorItem"); MainWindow window(th, settings); window.show(); return app.exec(); } // Check only arguments needing action before GUI is shown. // Rest of the arguments are handled in MainWindow::HandleCLIParams() bool CheckArgs(const QStringList &args) { if (args.contains("-h") || args.contains("--help")) { ShowUsage(); return false; } if (args.contains("-v") || args.contains("--version")) { ShowVersion(); return false; } return true; } void ShowUsage() { QString helpMessage = MainWindow::tr( "Cppcheck GUI.\n\n" "Syntax:\n" " cppcheck-gui [OPTIONS] [files or paths]\n\n" "Options:\n" " -h, --help Print this help\n" " -p Open given project file and start checking it\n" " -l Open given results xml file\n" " -d Specify the directory that was checked to generate the results xml specified with -l\n" " -v, --version Show program version"); #if defined(_WIN32) QMessageBox msgBox(QMessageBox::Information, MainWindow::tr("Cppcheck GUI - Command line parameters"), helpMessage, QMessageBox::Ok ); (void)msgBox.exec(); #else std::cout << helpMessage.toStdString() << std::endl; #endif } void ShowVersion() { #if defined(_WIN32) AboutDialog *dlg = new AboutDialog(CppCheck::version(), CppCheck::extraVersion(), 0); dlg->exec(); delete dlg; #else std::string versionMessage("Cppcheck "); versionMessage += CppCheck::version(); const char * extraVersion = CppCheck::extraVersion(); if (*extraVersion != 0) versionMessage += std::string(" (") + extraVersion + ")"; std::cout << versionMessage << std::endl; #endif } cppcheck-1.61/gui/main.ui000066400000000000000000000461271217722632100153050ustar00rootroot00000000000000 MainWindow 0 0 640 480 0 0 640 480 Cppcheck 22 22 0 0 0 0 16777215 16777215 0 0 640 25 &File &View &Toolbars &Help &Check C++ standard C standard &Edit Standard TopToolBarArea false Categories TopToolBarArea false Filter TopToolBarArea false &License... A&uthors... :/images/help-browser.png:/images/help-browser.png &About... &Files... Check files Check files Ctrl+F :/icon.png:/icon.png &Directory... Check directory Check directory Ctrl+D :/images/view-refresh.png:/images/view-refresh.png &Recheck files Ctrl+R :/images/process-stop.png:/images/process-stop.png &Stop Stop checking Stop checking Esc :/images/media-floppy.png:/images/media-floppy.png &Save results to file... Ctrl+S &Quit :/images/edit-clear.png:/images/edit-clear.png &Clear results :/images/preferences-system.png:/images/preferences-system.png &Preferences true :/images/applications-development.png:/images/applications-development.png Style warnings Show style warnings Show style warnings true :/images/showerrors.png:/images/showerrors.png Errors Show errors Show errors &Check all &Uncheck all Collapse &all &Expand all true &Standard Standard items &Contents Open the help contents F1 Toolbar true &Categories Error categories &Open XML... :/images/openproject.png:/images/openproject.png Open P&roject File... :/images/scratchpad.png:/images/scratchpad.png Show S&cratchpad... &New Project File... &Log View Log View false C&lose Project File false &Edit Project File... :/images/text-x-generic.png:/images/text-x-generic.png &Statistics true :/images/showwarnings.png:/images/showwarnings.png Warnings Show warnings Show warnings true :/images/showperformance.png:/images/showperformance.png Performance warnings Show performance warnings Show performance warnings false Show &hidden true :/images/dialog-information.png:/images/dialog-information.png Information Show information messages true :/images/applications-system.png:/images/applications-system.png Portability Show portability warnings true &Filter Filter results Project MRU placeholder true true Windows 32-bit ANSI true Windows 32-bit Unicode true Unix 32-bit true Unix 64-bit true Windows 64-bit false Platforms false true true C++11 true true C99 true Posix true C11 true C89 true C++03 ResultsView QWidget
resultsview.h
1
cppcheck-1.61/gui/mainwindow.cpp000066400000000000000000001227471217722632100167050ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include #include #include #include #include #include #include #include #include "mainwindow.h" #include "cppcheck.h" #include "applicationlist.h" #include "aboutdialog.h" #include "common.h" #include "threadhandler.h" #include "fileviewdialog.h" #include "projectfile.h" #include "project.h" #include "report.h" #include "scratchpad.h" #include "statsdialog.h" #include "settingsdialog.h" #include "threadresult.h" #include "translationhandler.h" #include "logview.h" #include "filelist.h" #include "showtypes.h" static const QString OnlineHelpURL("http://cppcheck.sourceforge.net/manual.html"); MainWindow::MainWindow(TranslationHandler* th, QSettings* settings) : mSettings(settings), mApplications(new ApplicationList(this)), mTranslation(th), mLogView(NULL), mScratchPad(NULL), mProject(NULL), mPlatformActions(new QActionGroup(this)), mCStandardActions(new QActionGroup(this)), mCppStandardActions(new QActionGroup(this)), mExiting(false) { mUI.setupUi(this); mUI.mResults->Initialize(mSettings, mApplications); mThread = new ThreadHandler(this); // Filter timer to delay filtering results slightly while typing mFilterTimer = new QTimer(this); mFilterTimer->setInterval(500); mFilterTimer->setSingleShot(true); connect(mFilterTimer, SIGNAL(timeout()), this, SLOT(FilterResults())); // "Filter" toolbar mLineEditFilter = new QLineEdit(mUI.mToolBarFilter); mLineEditFilter->setPlaceholderText(tr("Quick Filter:")); mUI.mToolBarFilter->addWidget(mLineEditFilter); connect(mLineEditFilter, SIGNAL(textChanged(const QString&)), mFilterTimer, SLOT(start())); connect(mLineEditFilter, SIGNAL(returnPressed()), this, SLOT(FilterResults())); connect(mUI.mActionQuit, SIGNAL(triggered()), this, SLOT(close())); connect(mUI.mActionCheckFiles, SIGNAL(triggered()), this, SLOT(CheckFiles())); connect(mUI.mActionCheckDirectory, SIGNAL(triggered()), this, SLOT(CheckDirectory())); connect(mUI.mActionSettings, SIGNAL(triggered()), this, SLOT(ProgramSettings())); connect(mUI.mActionClearResults, SIGNAL(triggered()), this, SLOT(ClearResults())); connect(mUI.mActionOpenXML, SIGNAL(triggered()), this, SLOT(OpenResults())); connect(mUI.mActionShowStyle, SIGNAL(toggled(bool)), this, SLOT(ShowStyle(bool))); connect(mUI.mActionShowErrors, SIGNAL(toggled(bool)), this, SLOT(ShowErrors(bool))); connect(mUI.mActionShowWarnings, SIGNAL(toggled(bool)), this, SLOT(ShowWarnings(bool))); connect(mUI.mActionShowPortability, SIGNAL(toggled(bool)), this, SLOT(ShowPortability(bool))); connect(mUI.mActionShowPerformance, SIGNAL(toggled(bool)), this, SLOT(ShowPerformance(bool))); connect(mUI.mActionShowInformation, SIGNAL(toggled(bool)), this, SLOT(ShowInformation(bool))); connect(mUI.mActionCheckAll, SIGNAL(triggered()), this, SLOT(CheckAll())); connect(mUI.mActionUncheckAll, SIGNAL(triggered()), this, SLOT(UncheckAll())); connect(mUI.mActionCollapseAll, SIGNAL(triggered()), mUI.mResults, SLOT(CollapseAllResults())); connect(mUI.mActionExpandAll, SIGNAL(triggered()), mUI.mResults, SLOT(ExpandAllResults())); connect(mUI.mActionShowHidden, SIGNAL(triggered()), mUI.mResults, SLOT(ShowHiddenResults())); connect(mUI.mActionViewLog, SIGNAL(triggered()), this, SLOT(ShowLogView())); connect(mUI.mActionViewStats, SIGNAL(triggered()), this, SLOT(ShowStatistics())); connect(mUI.mActionRecheck, SIGNAL(triggered()), this, SLOT(ReCheck())); connect(mUI.mActionStop, SIGNAL(triggered()), this, SLOT(StopChecking())); connect(mUI.mActionSave, SIGNAL(triggered()), this, SLOT(Save())); // About menu connect(mUI.mActionAbout, SIGNAL(triggered()), this, SLOT(About())); connect(mUI.mActionLicense, SIGNAL(triggered()), this, SLOT(ShowLicense())); // View > Toolbar menu connect(mUI.mActionToolBarMain, SIGNAL(toggled(bool)), this, SLOT(ToggleMainToolBar())); connect(mUI.mActionToolBarView, SIGNAL(toggled(bool)), this, SLOT(ToggleViewToolBar())); connect(mUI.mActionToolBarFilter, SIGNAL(toggled(bool)), this, SLOT(ToggleFilterToolBar())); connect(mUI.mActionAuthors, SIGNAL(triggered()), this, SLOT(ShowAuthors())); connect(mThread, SIGNAL(Done()), this, SLOT(CheckDone())); connect(mUI.mResults, SIGNAL(GotResults()), this, SLOT(ResultsAdded())); connect(mUI.mResults, SIGNAL(ResultsHidden(bool)), mUI.mActionShowHidden, SLOT(setEnabled(bool))); connect(mUI.mMenuView, SIGNAL(aboutToShow()), this, SLOT(AboutToShowViewMenu())); // File menu connect(mUI.mActionNewProjectFile, SIGNAL(triggered()), this, SLOT(NewProjectFile())); connect(mUI.mActionOpenProjectFile, SIGNAL(triggered()), this, SLOT(OpenProjectFile())); connect(mUI.mActionShowScratchpad, SIGNAL(triggered()), this, SLOT(ShowScratchpad())); connect(mUI.mActionCloseProjectFile, SIGNAL(triggered()), this, SLOT(CloseProjectFile())); connect(mUI.mActionEditProjectFile, SIGNAL(triggered()), this, SLOT(EditProjectFile())); connect(mUI.mActionHelpContents, SIGNAL(triggered()), this, SLOT(OpenHelpContents())); LoadSettings(); mThread->Initialize(mUI.mResults); FormatAndSetTitle(); EnableCheckButtons(true); mUI.mActionClearResults->setEnabled(false); mUI.mActionSave->setEnabled(false); mUI.mActionRecheck->setEnabled(false); EnableProjectOpenActions(true); EnableProjectActions(false); // Must setup MRU menu before CLI param handling as it can load a // project file and update MRU menu. for (int i = 0; i < MaxRecentProjects; ++i) { mRecentProjectActs[i] = new QAction(this); mRecentProjectActs[i]->setVisible(false); connect(mRecentProjectActs[i], SIGNAL(triggered()), this, SLOT(OpenRecentProject())); } mRecentProjectActs[MaxRecentProjects] = NULL; // The separator mUI.mActionProjectMRU->setVisible(false); UpdateMRUMenuItems(); QStringList args = QCoreApplication::arguments(); //Remove the application itself args.removeFirst(); if (!args.isEmpty()) { HandleCLIParams(args); } for (int i = 0; i < mPlatforms.getCount(); i++) { Platform plat = mPlatforms.mPlatforms[i]; QAction *act = new QAction(this); plat.mActMainWindow = act; mPlatforms.mPlatforms[i] = plat; act->setText(plat.mTitle); act->setData(plat.mType); act->setCheckable(true); act->setActionGroup(mPlatformActions); mUI.mMenuCheck->insertAction(mUI.mActionPlatforms, act); connect(act, SIGNAL(triggered()), this, SLOT(SelectPlatform())); } mUI.mActionC89->setActionGroup(mCStandardActions); mUI.mActionC99->setActionGroup(mCStandardActions); mUI.mActionC11->setActionGroup(mCStandardActions); mUI.mActionCpp03->setActionGroup(mCppStandardActions); mUI.mActionCpp11->setActionGroup(mCppStandardActions); // For Windows platforms default to Win32 checked platform. // For other platforms default to unspecified/default which means the // platform Cppcheck GUI was compiled on. #if defined(_WIN32) Platform &plat = mPlatforms.get(Settings::Win32A); #else Platform &plat = mPlatforms.get(Settings::Unspecified); #endif plat.mActMainWindow->setChecked(true); mSettings->setValue(SETTINGS_CHECKED_PLATFORM, plat.mType); } MainWindow::~MainWindow() { delete mLogView; delete mProject; delete mScratchPad; } void MainWindow::HandleCLIParams(const QStringList ¶ms) { if (params.contains("-p")) { const int ind = params.indexOf("-p"); if ((ind + 1) < params.length()) LoadProjectFile(params[ind + 1]); } else if (params.contains("-l")) { QString logFile; const int ind = params.indexOf("-l"); if ((ind + 1) < params.length()) logFile = params[ind + 1]; if (params.contains("-d")) { QString checkedDir; const int ind = params.indexOf("-d"); if ((ind + 1) < params.length()) checkedDir = params[ind + 1]; LoadResults(logFile, checkedDir); } else { LoadResults(logFile); } } else DoCheckFiles(params); } void MainWindow::LoadSettings() { // Window/dialog sizes if (mSettings->value(SETTINGS_WINDOW_MAXIMIZED, false).toBool()) { showMaximized(); } else { resize(mSettings->value(SETTINGS_WINDOW_WIDTH, 800).toInt(), mSettings->value(SETTINGS_WINDOW_HEIGHT, 600).toInt()); } ShowTypes *types = mUI.mResults->GetShowTypes(); mUI.mActionShowStyle->setChecked(types->isShown(ShowTypes::ShowStyle)); mUI.mActionShowErrors->setChecked(types->isShown(ShowTypes::ShowErrors)); mUI.mActionShowWarnings->setChecked(types->isShown(ShowTypes::ShowWarnings)); mUI.mActionShowPortability->setChecked(types->isShown(ShowTypes::ShowPortability)); mUI.mActionShowPerformance->setChecked(types->isShown(ShowTypes::ShowPerformance)); mUI.mActionShowInformation->setChecked(types->isShown(ShowTypes::ShowInformation)); const bool stdCpp03 = mSettings->value(SETTINGS_STD_CPP03, false).toBool(); mUI.mActionCpp03->setChecked(stdCpp03); const bool stdCpp11 = mSettings->value(SETTINGS_STD_CPP11, true).toBool(); mUI.mActionCpp11->setChecked(stdCpp11 || !stdCpp03); const bool stdC89 = mSettings->value(SETTINGS_STD_C89, false).toBool(); mUI.mActionC89->setChecked(stdC89); const bool stdC11 = mSettings->value(SETTINGS_STD_C11, false).toBool(); mUI.mActionC11->setChecked(stdC11); const bool stdC99 = mSettings->value(SETTINGS_STD_C99, true).toBool(); mUI.mActionC99->setChecked(stdC99 || (!stdC89 && !stdC11)); const bool stdPosix = mSettings->value(SETTINGS_STD_POSIX, false).toBool(); mUI.mActionPosix->setChecked(stdPosix); // Main window settings const bool showMainToolbar = mSettings->value(SETTINGS_TOOLBARS_MAIN_SHOW, true).toBool(); mUI.mActionToolBarMain->setChecked(showMainToolbar); mUI.mToolBarMain->setVisible(showMainToolbar); const bool showViewToolbar = mSettings->value(SETTINGS_TOOLBARS_VIEW_SHOW, true).toBool(); mUI.mActionToolBarView->setChecked(showViewToolbar); mUI.mToolBarView->setVisible(showViewToolbar); const bool showFilterToolbar = mSettings->value(SETTINGS_TOOLBARS_FILTER_SHOW, true).toBool(); mUI.mActionToolBarFilter->setChecked(showFilterToolbar); mUI.mToolBarFilter->setVisible(showFilterToolbar); bool succeeded = mApplications->LoadSettings(); if (!succeeded) { const QString msg = tr("There was a problem with loading the editor application settings.\n\n" "This is probably because the settings were changed between the Cppcheck versions. " "Please check (and fix) the editor application settings, otherwise the editor " "program might not start correctly."); QMessageBox msgBox(QMessageBox::Warning, tr("Cppcheck"), msg, QMessageBox::Ok, this); msgBox.exec(); } } void MainWindow::SaveSettings() const { // Window/dialog sizes mSettings->setValue(SETTINGS_WINDOW_WIDTH, size().width()); mSettings->setValue(SETTINGS_WINDOW_HEIGHT, size().height()); mSettings->setValue(SETTINGS_WINDOW_MAXIMIZED, isMaximized()); // Show * states mSettings->setValue(SETTINGS_SHOW_STYLE, mUI.mActionShowStyle->isChecked()); mSettings->setValue(SETTINGS_SHOW_ERRORS, mUI.mActionShowErrors->isChecked()); mSettings->setValue(SETTINGS_SHOW_WARNINGS, mUI.mActionShowWarnings->isChecked()); mSettings->setValue(SETTINGS_SHOW_PORTABILITY, mUI.mActionShowPortability->isChecked()); mSettings->setValue(SETTINGS_SHOW_PERFORMANCE, mUI.mActionShowPerformance->isChecked()); mSettings->setValue(SETTINGS_SHOW_INFORMATION, mUI.mActionShowInformation->isChecked()); mSettings->setValue(SETTINGS_STD_CPP03, mUI.mActionCpp03->isChecked()); mSettings->setValue(SETTINGS_STD_CPP11, mUI.mActionCpp11->isChecked()); mSettings->setValue(SETTINGS_STD_C89, mUI.mActionC89->isChecked()); mSettings->setValue(SETTINGS_STD_C99, mUI.mActionC99->isChecked()); mSettings->setValue(SETTINGS_STD_C11, mUI.mActionC11->isChecked()); mSettings->setValue(SETTINGS_STD_POSIX, mUI.mActionPosix->isChecked()); // Main window settings mSettings->setValue(SETTINGS_TOOLBARS_MAIN_SHOW, mUI.mToolBarMain->isVisible()); mSettings->setValue(SETTINGS_TOOLBARS_VIEW_SHOW, mUI.mToolBarView->isVisible()); mSettings->setValue(SETTINGS_TOOLBARS_FILTER_SHOW, mUI.mToolBarFilter->isVisible()); mApplications->SaveSettings(); mSettings->setValue(SETTINGS_LANGUAGE, mTranslation->GetCurrentLanguage()); mUI.mResults->SaveSettings(mSettings); } void MainWindow::DoCheckFiles(const QStringList &files) { if (files.isEmpty()) { return; } ClearResults(); FileList pathList; pathList.AddPathList(files); if (mProject) pathList.AddExcludeList(mProject->GetProjectFile()->GetExcludedPaths()); QStringList fileNames = pathList.GetFileList(); mUI.mResults->Clear(true); mThread->ClearFiles(); if (fileNames.isEmpty()) { QMessageBox msg(QMessageBox::Warning, tr("Cppcheck"), tr("No suitable files found to check!"), QMessageBox::Ok, this); msg.exec(); return; } mUI.mResults->CheckingStarted(fileNames.count()); mThread->SetFiles(fileNames); QDir inf(mCurrentDirectory); const QString checkPath = inf.canonicalPath(); SetPath(SETTINGS_LAST_CHECK_PATH, checkPath); CheckLockDownUI(); // lock UI while checking mUI.mResults->SetCheckDirectory(checkPath); Settings checkSettings = GetCppcheckSettings(); if (mProject) qDebug() << "Checking project file" << mProject->GetProjectFile()->GetFilename(); mThread->Check(checkSettings, false); } void MainWindow::CheckCode(const QString& code, const QString& filename) { // Initialize dummy ThreadResult as ErrorLogger ThreadResult result; result.SetFiles(QStringList(filename)); connect(&result, SIGNAL(Progress(int, const QString&)), mUI.mResults, SLOT(Progress(int, const QString&))); connect(&result, SIGNAL(Error(const ErrorItem &)), mUI.mResults, SLOT(Error(const ErrorItem &))); connect(&result, SIGNAL(Log(const QString &)), this, SLOT(Log(const QString &))); connect(&result, SIGNAL(DebugError(const ErrorItem &)), this, SLOT(DebugError(const ErrorItem &))); // Create CppCheck instance CppCheck cppcheck(result, true); cppcheck.settings() = GetCppcheckSettings(); // Check CheckLockDownUI(); ClearResults(); mUI.mResults->CheckingStarted(1); cppcheck.check(filename.toStdString(), code.toStdString()); CheckDone(); } QStringList MainWindow::SelectFilesToCheck(QFileDialog::FileMode mode) { if (mProject) { QMessageBox msgBox(this); msgBox.setWindowTitle(tr("Cppcheck")); const QString msg(tr("You must close the project file before selecting new files or directories!")); msgBox.setText(msg); msgBox.setIcon(QMessageBox::Critical); msgBox.exec(); return QStringList(); } QStringList selected; // NOTE: we use QFileDialog::getOpenFileNames() and // QFileDialog::getExistingDirectory() because they show native Windows // selection dialog which is a lot more usable than Qt:s own dialog. if (mode == QFileDialog::ExistingFiles) { selected = QFileDialog::getOpenFileNames(this, tr("Select files to check"), GetPath(SETTINGS_LAST_CHECK_PATH)); if (selected.isEmpty()) mCurrentDirectory.clear(); else { QFileInfo inf(selected[0]); mCurrentDirectory = inf.absolutePath(); } FormatAndSetTitle(); } else if (mode == QFileDialog::DirectoryOnly) { QString dir = QFileDialog::getExistingDirectory(this, tr("Select directory to check"), GetPath(SETTINGS_LAST_CHECK_PATH)); if (!dir.isEmpty()) { qDebug() << "Setting current directory to: " << dir; mCurrentDirectory = dir; selected.append(dir); dir = QDir::toNativeSeparators(dir); FormatAndSetTitle(dir); } } SetPath(SETTINGS_LAST_CHECK_PATH, mCurrentDirectory); return selected; } void MainWindow::CheckFiles() { DoCheckFiles(SelectFilesToCheck(QFileDialog::ExistingFiles)); } void MainWindow::CheckDirectory() { QStringList dir = SelectFilesToCheck(QFileDialog::DirectoryOnly); if (dir.isEmpty()) return; QDir checkDir(dir[0]); QStringList filters; filters << "*.cppcheck"; checkDir.setFilter(QDir::Files | QDir::Readable); checkDir.setNameFilters(filters); QStringList projFiles = checkDir.entryList(); if (!projFiles.empty()) { if (projFiles.size() == 1) { // If one project file found, suggest loading it QMessageBox msgBox(this); msgBox.setWindowTitle(tr("Cppcheck")); const QString msg(tr("Found project file: %1\n\nDo you want to " "load this project file instead?").arg(projFiles[0])); msgBox.setText(msg); msgBox.setIcon(QMessageBox::Warning); msgBox.addButton(QMessageBox::Yes); msgBox.addButton(QMessageBox::No); msgBox.setDefaultButton(QMessageBox::Yes); int dlgResult = msgBox.exec(); if (dlgResult == QMessageBox::Yes) { QString path = checkDir.canonicalPath(); if (!path.endsWith("/")) path += "/"; path += projFiles[0]; LoadProjectFile(path); } else { DoCheckFiles(dir); } } else { // If multiple project files found inform that there are project // files also available. QMessageBox msgBox(this); msgBox.setWindowTitle(tr("Cppcheck")); const QString msg(tr("Found project files from the directory.\n\n" "Do you want to proceed checking without " "using any of these project files?")); msgBox.setText(msg); msgBox.setIcon(QMessageBox::Warning); msgBox.addButton(QMessageBox::Yes); msgBox.addButton(QMessageBox::No); msgBox.setDefaultButton(QMessageBox::Yes); int dlgResult = msgBox.exec(); if (dlgResult == QMessageBox::Yes) { DoCheckFiles(dir); } } } else { DoCheckFiles(dir); } } void MainWindow::AddIncludeDirs(const QStringList &includeDirs, Settings &result) { QString dir; foreach(dir, includeDirs) { QString incdir; if (!QDir::isAbsolutePath(dir)) incdir = mCurrentDirectory + "/"; incdir += dir; incdir = QDir::cleanPath(incdir); // include paths must end with '/' if (!incdir.endsWith("/")) incdir += "/"; result._includePaths.push_back(incdir.toStdString()); } } Settings MainWindow::GetCppcheckSettings() { Settings result; const QString applicationFilePath = QCoreApplication::applicationFilePath(); result.library.load(applicationFilePath.toLatin1(), "std"); // If project file loaded, read settings from it if (mProject) { ProjectFile *pfile = mProject->GetProjectFile(); QStringList dirs = pfile->GetIncludeDirs(); AddIncludeDirs(dirs, result); QStringList defines = pfile->GetDefines(); QString define; foreach(define, defines) { if (!result.userDefines.empty()) result.userDefines += ";"; result.userDefines += define.toStdString(); } // Only check the given -D configuration if (!defines.isEmpty()) result._maxConfigs = 1; } // Include directories (and files) are searched in listed order. // Global include directories must be added AFTER the per project include // directories so per project include directories can override global ones. const QString globalIncludes = mSettings->value(SETTINGS_GLOBAL_INCLUDE_PATHS).toString(); if (!globalIncludes.isEmpty()) { QStringList includes = globalIncludes.split(";"); AddIncludeDirs(includes, result); } result.addEnabled("warning"); result.addEnabled("style"); result.addEnabled("performance"); result.addEnabled("portability"); result.addEnabled("information"); result.addEnabled("missingInclude"); result.debug = false; result.debugwarnings = mSettings->value(SETTINGS_SHOW_DEBUG_WARNINGS, false).toBool(); result._errorsOnly = false; result._verbose = true; result._force = mSettings->value(SETTINGS_CHECK_FORCE, 1).toBool(); result._xml = false; result._jobs = mSettings->value(SETTINGS_CHECK_THREADS, 1).toInt(); result._inlineSuppressions = mSettings->value(SETTINGS_INLINE_SUPPRESSIONS, false).toBool(); result.inconclusive = mSettings->value(SETTINGS_INCONCLUSIVE_ERRORS, false).toBool(); result.platformType = (Settings::PlatformType) mSettings->value(SETTINGS_CHECKED_PLATFORM, 0).toInt(); result.standards.cpp = mSettings->value(SETTINGS_STD_CPP11, true).toBool() ? Standards::CPP11 : Standards::CPP03; result.standards.c = mSettings->value(SETTINGS_STD_C99, true).toBool() ? Standards::C99 : (mSettings->value(SETTINGS_STD_C11, false).toBool() ? Standards::C11 : Standards::C89); result.standards.posix = mSettings->value(SETTINGS_STD_POSIX, false).toBool(); if (result._jobs <= 1) { result._jobs = 1; } return result; } void MainWindow::CheckDone() { if (mExiting) { close(); return; } mUI.mResults->CheckingFinished(); EnableCheckButtons(true); mUI.mActionSettings->setEnabled(true); mUI.mActionOpenXML->setEnabled(true); EnableProjectActions(true); EnableProjectOpenActions(true); mPlatformActions->setEnabled(true); mCStandardActions->setEnabled(true); mCppStandardActions->setEnabled(true); mUI.mActionPosix->setEnabled(true); if (mScratchPad) mScratchPad->setEnabled(true); if (mUI.mResults->HasResults()) { mUI.mActionClearResults->setEnabled(true); mUI.mActionSave->setEnabled(true); } for (int i = 0; i < MaxRecentProjects + 1; i++) { if (mRecentProjectActs[i] != NULL) mRecentProjectActs[i]->setEnabled(true); } // Notify user - if the window is not active - that check is ready QApplication::alert(this, 3000); } void MainWindow::CheckLockDownUI() { EnableCheckButtons(false); mUI.mActionSettings->setEnabled(false); mUI.mActionOpenXML->setEnabled(false); EnableProjectActions(false); EnableProjectOpenActions(false); mPlatformActions->setEnabled(false); mCStandardActions->setEnabled(false); mCppStandardActions->setEnabled(false); mUI.mActionPosix->setEnabled(false); if (mScratchPad) mScratchPad->setEnabled(false); for (int i = 0; i < MaxRecentProjects + 1; i++) { if (mRecentProjectActs[i] != NULL) mRecentProjectActs[i]->setEnabled(false); } } void MainWindow::ProgramSettings() { SettingsDialog dialog(mApplications, mTranslation, this); if (dialog.exec() == QDialog::Accepted) { dialog.SaveSettingValues(); mUI.mResults->UpdateSettings(dialog.ShowFullPath(), dialog.SaveFullPath(), dialog.SaveAllErrors(), dialog.ShowNoErrorsMessage(), dialog.ShowErrorId()); const QString newLang = mSettings->value(SETTINGS_LANGUAGE, "en").toString(); SetLanguage(newLang); } } void MainWindow::ReCheck() { const QStringList files = mThread->GetReCheckFiles(); if (files.empty()) return; // Clear details, statistics and progress mUI.mResults->Clear(false); // Clear results for changed files for (int i = 0; i < files.size(); ++i) mUI.mResults->Clear(files[i]); CheckLockDownUI(); // lock UI while checking mUI.mResults->CheckingStarted(files.size()); if (mProject) qDebug() << "Rechecking project file" << mProject->GetProjectFile()->GetFilename(); mThread->Check(GetCppcheckSettings(), true); } void MainWindow::ClearResults() { mUI.mResults->Clear(true); mUI.mActionClearResults->setEnabled(false); mUI.mActionSave->setEnabled(false); } void MainWindow::OpenResults() { if (mUI.mResults->HasResults()) { QMessageBox msgBox(this); msgBox.setWindowTitle(tr("Cppcheck")); const QString msg(tr("Current results will be cleared.\n\n" "Opening a new XML file will clear current results." "Do you want to proceed?")); msgBox.setText(msg); msgBox.setIcon(QMessageBox::Warning); msgBox.addButton(QMessageBox::Yes); msgBox.addButton(QMessageBox::No); msgBox.setDefaultButton(QMessageBox::Yes); int dlgResult = msgBox.exec(); if (dlgResult == QMessageBox::No) { return; } } QString selectedFilter; const QString filter(tr("XML files (*.xml)")); QString selectedFile = QFileDialog::getOpenFileName(this, tr("Open the report file"), GetPath(SETTINGS_LAST_RESULT_PATH), filter, &selectedFilter); if (!selectedFile.isEmpty()) { LoadResults(selectedFile); } } void MainWindow::LoadResults(const QString selectedFile) { if (!selectedFile.isEmpty()) { mUI.mResults->Clear(true); mUI.mResults->ReadErrorsXml(selectedFile); SetPath(SETTINGS_LAST_RESULT_PATH, selectedFile); } } void MainWindow::LoadResults(const QString selectedFile, const QString sourceDirectory) { LoadResults(selectedFile); mUI.mResults->SetCheckDirectory(sourceDirectory); } void MainWindow::EnableCheckButtons(bool enable) { mUI.mActionStop->setEnabled(!enable); mUI.mActionCheckFiles->setEnabled(enable); if (!enable || mThread->HasPreviousFiles()) mUI.mActionRecheck->setEnabled(enable); mUI.mActionCheckDirectory->setEnabled(enable); } void MainWindow::ShowStyle(bool checked) { mUI.mResults->ShowResults(ShowTypes::ShowStyle, checked); } void MainWindow::ShowErrors(bool checked) { mUI.mResults->ShowResults(ShowTypes::ShowErrors, checked); } void MainWindow::ShowWarnings(bool checked) { mUI.mResults->ShowResults(ShowTypes::ShowWarnings, checked); } void MainWindow::ShowPortability(bool checked) { mUI.mResults->ShowResults(ShowTypes::ShowPortability, checked); } void MainWindow::ShowPerformance(bool checked) { mUI.mResults->ShowResults(ShowTypes::ShowPerformance, checked); } void MainWindow::ShowInformation(bool checked) { mUI.mResults->ShowResults(ShowTypes::ShowInformation, checked); } void MainWindow::CheckAll() { ToggleAllChecked(true); } void MainWindow::UncheckAll() { ToggleAllChecked(false); } void MainWindow::closeEvent(QCloseEvent *event) { // Check that we aren't checking files if (!mThread->IsChecking()) { SaveSettings(); event->accept(); } else { const QString text(tr("Checking is running.\n\n" \ "Do you want to stop the checking and exit Cppcheck?.")); QMessageBox msg(QMessageBox::Warning, tr("Cppcheck"), text, QMessageBox::Yes | QMessageBox::No, this); msg.setDefaultButton(QMessageBox::No); int rv = msg.exec(); if (rv == QMessageBox::Yes) { // This isn't really very clean way to close threads but since the app is // exiting it doesn't matter. mThread->Stop(); SaveSettings(); mExiting = true; } event->ignore(); } } void MainWindow::ToggleAllChecked(bool checked) { mUI.mActionShowStyle->setChecked(checked); ShowStyle(checked); mUI.mActionShowErrors->setChecked(checked); ShowErrors(checked); mUI.mActionShowWarnings->setChecked(checked); ShowWarnings(checked); mUI.mActionShowPortability->setChecked(checked); ShowPortability(checked); mUI.mActionShowPerformance->setChecked(checked); ShowPerformance(checked); mUI.mActionShowInformation->setChecked(checked); ShowInformation(checked); } void MainWindow::About() { AboutDialog *dlg = new AboutDialog(CppCheck::version(), CppCheck::extraVersion(), this); dlg->exec(); } void MainWindow::ShowLicense() { FileViewDialog *dlg = new FileViewDialog(":COPYING", tr("License"), this); dlg->resize(570, 400); dlg->exec(); } void MainWindow::ShowAuthors() { FileViewDialog *dlg = new FileViewDialog(":AUTHORS", tr("Authors"), this); dlg->resize(350, 400); dlg->exec(); } void MainWindow::Save() { QString selectedFilter; const QString filter(tr("XML files version 2 (*.xml);;XML files version 1 (*.xml);;Text files (*.txt);;CSV files (*.csv)")); QString selectedFile = QFileDialog::getSaveFileName(this, tr("Save the report file"), GetPath(SETTINGS_LAST_RESULT_PATH), filter, &selectedFilter); if (!selectedFile.isEmpty()) { Report::Type type = Report::TXT; if (selectedFilter == tr("XML files version 1 (*.xml)")) { type = Report::XML; if (!selectedFile.endsWith(".xml", Qt::CaseInsensitive)) selectedFile += ".xml"; } else if (selectedFilter == tr("XML files version 2 (*.xml)")) { type = Report::XMLV2; if (!selectedFile.endsWith(".xml", Qt::CaseInsensitive)) selectedFile += ".xml"; } else if (selectedFilter == tr("Text files (*.txt)")) { type = Report::TXT; if (!selectedFile.endsWith(".txt", Qt::CaseInsensitive)) selectedFile += ".txt"; } else if (selectedFilter == tr("CSV files (*.csv)")) { type = Report::CSV; if (!selectedFile.endsWith(".csv", Qt::CaseInsensitive)) selectedFile += ".csv"; } else { if (selectedFile.endsWith(".xml", Qt::CaseInsensitive)) type = Report::XML; else if (selectedFile.endsWith(".txt", Qt::CaseInsensitive)) type = Report::TXT; else if (selectedFile.endsWith(".csv", Qt::CaseInsensitive)) type = Report::CSV; } mUI.mResults->Save(selectedFile, type); SetPath(SETTINGS_LAST_RESULT_PATH, selectedFile); } } void MainWindow::ResultsAdded() { } void MainWindow::ToggleMainToolBar() { mUI.mToolBarMain->setVisible(mUI.mActionToolBarMain->isChecked()); } void MainWindow::ToggleViewToolBar() { mUI.mToolBarView->setVisible(mUI.mActionToolBarView->isChecked()); } void MainWindow::ToggleFilterToolBar() { mUI.mToolBarFilter->setVisible(mUI.mActionToolBarFilter->isChecked()); mLineEditFilter->clear(); // Clearing the filter also disables filtering } void MainWindow::FormatAndSetTitle(const QString &text) { QString title; if (text.isEmpty()) title = tr("Cppcheck"); else title = QString(tr("Cppcheck - %1")).arg(text); setWindowTitle(title); } void MainWindow::SetLanguage(const QString &code) { const QString currentLang = mTranslation->GetCurrentLanguage(); if (currentLang == code) return; if (mTranslation->SetLanguage(code)) { //Translate everything that is visible here mUI.retranslateUi(this); mUI.mResults->Translate(); delete mLogView; mLogView = 0; } } void MainWindow::AboutToShowViewMenu() { mUI.mActionToolBarMain->setChecked(mUI.mToolBarMain->isVisible()); mUI.mActionToolBarView->setChecked(mUI.mToolBarView->isVisible()); mUI.mActionToolBarFilter->setChecked(mUI.mToolBarFilter->isVisible()); } void MainWindow::StopChecking() { mThread->Stop(); mUI.mResults->DisableProgressbar(); } void MainWindow::OpenHelpContents() { OpenOnlineHelp(); } void MainWindow::OpenOnlineHelp() { QDesktopServices::openUrl(QUrl(OnlineHelpURL)); } void MainWindow::OpenProjectFile() { const QString lastPath = mSettings->value(SETTINGS_LAST_PROJECT_PATH, QString()).toString(); const QString filter = tr("Project files (*.cppcheck);;All files(*.*)"); const QString filepath = QFileDialog::getOpenFileName(this, tr("Select Project File"), GetPath(SETTINGS_LAST_PROJECT_PATH), filter); if (!filepath.isEmpty()) { const QFileInfo fi(filepath); if (fi.exists() && fi.isFile() && fi.isReadable()) { SetPath(SETTINGS_LAST_PROJECT_PATH, filepath); LoadProjectFile(filepath); } } } void MainWindow::ShowScratchpad() { if (!mScratchPad) mScratchPad = new ScratchPad(*this); mScratchPad->show(); if (!mScratchPad->isActiveWindow()) mScratchPad->activateWindow(); } void MainWindow::LoadProjectFile(const QString &filePath) { QFileInfo inf(filePath); const QString filename = inf.fileName(); FormatAndSetTitle(tr("Project:") + QString(" ") + filename); AddProjectMRU(filePath); mUI.mActionCloseProjectFile->setEnabled(true); mUI.mActionEditProjectFile->setEnabled(true); delete mProject; mProject = new Project(filePath, this); CheckProject(mProject); } void MainWindow::CheckProject(Project *project) { if (!project->IsOpen()) { if (!project->Open()) { delete mProject; mProject = 0; return; } } QFileInfo inf(project->Filename()); const QString rootpath = project->GetProjectFile()->GetRootPath(); // If the root path is not given or is not "current dir", use project // file's location directory as root path if (rootpath.isEmpty() || rootpath == ".") mCurrentDirectory = inf.canonicalPath(); else mCurrentDirectory = rootpath; QStringList paths = project->GetProjectFile()->GetCheckPaths(); // If paths not given then check the root path (which may be the project // file's location, see above). This is to keep the compatibility with // old "silent" project file loading when we checked the director where the // project file was located. if (paths.isEmpty()) { paths << mCurrentDirectory; } // Convert relative paths to absolute paths for (int i = 0; i < paths.size(); i++) { if (!QDir::isAbsolutePath(paths[i])) { QString path = mCurrentDirectory + "/"; path += paths[i]; paths[i] = QDir::cleanPath(path); } } DoCheckFiles(paths); } void MainWindow::NewProjectFile() { const QString filter = tr("Project files (*.cppcheck);;All files(*.*)"); QString filepath = QFileDialog::getSaveFileName(this, tr("Select Project Filename"), GetPath(SETTINGS_LAST_PROJECT_PATH), filter); if (filepath.isEmpty()) return; SetPath(SETTINGS_LAST_PROJECT_PATH, filepath); EnableProjectActions(true); QFileInfo inf(filepath); const QString filename = inf.fileName(); FormatAndSetTitle(tr("Project:") + QString(" ") + filename); delete mProject; mProject = new Project(filepath, this); mProject->Create(); if (mProject->Edit()) { AddProjectMRU(filepath); CheckProject(mProject); } } void MainWindow::CloseProjectFile() { delete mProject; mProject = NULL; EnableProjectActions(false); EnableProjectOpenActions(true); FormatAndSetTitle(); } void MainWindow::EditProjectFile() { if (!mProject) { QMessageBox msg(QMessageBox::Critical, tr("Cppcheck"), QString(tr("No project file loaded")), QMessageBox::Ok, this); msg.exec(); return; } mProject->Edit(); } void MainWindow::ShowLogView() { if (mLogView == NULL) mLogView = new LogView; mLogView->show(); if (!mLogView->isActiveWindow()) mLogView->activateWindow(); } void MainWindow::ShowStatistics() { StatsDialog statsDialog(this); // Show a dialog with the previous scan statistics and project information if (mProject) { statsDialog.setProject(*mProject); } statsDialog.setPathSelected(mCurrentDirectory); statsDialog.setNumberOfFilesScanned(mThread->GetPreviousFilesCount()); statsDialog.setScanDuration(mThread->GetPreviousScanDuration() / 1000.0); statsDialog.setStatistics(mUI.mResults->GetStatistics()); statsDialog.exec(); } void MainWindow::Log(const QString &logline) { if (mLogView) { mLogView->AppendLine(logline); } } void MainWindow::DebugError(const ErrorItem &item) { if (mLogView) { mLogView->AppendLine(item.ToString()); } } void MainWindow::FilterResults() { mUI.mResults->FilterResults(mLineEditFilter->text()); } void MainWindow::EnableProjectActions(bool enable) { mUI.mActionCloseProjectFile->setEnabled(enable); mUI.mActionEditProjectFile->setEnabled(enable); } void MainWindow::EnableProjectOpenActions(bool enable) { mUI.mActionNewProjectFile->setEnabled(enable); mUI.mActionOpenProjectFile->setEnabled(enable); } void MainWindow::OpenRecentProject() { QAction *action = qobject_cast(sender()); if (action) { const QString project = action->data().toString(); QFileInfo inf(project); if (inf.exists()) { LoadProjectFile(project); } else { const QString text(tr("The project file\n\n%1\n\n could not be found!\n\n" "Do you want to remove the file from the recently " "used projects -list?").arg(project)); QMessageBox msg(QMessageBox::Warning, tr("Cppcheck"), text, QMessageBox::Yes | QMessageBox::No, this); msg.setDefaultButton(QMessageBox::No); int rv = msg.exec(); if (rv == QMessageBox::Yes) { RemoveProjectMRU(project); } } } } void MainWindow::UpdateMRUMenuItems() { for (int i = 0; i < MaxRecentProjects + 1; i++) { if (mRecentProjectActs[i] != NULL) mUI.mMenuFile->removeAction(mRecentProjectActs[i]); } QStringList projects = mSettings->value(SETTINGS_MRU_PROJECTS).toStringList(); // Do a sanity check - remove duplicates and empty or space only items int removed = projects.removeDuplicates(); for (int i = projects.size() - 1; i >= 0; i--) { QString text = projects[i].trimmed(); if (text.isEmpty()) { projects.removeAt(i); removed++; } } if (removed) mSettings->setValue(SETTINGS_MRU_PROJECTS, projects); const int numRecentProjects = qMin(projects.size(), (int)MaxRecentProjects); for (int i = 0; i < numRecentProjects; i++) { const QString filename = QFileInfo(projects[i]).fileName(); const QString text = QString("&%1 %2").arg(i + 1).arg(filename); mRecentProjectActs[i]->setText(text); mRecentProjectActs[i]->setData(projects[i]); mRecentProjectActs[i]->setVisible(true); mUI.mMenuFile->insertAction(mUI.mActionProjectMRU, mRecentProjectActs[i]); } if (numRecentProjects > 1) mRecentProjectActs[numRecentProjects] = mUI.mMenuFile->insertSeparator(mUI.mActionProjectMRU); } void MainWindow::AddProjectMRU(const QString &project) { QStringList files = mSettings->value(SETTINGS_MRU_PROJECTS).toStringList(); files.removeAll(project); files.prepend(project); while (files.size() > MaxRecentProjects) files.removeLast(); mSettings->setValue(SETTINGS_MRU_PROJECTS, files); UpdateMRUMenuItems(); } void MainWindow::RemoveProjectMRU(const QString &project) { QStringList files = mSettings->value(SETTINGS_MRU_PROJECTS).toStringList(); files.removeAll(project); mSettings->setValue(SETTINGS_MRU_PROJECTS, files); UpdateMRUMenuItems(); } void MainWindow::SelectPlatform() { QAction *action = qobject_cast(sender()); if (action) { const Settings::PlatformType platform = (Settings::PlatformType) action->data().toInt(); mSettings->setValue(SETTINGS_CHECKED_PLATFORM, platform); } } cppcheck-1.61/gui/mainwindow.h000066400000000000000000000267011217722632100163430ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #ifndef MAINWINDOW_H #define MAINWINDOW_H #include #include #include #include #include #include #include "settings.h" #include "platforms.h" #include "ui_main.h" class ThreadHandler; class TranslationHandler; class ScratchPad; class LogView; class Project; class ErrorItem; class QAction; /// @addtogroup GUI /// @{ /** * @brief Main window for cppcheck-gui * */ class MainWindow : public QMainWindow { Q_OBJECT public: /** * @brief Maximum number of MRU project items in File-menu. */ enum { MaxRecentProjects = 5 }; MainWindow(TranslationHandler* th, QSettings* settings); virtual ~MainWindow(); /** * List of checked platforms. */ Platforms mPlatforms; /** * @brief Checks given code * * @param code Content of the (virtual) file to be checked * @param filename Name of the (virtual) file to be checked - determines language. */ void CheckCode(const QString& code, const QString& filename); public slots: /** * @brief Slot for check files menu item * */ void CheckFiles(); /** * @brief Slot to recheck files * */ void ReCheck(); /** * @brief Slot to clear all search results * */ void ClearResults(); /** * @brief Slot to open XML report file * */ void OpenResults(); /** * @brief Show errors with type "style" * @param checked Should errors be shown (true) or hidden (false) */ void ShowStyle(bool checked); /** * @brief Show errors with type "error" * @param checked Should errors be shown (true) or hidden (false) */ void ShowErrors(bool checked); /** * @brief Show errors with type "warning" * @param checked Should errors be shown (true) or hidden (false) */ void ShowWarnings(bool checked); /** * @brief Show errors with type "portability" * @param checked Should errors be shown (true) or hidden (false) */ void ShowPortability(bool checked); /** * @brief Show errors with type "performance" * @param checked Should errors be shown (true) or hidden (false) */ void ShowPerformance(bool checked); /** * @brief Show errors with type "information" * @param checked Should errors be shown (true) or hidden (false) */ void ShowInformation(bool checked); /** * @brief Slot to check all "Show errors" menu items */ void CheckAll(); /** * @brief Slot to uncheck all "Show errors" menu items */ void UncheckAll(); /** * @brief Slot for check directory menu item * */ void CheckDirectory(); /** * @brief Slot to open program's settings dialog * */ void ProgramSettings(); /** * @brief Slot to open program's about dialog * */ void About(); /** * @brief Slot to to show license text * */ void ShowLicense(); /** * @brief Slot to to show authors list * */ void ShowAuthors(); /** * @brief Slot to stop processing files * */ void Save(); /** * @brief Slot to create new project file * */ void NewProjectFile(); /** * @brief Slot to open project file and start checking contained paths. * */ void OpenProjectFile(); /** * @brief Slot to open project file and start checking contained paths. * */ void ShowScratchpad(); /** * @brief Slot to close open project file. * */ void CloseProjectFile(); /** * @brief Slot to edit project file. * */ void EditProjectFile(); /** * @brief Slot for showing the log view. * */ void ShowLogView(); /** * @brief Slot for showing the scan and project statistics. * */ void ShowStatistics(); protected slots: /** * @brief Slot for checkthread's done signal * */ void CheckDone(); /** * @brief Lock down UI while checking * */ void CheckLockDownUI(); /** * @brief Slot for enabling save and clear button * */ void ResultsAdded(); /** * @brief Slot for showing/hiding standard toolbar */ void ToggleMainToolBar(); /** * @brief Slot for showing/hiding Categories toolbar */ void ToggleViewToolBar(); /** * @brief Slot for showing/hiding Filter toolbar */ void ToggleFilterToolBar(); /** * @brief Slot for updating View-menu before it is shown. */ void AboutToShowViewMenu(); /** * @brief Slot when stop checking button is pressed * */ void StopChecking(); /** * @brief Open help file contents * */ void OpenHelpContents(); /** * @brief Add new line to log. * */ void Log(const QString &logline); /** * @brief Handle new debug error. * */ void DebugError(const ErrorItem &item); /** * @brief Filters the results in the result list. */ void FilterResults(); /** * @brief Opens recently opened project file. */ void OpenRecentProject(); /** * @brief Selects the platform as checked platform. */ void SelectPlatform(); private: /** * @brief Check the project. * @param project Pointer to the project to check. */ void CheckProject(Project *project); /** * @brief Set current language * @param code Language code of the language to set (e.g. "en"). */ void SetLanguage(const QString &code); /** * @brief Event coming when application is about to close. */ virtual void closeEvent(QCloseEvent *event); /** * @brief Helper function to toggle all show error menu items * @param checked Should all errors be shown (true) or hidden (false) */ void ToggleAllChecked(bool checked); /** * @brief Helper function to enable/disable all check,recheck buttons * */ void EnableCheckButtons(bool enable); /** * @brief Select files/or directory to check. * Helper function to open a dialog to ask user to select files or * directory to check. Use native dialogs instead of Qt:s own dialogs. * * @param mode Dialog open mode (files or directories) * @return QStringList of files or directories that were selected to check */ QStringList SelectFilesToCheck(QFileDialog::FileMode mode); /** * @brief Check all files specified in parameter files * * @param files List of files and/or directories to check */ void DoCheckFiles(const QStringList &files); /** * @brief Get our default cppcheck settings and read project file. * * @return Default cppcheck settings */ Settings GetCppcheckSettings(); /** * @brief Load program settings * */ void LoadSettings(); /** * @brief Save program settings * */ void SaveSettings() const; /** * @brief Format main window title. * @param text Text added to end of the title. */ void FormatAndSetTitle(const QString &text = QString()); /** * @brief Show help contents */ void OpenOnlineHelp(); /** * @brief Enable or disable project file actions. * Project editing and closing actions should be only enabled when project is * open and we are not checking files. * @param enable If true then actions are enabled. */ void EnableProjectActions(bool enable); /** * @brief Enable or disable project file actions. * Project opening and creating actions should be disabled when checking. * @param enable If true then actions are enabled. */ void EnableProjectOpenActions(bool enable); /** * @brief Add include directories. * @param includeDirs List of include directories to add. * @param result Settings class where include directories are added. */ void AddIncludeDirs(const QStringList &includeDirs, Settings &result); /** * @brief Handle command line parameters given to GUI. * @param params List of string given to command line. */ void HandleCLIParams(const QStringList ¶ms); /** * @brief Load XML file to the GUI. * @param file Filename (inc. path) of XML file to load. */ void LoadResults(const QString file); /** * @brief Load XML file to the GUI. * @param file Filename (inc. path) of XML file to load. * @param checkedDirectory Path to the directory that the results were generated for. */ void LoadResults(const QString file, const QString checkedDirectory); /** * @brief Load project file to the GUI. * @param filePath Filename (inc. path) of project file to load. */ void LoadProjectFile(const QString &filePath); /** * @brief Update project MRU items in File-menu. */ void UpdateMRUMenuItems(); /** * @brief Add project file (path) to the MRU list. * @param project Full path to the project file to add. */ void AddProjectMRU(const QString &project); /** * @brief Remove project file (path) from the MRU list. * @param project Full path of the project file to remove. */ void RemoveProjectMRU(const QString &project); /** * @brief Program settings * */ QSettings *mSettings; /** * @brief Thread to check files * */ ThreadHandler *mThread; /** * @brief List of user defined applications to open errors with * */ ApplicationList *mApplications; /** * @brief Class to handle translation changes * */ TranslationHandler *mTranslation; /** * @brief Class holding all UI components * */ Ui::MainWindow mUI; /** * @brief Current checked directory. */ QString mCurrentDirectory; /** * @brief Log view. */ LogView *mLogView; /** * @brief Scratchpad. */ ScratchPad* mScratchPad; /** * @brief Project (file). */ Project *mProject; /** * @brief Filter field in the Filter toolbar. */ QLineEdit* mLineEditFilter; /** * @brief Timer to delay filtering while typing. */ QTimer* mFilterTimer; /** * @brief GUI actions for selecting the checked platform. */ QActionGroup *mPlatformActions; /** * @brief GUI actions for selecting the coding standard. */ QActionGroup *mCStandardActions, *mCppStandardActions; /** * @brief Are we exiting the cppcheck? * If this is true then the cppcheck is waiting for check threads to exit * so that the application can be closed. */ bool mExiting; /** * @brief Project MRU menu actions. * List of MRU menu actions. Needs also to store the separator. */ QAction *mRecentProjectActs[MaxRecentProjects + 1]; }; /// @} #endif // MAINWINDOW_H cppcheck-1.61/gui/platforms.cpp000066400000000000000000000033041217722632100165230ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include "platforms.h" Platforms::Platforms(QObject *parent) : QObject(parent) { init(); } void Platforms::add(const QString &title, Settings::PlatformType platform) { Platform plat; plat.mTitle = title; plat.mType = platform; mPlatforms << plat; } void Platforms::init() { add(tr("Built-in"), Settings::Unspecified); add(tr("Unix 32-bit"), Settings::Unix32); add(tr("Unix 64-bit"), Settings::Unix64); add(tr("Windows 32-bit ANSI"), Settings::Win32A); add(tr("Windows 32-bit Unicode"), Settings::Win32W); add(tr("Windows 64-bit"), Settings::Win64); } int Platforms::getCount() const { return mPlatforms.count(); } Platform& Platforms::get(Settings::PlatformType platform) { QList::iterator iter = mPlatforms.begin(); while (iter != mPlatforms.end()) { if ((*iter).mType == platform) { return *iter; } ++iter; } return mPlatforms.first(); } cppcheck-1.61/gui/platforms.h000066400000000000000000000030361217722632100161720ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #ifndef PLATFORMS_H #define PLATFORMS_H #include #include #include #include #include "settings.h" /// @addtogroup GUI /// @{ /** * @brief Checked platform GUI-data. */ struct Platform { QString mTitle; /**< Text visible in the GUI. */ Settings::PlatformType mType; /**< Type in the core. */ QAction *mActMainWindow; /**< Pointer to main window action item. */ }; /** * @brief List of checked platforms. */ class Platforms : public QObject { Q_OBJECT public: Platforms(QObject *parent = NULL); void add(const QString &title, Settings::PlatformType platform); int getCount() const; void init(); Platform& get(Settings::PlatformType platform); QList mPlatforms; }; /// @} #endif // PLATFORMS_H cppcheck-1.61/gui/project.cpp000066400000000000000000000067441217722632100161750ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include #include #include #include #include #include #include "project.h" #include "projectfile.h" #include "projectfiledialog.h" Project::Project(QWidget *parent) : QObject(parent), mPFile(NULL), mParentWidget(parent) { } Project::Project(const QString &filename, QWidget *parent) : QObject(parent), mFilename(filename), mPFile(NULL), mParentWidget(parent) { } Project::~Project() { delete mPFile; } QString Project::Filename() const { return mFilename; } void Project::SetFilename(const QString &filename) { mFilename = filename; } bool Project::IsOpen() const { return mPFile != NULL; } bool Project::Open() { mPFile = new ProjectFile(mFilename, this); if (QFile::exists(mFilename)) { if (!mPFile->Read()) { QMessageBox msg(QMessageBox::Critical, tr("Cppcheck"), tr("Could not read the project file."), QMessageBox::Ok, mParentWidget); msg.exec(); mFilename = QString(); mPFile->SetFilename(mFilename); return false; } return true; } return false; } bool Project::Edit() { ProjectFileDialog dlg(mFilename, mParentWidget); QString root = mPFile->GetRootPath(); dlg.SetRootPath(root); QStringList includes = mPFile->GetIncludeDirs(); dlg.SetIncludepaths(includes); QStringList defines = mPFile->GetDefines(); dlg.SetDefines(defines); QStringList paths = mPFile->GetCheckPaths(); dlg.SetPaths(paths); QStringList ignorepaths = mPFile->GetExcludedPaths(); dlg.SetExcludedPaths(ignorepaths); int rv = dlg.exec(); if (rv == QDialog::Accepted) { QString root = dlg.GetRootPath(); mPFile->SetRootPath(root); QStringList includes = dlg.GetIncludePaths(); mPFile->SetIncludes(includes); QStringList defines = dlg.GetDefines(); mPFile->SetDefines(defines); QStringList paths = dlg.GetPaths(); mPFile->SetCheckPaths(paths); QStringList excludedpaths = dlg.GetExcludedPaths(); mPFile->SetExcludedPaths(excludedpaths); bool writeSuccess = mPFile->Write(); if (!writeSuccess) { QMessageBox msg(QMessageBox::Critical, tr("Cppcheck"), tr("Could not write the project file."), QMessageBox::Ok, mParentWidget); msg.exec(); } return writeSuccess; } return false; } void Project::Create() { mPFile = new ProjectFile(mFilename, this); } cppcheck-1.61/gui/project.h000066400000000000000000000043151217722632100156320ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #ifndef PROJECT_H #define PROJECT_H #include #include class QWidget; class ProjectFile; /// @addtogroup GUI /// @{ /** * @brief A class that contains project data and manages projects. * Currently only project file creation and editing is implemented. */ class Project : public QObject { Q_OBJECT public: Project(QWidget *parent = 0); Project(const QString &filename, QWidget *parent = 0); ~Project(); /** * @brief Return the filename of the project. * @return Project's filename. */ QString Filename() const; /** * @brief Set filename for the project file. * @param filename Filename. */ void SetFilename(const QString &filename); /** * @brief Is the project open? * The project is considered to be open if it has an opened project file. * @return true if the project is open, false otherwise. */ bool IsOpen() const; /** * @brief Open existing project file. */ bool Open(); /** * @brief Edit the project file. * @return true if editing was successful. */ bool Edit(); /** * @brief Create new project file. */ void Create(); /** * @brief Return current project file. * @return project file. */ ProjectFile * GetProjectFile() const { return mPFile; } private: QString mFilename; ProjectFile *mPFile; QWidget *mParentWidget; }; /// @} #endif // PROJECT_H cppcheck-1.61/gui/projectfile.cpp000066400000000000000000000316651217722632100170350ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include #include #include #include #include #include "projectfile.h" static const char ProjectElementName[] = "project"; static const char ProjectVersionAttrib[] = "version"; static const char ProjectFileVersion[] = "1"; static const char IncludeDirElementName[] = "includedir"; static const char DirElementName[] = "dir"; static const char DirNameAttrib[] = "name"; static const char DefinesElementName[] = "defines"; static const char DefineName[] = "define"; static const char DefineNameAttrib[] = "name"; static const char PathsElementName[] = "paths"; static const char PathName[] = "dir"; static const char PathNameAttrib[] = "name"; static const char RootPathName[] = "root"; static const char RootPathNameAttrib[] = "name"; static const char IgnoreElementName[] = "ignore"; static const char IgnorePathName[] = "path"; static const char IgnorePathNameAttrib[] = "name"; static const char ExcludeElementName[] = "exclude"; static const char ExcludePathName[] = "path"; static const char ExcludePathNameAttrib[] = "name"; ProjectFile::ProjectFile(QObject *parent) : QObject(parent) { } ProjectFile::ProjectFile(const QString &filename, QObject *parent) : QObject(parent), mFilename(filename) { } bool ProjectFile::Read(const QString &filename) { if (!filename.isEmpty()) mFilename = filename; QFile file(mFilename); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) return false; QXmlStreamReader xmlReader(&file); bool insideProject = false; bool projectTagFound = false; while (!xmlReader.atEnd()) { switch (xmlReader.readNext()) { case QXmlStreamReader::StartElement: if (xmlReader.name() == ProjectElementName) { insideProject = true; projectTagFound = true; } // Read root path from inside project element if (insideProject && xmlReader.name() == RootPathName) ReadRootPath(xmlReader); // Find paths to check from inside project element if (insideProject && xmlReader.name() == PathsElementName) ReadCheckPaths(xmlReader); // Find include directory from inside project element if (insideProject && xmlReader.name() == IncludeDirElementName) ReadIncludeDirs(xmlReader); // Find preprocessor define from inside project element if (insideProject && xmlReader.name() == DefinesElementName) ReadDefines(xmlReader); // Find exclude list from inside project element if (insideProject && xmlReader.name() == ExcludeElementName) ReadExcludes(xmlReader); // Find ignore list from inside project element // These are read for compatibility if (insideProject && xmlReader.name() == IgnoreElementName) ReadExcludes(xmlReader); break; case QXmlStreamReader::EndElement: if (xmlReader.name() == ProjectElementName) insideProject = false; break; // Not handled case QXmlStreamReader::NoToken: case QXmlStreamReader::Invalid: case QXmlStreamReader::StartDocument: case QXmlStreamReader::EndDocument: case QXmlStreamReader::Characters: case QXmlStreamReader::Comment: case QXmlStreamReader::DTD: case QXmlStreamReader::EntityReference: case QXmlStreamReader::ProcessingInstruction: break; } } file.close(); if (projectTagFound) return true; else return false; } QStringList ProjectFile::GetIncludeDirs() const { QStringList dirs; foreach(QString path, mIncludeDirs) { dirs << QDir::fromNativeSeparators(path); } return dirs; } QStringList ProjectFile::GetDefines() const { return mDefines; } QStringList ProjectFile::GetCheckPaths() const { QStringList paths; foreach(QString path, mPaths) { paths << QDir::fromNativeSeparators(path); } return paths; } QStringList ProjectFile::GetExcludedPaths() const { QStringList paths; foreach(QString path, mExcludedPaths) { paths << QDir::fromNativeSeparators(path); } return paths; } void ProjectFile::ReadRootPath(QXmlStreamReader &reader) { QXmlStreamAttributes attribs = reader.attributes(); QString name = attribs.value("", RootPathNameAttrib).toString(); if (!name.isEmpty()) mRootPath = name; } void ProjectFile::ReadIncludeDirs(QXmlStreamReader &reader) { QXmlStreamReader::TokenType type; bool allRead = false; do { type = reader.readNext(); switch (type) { case QXmlStreamReader::StartElement: // Read dir-elements if (reader.name().toString() == DirElementName) { QXmlStreamAttributes attribs = reader.attributes(); QString name = attribs.value("", DirNameAttrib).toString(); if (!name.isEmpty()) mIncludeDirs << name; } break; case QXmlStreamReader::EndElement: if (reader.name().toString() == IncludeDirElementName) allRead = true; break; // Not handled case QXmlStreamReader::NoToken: case QXmlStreamReader::Invalid: case QXmlStreamReader::StartDocument: case QXmlStreamReader::EndDocument: case QXmlStreamReader::Characters: case QXmlStreamReader::Comment: case QXmlStreamReader::DTD: case QXmlStreamReader::EntityReference: case QXmlStreamReader::ProcessingInstruction: break; } } while (!allRead); } void ProjectFile::ReadDefines(QXmlStreamReader &reader) { QXmlStreamReader::TokenType type; bool allRead = false; do { type = reader.readNext(); switch (type) { case QXmlStreamReader::StartElement: // Read define-elements if (reader.name().toString() == DefineName) { QXmlStreamAttributes attribs = reader.attributes(); QString name = attribs.value("", DefineNameAttrib).toString(); if (!name.isEmpty()) mDefines << name; } break; case QXmlStreamReader::EndElement: if (reader.name().toString() == DefinesElementName) allRead = true; break; // Not handled case QXmlStreamReader::NoToken: case QXmlStreamReader::Invalid: case QXmlStreamReader::StartDocument: case QXmlStreamReader::EndDocument: case QXmlStreamReader::Characters: case QXmlStreamReader::Comment: case QXmlStreamReader::DTD: case QXmlStreamReader::EntityReference: case QXmlStreamReader::ProcessingInstruction: break; } } while (!allRead); } void ProjectFile::ReadCheckPaths(QXmlStreamReader &reader) { QXmlStreamReader::TokenType type; bool allRead = false; do { type = reader.readNext(); switch (type) { case QXmlStreamReader::StartElement: // Read dir-elements if (reader.name().toString() == PathName) { QXmlStreamAttributes attribs = reader.attributes(); QString name = attribs.value("", PathNameAttrib).toString(); if (!name.isEmpty()) mPaths << name; } break; case QXmlStreamReader::EndElement: if (reader.name().toString() == PathsElementName) allRead = true; break; // Not handled case QXmlStreamReader::NoToken: case QXmlStreamReader::Invalid: case QXmlStreamReader::StartDocument: case QXmlStreamReader::EndDocument: case QXmlStreamReader::Characters: case QXmlStreamReader::Comment: case QXmlStreamReader::DTD: case QXmlStreamReader::EntityReference: case QXmlStreamReader::ProcessingInstruction: break; } } while (!allRead); } void ProjectFile::ReadExcludes(QXmlStreamReader &reader) { QXmlStreamReader::TokenType type; bool allRead = false; do { type = reader.readNext(); switch (type) { case QXmlStreamReader::StartElement: // Read exclude-elements if (reader.name().toString() == ExcludePathName) { QXmlStreamAttributes attribs = reader.attributes(); QString name = attribs.value("", ExcludePathNameAttrib).toString(); if (!name.isEmpty()) mExcludedPaths << name; } // Read ignore-elements - deprecated but support reading them else if (reader.name().toString() == IgnorePathName) { QXmlStreamAttributes attribs = reader.attributes(); QString name = attribs.value("", IgnorePathNameAttrib).toString(); if (!name.isEmpty()) mExcludedPaths << name; } break; case QXmlStreamReader::EndElement: if (reader.name().toString() == IgnoreElementName) allRead = true; if (reader.name().toString() == ExcludeElementName) allRead = true; break; // Not handled case QXmlStreamReader::NoToken: case QXmlStreamReader::Invalid: case QXmlStreamReader::StartDocument: case QXmlStreamReader::EndDocument: case QXmlStreamReader::Characters: case QXmlStreamReader::Comment: case QXmlStreamReader::DTD: case QXmlStreamReader::EntityReference: case QXmlStreamReader::ProcessingInstruction: break; } } while (!allRead); } void ProjectFile::SetIncludes(const QStringList &includes) { mIncludeDirs = includes; } void ProjectFile::SetDefines(const QStringList &defines) { mDefines = defines; } void ProjectFile::SetCheckPaths(const QStringList &paths) { mPaths = paths; } void ProjectFile::SetExcludedPaths(const QStringList &paths) { mExcludedPaths = paths; } bool ProjectFile::Write(const QString &filename) { if (!filename.isEmpty()) mFilename = filename; QFile file(mFilename); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) return false; QXmlStreamWriter xmlWriter(&file); xmlWriter.setAutoFormatting(true); xmlWriter.writeStartDocument("1.0"); xmlWriter.writeStartElement(ProjectElementName); xmlWriter.writeAttribute(ProjectVersionAttrib, ProjectFileVersion); if (!mRootPath.isEmpty()) { xmlWriter.writeStartElement(RootPathName); xmlWriter.writeAttribute(RootPathNameAttrib, mRootPath); xmlWriter.writeEndElement(); } if (!mIncludeDirs.isEmpty()) { xmlWriter.writeStartElement(IncludeDirElementName); foreach(QString incdir, mIncludeDirs) { xmlWriter.writeStartElement(DirElementName); xmlWriter.writeAttribute(DirNameAttrib, incdir); xmlWriter.writeEndElement(); } xmlWriter.writeEndElement(); } if (!mDefines.isEmpty()) { xmlWriter.writeStartElement(DefinesElementName); foreach(QString define, mDefines) { xmlWriter.writeStartElement(DefineName); xmlWriter.writeAttribute(DefineNameAttrib, define); xmlWriter.writeEndElement(); } xmlWriter.writeEndElement(); } if (!mPaths.isEmpty()) { xmlWriter.writeStartElement(PathsElementName); foreach(QString path, mPaths) { xmlWriter.writeStartElement(PathName); xmlWriter.writeAttribute(PathNameAttrib, path); xmlWriter.writeEndElement(); } xmlWriter.writeEndElement(); } if (!mExcludedPaths.isEmpty()) { xmlWriter.writeStartElement(ExcludeElementName); foreach(QString path, mExcludedPaths) { xmlWriter.writeStartElement(ExcludePathName); xmlWriter.writeAttribute(ExcludePathNameAttrib, path); xmlWriter.writeEndElement(); } xmlWriter.writeEndElement(); } xmlWriter.writeEndDocument(); file.close(); return true; } cppcheck-1.61/gui/projectfile.h000066400000000000000000000114521217722632100164720ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #ifndef PROJECT_FILE_H #define PROJECT_FILE_H #include #include #include #include /// @addtogroup GUI /// @{ /** * @brief A class that reads and writes project files. * The project files contain project-specific settings for checking. For * example a list of include paths. */ class ProjectFile : public QObject { Q_OBJECT public: ProjectFile(QObject *parent = 0); ProjectFile(const QString &filename, QObject *parent = 0); /** * @brief Read the project file. * @param filename Filename (can be also given to constructor). */ bool Read(const QString &filename = QString()); /** * @brief Get project root path. * @return project root path. */ QString GetRootPath() const { return mRootPath; } /** * @brief Get list of include directories. * @return list of directories. */ QStringList GetIncludeDirs() const; /** * @brief Get list of defines. * @return list of defines. */ QStringList GetDefines() const; /** * @brief Get list of paths to check. * @return list of paths. */ QStringList GetCheckPaths() const; /** * @brief Get list of paths to exclude from the check. * @return list of paths. */ QStringList GetExcludedPaths() const; /** * @brief Get filename for the project file. * @return file name. */ QString GetFilename() const { return mFilename; } /** * @brief Set project root path. * @param rootpath new project root path. */ void SetRootPath(const QString &rootpath) { mRootPath = rootpath; } /** * @brief Set list of includes. * @param includes List of defines. */ void SetIncludes(const QStringList &includes); /** * @brief Set list of defines. * @param defines List of defines. */ void SetDefines(const QStringList &defines); /** * @brief Set list of paths to check. * @param paths List of paths. */ void SetCheckPaths(const QStringList &paths); /** * @brief Set list of paths to exclude from the check. * @param paths List of paths. */ void SetExcludedPaths(const QStringList &paths); /** * @brief Write project file (to disk). * @param filename Filename to use. */ bool Write(const QString &filename = QString()); /** * @brief Set filename for the project file. * @param filename Filename to use. */ void SetFilename(const QString &filename) { mFilename = filename; } protected: /** * @brief Read optional root path from XML. * @param reader XML stream reader. */ void ReadRootPath(QXmlStreamReader &reader); /** * @brief Read list of include directories from XML. * @param reader XML stream reader. */ void ReadIncludeDirs(QXmlStreamReader &reader); /** * @brief Read list of defines from XML. * @param reader XML stream reader. */ void ReadDefines(QXmlStreamReader &reader); /** * @brief Read list paths to check. * @param reader XML stream reader. */ void ReadCheckPaths(QXmlStreamReader &reader); /** * @brief Read lists of excluded paths. * @param reader XML stream reader. */ void ReadExcludes(QXmlStreamReader &reader); private: /** * @brief Filename (+path) of the project file. */ QString mFilename; /** * @brief Root path (optional) for the project. * This is the project root path. If it is present then all relative paths in * the project file are relative to this path. Otherwise paths are relative * to project file's path. */ QString mRootPath; /** * @brief List of include directories used to search include files. */ QStringList mIncludeDirs; /** * @brief List of defines. */ QStringList mDefines; /** * @brief List of paths to check. */ QStringList mPaths; /** * @brief Paths excluded from the check. */ QStringList mExcludedPaths; }; /// @} #endif // PROJECT_FILE_H cppcheck-1.61/gui/projectfile.txt000066400000000000000000000035211217722632100170600ustar00rootroot00000000000000Project files ------------- cppcheck GUI handles per-project settings in project files instead of global program settings. This allows customizing cppcheck for each project's needs. The project file is simple XML file easy to edit with your favourite editor program. The format is: where: - optional root element defines the root directory for the project. All relative paths are considered to be relative to this path. If the root element is missing or it contains "." as value then the project file's location is considered to be the root path. - paths element contains a list of checked paths. The paths can be relative or absolute paths. - indludedir element contains a list of additional include paths. These include paths are used when finding local include files ("#include "file.h") for source files. The paths can be relative or absolute paths. It is highly recommended that relative paths are used for paths inside the project root folder for better portability. - defines element contains a list of C/C++ preprocessor defines. - exclude element contains list of paths to exclude from the check. The path can be a directory (must end with path separator) or a file. For real life examples see the cppcheck.cppcheck-file in the Cppcheck sources root-directory or gui.cppcheck file in gui-directory. cppcheck-1.61/gui/projectfile.ui000066400000000000000000000230171217722632100166600ustar00rootroot00000000000000 ProjectFile 0 0 467 329 Project File 0 Project Defines: mEditDefines Root: mEditProjectRoot Paths: Qt::Vertical 20 40 Add... Edit Remove Qt::Vertical 20 40 Includes Include directories: QAbstractItemView::SelectRows Add... Edit Remove Qt::Vertical 20 40 Up Down Exclude Paths: Add... Edit Remove Qt::Vertical 20 40 Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok mButtons tabWidget mEditDefines mEditProjectRoot mListPaths mBtnAddPath mBtnEditPath mBtnRemovePath mListIncludeDirs mBtnAddInclude mBtnEditInclude mBtnRemoveInclude mBtnIncludeUp mBtnIncludeDown mListExcludedPaths mBtnAddIgnorePath mBtnEditIgnorePath mBtnRemoveIgnorePath mButtons accepted() ProjectFile accept() 266 319 157 158 mButtons rejected() ProjectFile reject() 334 319 286 158 cppcheck-1.61/gui/projectfiledialog.cpp000066400000000000000000000224521217722632100202070ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include #include #include #include #include #include #include #include "common.h" #include "projectfiledialog.h" ProjectFileDialog::ProjectFileDialog(const QString &path, QWidget *parent) : QDialog(parent) , mFilePath(path) { mUI.setupUi(this); QFileInfo inf(path); QString filename = inf.fileName(); QString title = tr("Project file: %1").arg(filename); setWindowTitle(title); LoadSettings(); connect(mUI.mButtons, SIGNAL(accepted()), this, SLOT(accept())); connect(mUI.mBtnAddInclude, SIGNAL(clicked()), this, SLOT(AddIncludeDir())); connect(mUI.mBtnAddPath, SIGNAL(clicked()), this, SLOT(AddPath())); connect(mUI.mBtnEditInclude, SIGNAL(clicked()), this, SLOT(EditIncludeDir())); connect(mUI.mBtnRemoveInclude, SIGNAL(clicked()), this, SLOT(RemoveIncludeDir())); connect(mUI.mBtnEditPath, SIGNAL(clicked()), this, SLOT(EditPath())); connect(mUI.mBtnRemovePath, SIGNAL(clicked()), this, SLOT(RemovePath())); connect(mUI.mBtnAddIgnorePath, SIGNAL(clicked()), this, SLOT(AddExcludePath())); connect(mUI.mBtnEditIgnorePath, SIGNAL(clicked()), this, SLOT(EditExcludePath())); connect(mUI.mBtnRemoveIgnorePath, SIGNAL(clicked()), this, SLOT(RemoveExcludePath())); connect(mUI.mBtnIncludeUp, SIGNAL(clicked()), this, SLOT(MoveIncludePathUp())); connect(mUI.mBtnIncludeDown, SIGNAL(clicked()), this, SLOT(MoveIncludePathDown())); } ProjectFileDialog::~ProjectFileDialog() { SaveSettings(); } void ProjectFileDialog::LoadSettings() { QSettings settings; resize(settings.value(SETTINGS_PROJECT_DIALOG_WIDTH, 470).toInt(), settings.value(SETTINGS_PROJECT_DIALOG_HEIGHT, 330).toInt()); } void ProjectFileDialog::SaveSettings() const { QSettings settings; settings.setValue(SETTINGS_PROJECT_DIALOG_WIDTH, size().width()); settings.setValue(SETTINGS_PROJECT_DIALOG_HEIGHT, size().height()); } void ProjectFileDialog::AddIncludeDir(const QString &dir) { if (dir.isNull() || dir.isEmpty()) return; const QString newdir = QDir::toNativeSeparators(dir); QListWidgetItem *item = new QListWidgetItem(newdir); item->setFlags(item->flags() | Qt::ItemIsEditable); mUI.mListIncludeDirs->addItem(item); } void ProjectFileDialog::AddPath(const QString &path) { if (path.isNull() || path.isEmpty()) return; const QString newpath = QDir::toNativeSeparators(path); QListWidgetItem *item = new QListWidgetItem(newpath); item->setFlags(item->flags() | Qt::ItemIsEditable); mUI.mListPaths->addItem(item); } void ProjectFileDialog::AddExcludePath(const QString &path) { if (path.isNull() || path.isEmpty()) return; const QString newpath = QDir::toNativeSeparators(path); QListWidgetItem *item = new QListWidgetItem(newpath); item->setFlags(item->flags() | Qt::ItemIsEditable); mUI.mListExcludedPaths->addItem(item); } QString ProjectFileDialog::GetRootPath() const { QString root = mUI.mEditProjectRoot->text(); root = root.trimmed(); root = QDir::fromNativeSeparators(root); return root; } QStringList ProjectFileDialog::GetIncludePaths() const { const int count = mUI.mListIncludeDirs->count(); QStringList includePaths; for (int i = 0; i < count; i++) { QListWidgetItem *item = mUI.mListIncludeDirs->item(i); includePaths << QDir::fromNativeSeparators(item->text()); } return includePaths; } QStringList ProjectFileDialog::GetDefines() const { QString define = mUI.mEditDefines->text(); QStringList defines; if (!define.isEmpty()) { define = define.trimmed(); if (define.indexOf(';') != -1) defines = define.split(";"); else defines.append(define); } return defines; } QStringList ProjectFileDialog::GetPaths() const { const int count = mUI.mListPaths->count(); QStringList paths; for (int i = 0; i < count; i++) { QListWidgetItem *item = mUI.mListPaths->item(i); paths << QDir::fromNativeSeparators(item->text()); } return paths; } QStringList ProjectFileDialog::GetExcludedPaths() const { const int count = mUI.mListExcludedPaths->count(); QStringList paths; for (int i = 0; i < count; i++) { QListWidgetItem *item = mUI.mListExcludedPaths->item(i); paths << QDir::fromNativeSeparators(item->text()); } return paths; } void ProjectFileDialog::SetRootPath(const QString &root) { QString newroot = QDir::toNativeSeparators(root); mUI.mEditProjectRoot->setText(newroot); } void ProjectFileDialog::SetIncludepaths(const QStringList &includes) { foreach(QString dir, includes) { AddIncludeDir(dir); } } void ProjectFileDialog::SetDefines(const QStringList &defines) { QString definestr; QString define; foreach(define, defines) { definestr += define; definestr += ";"; } // Remove ; from the end of the string if (definestr.endsWith(';')) definestr = definestr.left(definestr.length() - 1); mUI.mEditDefines->setText(definestr); } void ProjectFileDialog::SetPaths(const QStringList &paths) { foreach(QString path, paths) { AddPath(path); } } void ProjectFileDialog::SetExcludedPaths(const QStringList &paths) { foreach(QString path, paths) { AddExcludePath(path); } } void ProjectFileDialog::AddIncludeDir() { const QFileInfo inf(mFilePath); const QString rootpath = inf.absolutePath(); QString selectedDir = QFileDialog::getExistingDirectory(this, tr("Select include directory"), rootpath); if (!selectedDir.isEmpty()) { // Check if the path is relative to project file's path and if so // make it a relative path instead of absolute path. const QDir dir(selectedDir); QString absPath = dir.absolutePath(); if (absPath.startsWith(rootpath)) { // Remove also the slash from begin of new relative path selectedDir = absPath.remove(0, rootpath.length() + 1); } if (!selectedDir.endsWith("/")) selectedDir += '/'; AddIncludeDir(selectedDir); } } void ProjectFileDialog::AddPath() { QFileInfo inf(mFilePath); const QString rootpath = inf.absolutePath(); QString selectedDir = QFileDialog::getExistingDirectory(this, tr("Select a directory to check"), rootpath); if (!selectedDir.isEmpty()) { AddPath(selectedDir); } } void ProjectFileDialog::RemoveIncludeDir() { const int row = mUI.mListIncludeDirs->currentRow(); QListWidgetItem *item = mUI.mListIncludeDirs->takeItem(row); delete item; } void ProjectFileDialog::EditIncludeDir() { QListWidgetItem *item = mUI.mListIncludeDirs->currentItem(); mUI.mListIncludeDirs->editItem(item); } void ProjectFileDialog::EditPath() { QListWidgetItem *item = mUI.mListPaths->currentItem(); mUI.mListPaths->editItem(item); } void ProjectFileDialog::RemovePath() { const int row = mUI.mListPaths->currentRow(); QListWidgetItem *item = mUI.mListPaths->takeItem(row); delete item; } void ProjectFileDialog::AddExcludePath() { QFileInfo inf(mFilePath); const QString rootpath = inf.absolutePath(); QString selectedDir = QFileDialog::getExistingDirectory(this, tr("Select directory to ignore"), rootpath); if (!selectedDir.isEmpty()) { if (!selectedDir.endsWith('/')) selectedDir += '/'; AddExcludePath(selectedDir); } } void ProjectFileDialog::EditExcludePath() { QListWidgetItem *item = mUI.mListExcludedPaths->currentItem(); mUI.mListExcludedPaths->editItem(item); } void ProjectFileDialog::RemoveExcludePath() { const int row = mUI.mListExcludedPaths->currentRow(); QListWidgetItem *item = mUI.mListExcludedPaths->takeItem(row); delete item; } void ProjectFileDialog::MoveIncludePathUp() { int row = mUI.mListIncludeDirs->currentRow(); QListWidgetItem *item = mUI.mListIncludeDirs->takeItem(row); row = row > 0 ? row - 1 : 0; mUI.mListIncludeDirs->insertItem(row, item); mUI.mListIncludeDirs->setCurrentItem(item); } void ProjectFileDialog::MoveIncludePathDown() { int row = mUI.mListIncludeDirs->currentRow(); QListWidgetItem *item = mUI.mListIncludeDirs->takeItem(row); const int count = mUI.mListIncludeDirs->count(); row = row < count ? row + 1 : count; mUI.mListIncludeDirs->insertItem(row, item); mUI.mListIncludeDirs->setCurrentItem(item); } cppcheck-1.61/gui/projectfiledialog.h000066400000000000000000000107531217722632100176550ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #ifndef PROJECTFILE_DIALOG_H #define PROJECTFILE_DIALOG_H #include #include #include #include "ui_projectfile.h" class QWidget; /// @addtogroup GUI /// @{ /** * @brief A dialog for editing project file data. */ class ProjectFileDialog : public QDialog { Q_OBJECT public: ProjectFileDialog(const QString &path, QWidget *parent = 0); virtual ~ProjectFileDialog(); /** * @brief Return project root path from the dialog control. * @return Project root path. */ QString GetRootPath() const; /** * @brief Return include paths from the dialog control. * @return List of include paths. */ QStringList GetIncludePaths() const; /** * @brief Return define names from the dialog control. * @return List of define names. */ QStringList GetDefines() const; /** * @brief Return check paths from the dialog control. * @return List of check paths. */ QStringList GetPaths() const; /** * @brief Return excluded paths from the dialog control. * @return List of excluded paths. */ QStringList GetExcludedPaths() const; /** * @brief Set project root path to dialog control. * @param root Project root path to set to dialog control. */ void SetRootPath(const QString &root); /** * @brief Set include paths to dialog control. * @param includes List of include paths to set to dialog control. */ void SetIncludepaths(const QStringList &includes); /** * @brief Set define names to dialog control. * @param defines List of define names to set to dialog control. */ void SetDefines(const QStringList &defines); /** * @brief Set check paths to dialog control. * @param paths List of path names to set to dialog control. */ void SetPaths(const QStringList &paths); /** * @brief Set excluded paths to dialog control. * @param paths List of path names to set to dialog control. */ void SetExcludedPaths(const QStringList &paths); protected slots: /** * @brief Browse for include directory. * Allow user to add new include directory to the list. */ void AddIncludeDir(); /** * @brief Add new path to check. */ void AddPath(); /** * @brief Remove include directory from the list. */ void RemoveIncludeDir(); /** * @brief Edit include directory in the list. */ void EditIncludeDir(); /** * @brief Edit path in the list. */ void EditPath(); /** * @brief Remove path from the list. */ void RemovePath(); /** * @brief Add new path to exclude. */ void AddExcludePath(); /** * @brief Edit excluded path in the list. */ void EditExcludePath(); /** * @brief Remove excluded path from the list. */ void RemoveExcludePath(); /** * @brief Move include path up in the list. */ void MoveIncludePathUp(); /** * @brief Move include path down in the list. */ void MoveIncludePathDown(); protected: /** * @brief Save dialog settings. */ void LoadSettings(); /** * @brief Load dialog settings. */ void SaveSettings() const; /** * @brief Add new indlude directory. * @param dir Directory to add. */ void AddIncludeDir(const QString &dir); /** * @brief Add new path to check. * @param path Path to add. */ void AddPath(const QString &path); /** * @brief Add new path to ignore list. * @param path Path to add. */ void AddExcludePath(const QString &path); private: Ui::ProjectFile mUI; /** * @brief Projectfile path. */ QString mFilePath; }; /// @} #endif // PROJECTFILE_DIALOG_H cppcheck-1.61/gui/report.cpp000066400000000000000000000027361217722632100160370ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include #include #include "report.h" Report::Report(const QString &filename) : mFilename(filename) { } Report::~Report() { Close(); } bool Report::Create() { bool succeed = false; if (!mFile.isOpen()) { mFile.setFileName(mFilename); succeed = mFile.open(QIODevice::WriteOnly | QIODevice::Text); } return succeed; } bool Report::Open() { bool succeed = false; if (!mFile.isOpen()) { mFile.setFileName(mFilename); succeed = mFile.open(QIODevice::ReadOnly | QIODevice::Text); } return succeed; } void Report::Close() { if (mFile.isOpen()) mFile.close(); } QFile* Report::GetFile() { return &mFile; } cppcheck-1.61/gui/report.h000066400000000000000000000041371217722632100155010ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #ifndef REPORT_H #define REPORT_H #include #include #include #include "erroritem.h" /// @addtogroup GUI /// @{ /** * @brief A base class for reports. */ class Report : public QObject { public: enum Type { TXT, XML, XMLV2, CSV, }; Report(const QString &filename); virtual ~Report(); /** * @brief Create the report (file). * @return true if succeeded, false if file could not be created. */ virtual bool Create(); /** * @brief Open the existing report (file). * @return true if succeeded, false if file could not be created. */ virtual bool Open(); /** * @brief Close the report (file). */ virtual void Close(); /** * @brief Write report header. */ virtual void WriteHeader() = 0; /** * @brief Write report footer. */ virtual void WriteFooter() = 0; /** * @brief Write error to report. * @param error Error data. */ virtual void WriteError(const ErrorItem &error) = 0; protected: /** * @brief Get the file object where the report is written to. */ QFile* GetFile(); private: /** * @brief Filename of the report. */ QString mFilename; /** * @brief Fileobject for the report file. */ QFile mFile; }; /// @} #endif // REPORT_H cppcheck-1.61/gui/resultstree.cpp000066400000000000000000000776341217722632100171160ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "common.h" #include "erroritem.h" #include "applicationlist.h" #include "resultstree.h" #include "report.h" #include "application.h" #include "showtypes.h" ResultsTree::ResultsTree(QWidget * parent) : QTreeView(parent), mContextItem(0), mShowErrorId(false), mVisibleErrors(false), mSelectionModel(0) { setModel(&mModel); Translate(); // Adds columns to grid setExpandsOnDoubleClick(false); setSortingEnabled(true); connect(this, SIGNAL(doubleClicked(const QModelIndex &)), this, SLOT(QuickStartApplication(const QModelIndex &))); } ResultsTree::~ResultsTree() { } void ResultsTree::Initialize(QSettings *settings, ApplicationList *list) { mSettings = settings; mApplications = list; LoadSettings(); } QStandardItem *ResultsTree::CreateNormalItem(const QString &name) { QStandardItem *item = new QStandardItem(name); item->setData(name, Qt::ToolTipRole); item->setEditable(false); return item; } QStandardItem *ResultsTree::CreateLineNumberItem(const QString &linenumber) { QStandardItem *item = new QStandardItem(); item->setData(QVariant(linenumber.toULongLong()), Qt::DisplayRole); item->setToolTip(linenumber); item->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter); item->setEditable(false); return item; } bool ResultsTree::AddErrorItem(const ErrorItem &item) { if (item.files.isEmpty()) { return false; } QString realfile = StripPath(item.files[0], false); if (realfile.isEmpty()) { realfile = tr("Undefined file"); } bool hide = !mShowSeverities.isShown(item.severity); //bool hide = !mShowTypes[SeverityToShowType(item.severity)]; //If specified, filter on summary, message, filename, and id if (!hide && !mFilter.isEmpty()) { if (!item.summary.contains(mFilter, Qt::CaseInsensitive) && !item.message.contains(mFilter, Qt::CaseInsensitive) && !item.file.contains(mFilter, Qt::CaseInsensitive) && !item.errorId.contains(mFilter, Qt::CaseInsensitive)) { hide = true; } } //if there is at least one error that is not hidden, we have a visible error if (!hide) { mVisibleErrors = true; } ErrorLine line; line.file = realfile; line.errorId = item.errorId; line.inconclusive = item.inconclusive; line.line = item.lines[0]; line.summary = item.summary; line.message = item.message; line.severity = item.severity; //Create the base item for the error and ensure it has a proper //file item as a parent QStandardItem *stditem = AddBacktraceFiles(EnsureFileItem(line.file, item.file0, hide), line, hide, SeverityToIcon(line.severity)); if (!stditem) return false; //Add user data to that item QMap data; data["hide"] = false; data["severity"] = ShowTypes::SeverityToShowType(item.severity); data["summary"] = item.summary; data["message"] = item.message; data["file"] = item.files[0]; data["line"] = item.lines[0]; data["id"] = item.errorId; data["inconclusive"] = item.inconclusive; data["file0"] = item.file0; stditem->setData(QVariant(data)); //Add backtrace files as children for (int i = 1; i < item.files.size(); i++) { line.file = StripPath(item.files[i], false); line.line = item.lines[i]; QStandardItem *child_item; child_item = AddBacktraceFiles(stditem, line, hide, ":images/go-down.png"); //Add user data to that item QMap child_data; child_data["severity"] = ShowTypes::SeverityToShowType(line.severity); child_data["summary"] = line.summary; child_data["message"] = line.message; child_data["file"] = item.files[i]; child_data["line"] = line.line; child_data["id"] = line.errorId; child_data["inconclusive"] = line.inconclusive; child_item->setData(QVariant(child_data)); } //TODO just hide/show current error and it's file //since this does a lot of unnecessary work if (!hide) { ShowFileItem(realfile); } return true; } QStandardItem *ResultsTree::AddBacktraceFiles(QStandardItem *parent, const ErrorLine &item, const bool hide, const QString &icon) { if (!parent) { return 0; } QList list; // Ensure shown path is with native separators const QString file = QDir::toNativeSeparators(item.file); list << CreateNormalItem(file); const QString severity = SeverityToTranslatedString(item.severity); list << CreateNormalItem(severity); list << CreateLineNumberItem(QString("%1").arg(item.line)); list << CreateNormalItem(item.errorId); //TODO message has parameter names so we'll need changes to the core //cppcheck so we can get proper translations QString summary; if (item.inconclusive) { summary = tr("[Inconclusive]"); summary += " "; } summary += item.summary.toLatin1(); list << CreateNormalItem(summary); // Check for duplicate rows and don't add them if found for (int i = 0; i < parent->rowCount(); i++) { // The first column is the file name and is always the same // the third column is the line number so check it first if (parent->child(i, 2)->text() == list[2]->text()) { // the second column is the severity so check it next if (parent->child(i, 1)->text() == list[1]->text()) { // the fourth column is the summary so check it last if (parent->child(i, 4)->text() == list[4]->text()) { // this row matches so don't add it return 0; } } } } parent->appendRow(list); setRowHidden(parent->rowCount() - 1, parent->index(), hide); if (!icon.isEmpty()) { list[0]->setIcon(QIcon(icon)); } //TODO Does this leak memory? Should items from list be deleted? return list[0]; } QString ResultsTree::SeverityToTranslatedString(Severity::SeverityType severity) { switch (severity) { case Severity::style: return tr("style"); case Severity::error: return tr("error"); case Severity::warning: return tr("warning"); case Severity::performance: return tr("performance"); case Severity::portability: return tr("portability"); case Severity::information: return tr("information"); case Severity::debug: return tr("debug"); case Severity::none: default: return ""; } } QStandardItem *ResultsTree::FindFileItem(const QString &name) const { // The first column contains the file name. In Windows we can get filenames // "header.h" and "Header.h" and must compare them as identical. for (int i = 0; i < mModel.rowCount(); i++) { #ifdef _WIN32 if (QString::compare(mModel.item(i, 0)->text(), name, Qt::CaseInsensitive) == 0) #else if (mModel.item(i, 0)->text() == name) #endif return mModel.item(i, 0); } return 0; } void ResultsTree::Clear() { mModel.removeRows(0, mModel.rowCount()); } void ResultsTree::Clear(const QString &filename) { const QString stripped = StripPath(filename, false); for (int i = 0; i < mModel.rowCount(); ++i) { const QStandardItem *item = mModel.item(i, 0); if (!item) continue; QVariantMap data = item->data().toMap(); if (stripped == data["file"].toString() || filename == data["file0"].toString()) { mModel.removeRow(i); break; } } } void ResultsTree::LoadSettings() { for (int i = 0; i < mModel.columnCount(); i++) { QString temp = QString(SETTINGS_RESULT_COLUMN_WIDTH).arg(i); setColumnWidth(i, qMax(20, mSettings->value(temp, 800 / mModel.columnCount()).toInt())); } mSaveFullPath = mSettings->value(SETTINGS_SAVE_FULL_PATH, false).toBool(); mSaveAllErrors = mSettings->value(SETTINGS_SAVE_ALL_ERRORS, false).toBool(); mShowFullPath = mSettings->value(SETTINGS_SHOW_FULL_PATH, false).toBool(); ShowIdColumn(mSettings->value(SETTINGS_SHOW_ERROR_ID, false).toBool()); } void ResultsTree::SaveSettings() const { for (int i = 0; i < mModel.columnCount(); i++) { QString temp = QString(SETTINGS_RESULT_COLUMN_WIDTH).arg(i); mSettings->setValue(temp, columnWidth(i)); } } void ResultsTree::ShowResults(ShowTypes::ShowType type, bool show) { if (type != ShowTypes::ShowNone && mShowSeverities.isShown(type) != show) { mShowSeverities.show(type, show); RefreshTree(); } } void ResultsTree::FilterResults(const QString& filter) { mFilter = filter; RefreshTree(); } void ResultsTree::ShowHiddenResults() { //Clear the "hide" flag for each item int filecount = mModel.rowCount(); for (int i = 0; i < filecount; i++) { QStandardItem *file = mModel.item(i, 0); if (!file) continue; QVariantMap data = file->data().toMap(); data["hide"] = false; file->setData(QVariant(data)); int errorcount = file->rowCount(); for (int j = 0; j < errorcount; j++) { QStandardItem *child = file->child(j, 0); if (child) { data = child->data().toMap(); data["hide"] = false; child->setData(QVariant(data)); } } } RefreshTree(); emit ResultsHidden(false); } void ResultsTree::RefreshTree() { mVisibleErrors = false; //Get the amount of files in the tree int filecount = mModel.rowCount(); for (int i = 0; i < filecount; i++) { //Get file i QStandardItem *file = mModel.item(i, 0); if (!file) { continue; } //Get the amount of errors this file contains int errorcount = file->rowCount(); //By default it shouldn't be visible bool show = false; for (int j = 0; j < errorcount; j++) { //Get the error itself QStandardItem *child = file->child(j, 0); if (!child) { continue; } //Get error's user data QVariant userdata = child->data(); //Convert it to QVariantMap QVariantMap data = userdata.toMap(); //Check if this error should be hidden bool hide = (data["hide"].toBool() || !mShowSeverities.isShown(ShowTypes::VariantToShowType(data["severity"]))); //If specified, filter on summary, message, filename, and id if (!hide && !mFilter.isEmpty()) { if (!data["summary"].toString().contains(mFilter, Qt::CaseInsensitive) && !data["message"].toString().contains(mFilter, Qt::CaseInsensitive) && !data["file"].toString().contains(mFilter, Qt::CaseInsensitive) && !data["id"].toString().contains(mFilter, Qt::CaseInsensitive)) { hide = true; } } if (!hide) { mVisibleErrors = true; } //Hide/show accordingly setRowHidden(j, file->index(), hide); //If it was shown then the file itself has to be shown as well if (!hide) { show = true; } } //Hide the file if its "hide" attribute is set if (file->data().toMap()["hide"].toBool()) { show = false; } //Show the file if any of it's errors are visible setRowHidden(i, QModelIndex(), !show); } } QStandardItem *ResultsTree::EnsureFileItem(const QString &fullpath, const QString &file0, bool hide) { QString name = StripPath(fullpath, false); // Since item has path with native separators we must use path with // native separators to find it. QStandardItem *item = FindFileItem(QDir::toNativeSeparators(name)); if (item) { return item; } // Ensure shown path is with native separators name = QDir::toNativeSeparators(name); item = CreateNormalItem(name); item->setIcon(QIcon(":images/text-x-generic.png")); //Add user data to that item QMap data; data["file"] = fullpath; data["file0"] = file0; item->setData(QVariant(data)); mModel.appendRow(item); setRowHidden(mModel.rowCount() - 1, QModelIndex(), hide); return item; } void ResultsTree::ShowFileItem(const QString &name) { QStandardItem *item = FindFileItem(name); if (item) { setRowHidden(0, mModel.indexFromItem(item), false); } } void ResultsTree::contextMenuEvent(QContextMenuEvent * e) { QModelIndex index = indexAt(e->pos()); if (index.isValid()) { bool multipleSelection = false; mSelectionModel = selectionModel(); if (mSelectionModel->selectedRows().count() > 1) multipleSelection = true; mContextItem = mModel.itemFromIndex(index); //Create a new context menu QMenu menu(this); //Store all applications in a list QList actions; //Create a signal mapper so we don't have to store data to class //member variables QSignalMapper *signalMapper = new QSignalMapper(this); if (mContextItem && mApplications->GetApplicationCount() > 0 && mContextItem->parent()) { //Go through all applications and add them to the context menu for (int i = 0; i < mApplications->GetApplicationCount(); i++) { //Create an action for the application const Application& app = mApplications->GetApplication(i); QAction *start = new QAction(app.getName(), &menu); if (multipleSelection) start->setDisabled(true); //Add it to our list so we can disconnect later on actions << start; //Add it to context menu menu.addAction(start); //Connect the signal to signal mapper connect(start, SIGNAL(triggered()), signalMapper, SLOT(map())); //Add a new mapping signalMapper->setMapping(start, i); } connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(Context(int))); } // Add menuitems to copy full path/filename to clipboard if (mContextItem) { if (mApplications->GetApplicationCount() > 0) { menu.addSeparator(); } //Create an action for the application QAction *copyfilename = new QAction(tr("Copy filename"), &menu); QAction *copypath = new QAction(tr("Copy full path"), &menu); QAction *copymessage = new QAction(tr("Copy message"), &menu); QAction *copymessageid = new QAction(tr("Copy message id"), &menu); QAction *hide = new QAction(tr("Hide"), &menu); QAction *hideallid = new QAction(tr("Hide all with id"), &menu); if (multipleSelection) { copyfilename->setDisabled(true); copypath->setDisabled(true); copymessage->setDisabled(true); copymessageid->setDisabled(true); hideallid->setDisabled(true); } menu.addAction(copyfilename); menu.addAction(copypath); menu.addAction(copymessage); menu.addAction(copymessageid); menu.addAction(hide); menu.addAction(hideallid); connect(copyfilename, SIGNAL(triggered()), this, SLOT(CopyFilename())); connect(copypath, SIGNAL(triggered()), this, SLOT(CopyFullPath())); connect(copymessage, SIGNAL(triggered()), this, SLOT(CopyMessage())); connect(copymessageid, SIGNAL(triggered()), this, SLOT(CopyMessageId())); connect(hide, SIGNAL(triggered()), this, SLOT(HideResult())); connect(hideallid, SIGNAL(triggered()), this, SLOT(HideAllIdResult())); } //Start the menu menu.exec(e->globalPos()); if (mContextItem && mApplications->GetApplicationCount() > 0 && mContextItem->parent()) { //Disconnect all signals for (int i = 0; i < actions.size(); i++) { disconnect(actions[i], SIGNAL(triggered()), signalMapper, SLOT(map())); } disconnect(signalMapper, SIGNAL(mapped(int)), this, SLOT(Context(int))); //And remove the signal mapper delete signalMapper; } } } void ResultsTree::StartApplication(QStandardItem *target, int application) { //If there are no applications specified, tell the user about it if (mApplications->GetApplicationCount() == 0) { QMessageBox msg(QMessageBox::Critical, tr("Cppcheck"), tr("No editor application configured.\n\n" "Configure the editor application for Cppcheck in preferences/Applications."), QMessageBox::Ok, this); msg.exec(); return; } if (application == -1) application = mApplications->GetDefaultApplication(); if (application == -1) { QMessageBox msg(QMessageBox::Critical, tr("Cppcheck"), tr("No default editor application selected.\n\n" "Please select the default editor application in preferences/Applications."), QMessageBox::Ok, this); msg.exec(); return; } if (target && application >= 0 && application < mApplications->GetApplicationCount() && target->parent()) { // Make sure we are working with the first column if (target->column() != 0) target = target->parent()->child(target->row(), 0); QVariantMap data = target->data().toMap(); //Replace (file) with filename QString file = data["file"].toString(); file = QDir::toNativeSeparators(file); #ifdef Q_WS_WIN file.replace(QString("\\"), QString("\\\\")); #endif qDebug() << "Opening file: " << file; QFileInfo info(file); if (!info.exists()) { if (info.isAbsolute()) { QMessageBox msgbox(this); msgbox.setWindowTitle("Cppcheck"); msgbox.setText(tr("Could not find the file!")); msgbox.setIcon(QMessageBox::Critical); msgbox.exec(); } else { QDir checkdir(mCheckPath); if (checkdir.isAbsolute() && checkdir.exists()) { file = mCheckPath + "/" + file; } else { QString dir = AskFileDir(file); dir += '/'; file = dir + file; } } } if (file.indexOf(" ") > -1) { file.insert(0, "\""); file.append("\""); } const Application& app = mApplications->GetApplication(application); QString params = app.getParameters(); params.replace("(file)", file, Qt::CaseInsensitive); QVariant line = data["line"]; params.replace("(line)", QString("%1").arg(line.toInt()), Qt::CaseInsensitive); params.replace("(message)", data["message"].toString(), Qt::CaseInsensitive); params.replace("(severity)", data["severity"].toString(), Qt::CaseInsensitive); QString program = app.getPath(); // In Windows we must surround paths including spaces with quotation marks. #ifdef Q_WS_WIN if (program.indexOf(" ") > -1) { if (!program.startsWith('"') && !program.endsWith('"')) { program.insert(0, "\""); program.append("\""); } } #endif // Q_WS_WIN const QString cmdLine = QString("%1 %2").arg(program).arg(params); bool success = QProcess::startDetached(cmdLine); if (!success) { QString text = tr("Could not start %1\n\nPlease check the application path and parameters are correct.").arg(program); QMessageBox msgbox(this); msgbox.setWindowTitle("Cppcheck"); msgbox.setText(text); msgbox.setIcon(QMessageBox::Critical); msgbox.exec(); } } } QString ResultsTree::AskFileDir(const QString &file) { QString text = tr("Could not find file:\n%1\nPlease select the directory where file is located.").arg(file); QMessageBox msgbox(this); msgbox.setWindowTitle("Cppcheck"); msgbox.setText(text); msgbox.setIcon(QMessageBox::Warning); msgbox.exec(); QString dir = QFileDialog::getExistingDirectory(this, tr("Select Directory"), GetPath(SETTINGS_LAST_SOURCE_PATH), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks); mCheckPath = dir; SetPath(SETTINGS_LAST_SOURCE_PATH, dir); return dir; } void ResultsTree::CopyFilename() { CopyPath(mContextItem, false); } void ResultsTree::CopyFullPath() { CopyPath(mContextItem, true); } void ResultsTree::CopyMessage() { if (mContextItem) { // Make sure we are working with the first column if (mContextItem->column() != 0) mContextItem = mContextItem->parent()->child(mContextItem->row(), 0); QVariantMap data = mContextItem->data().toMap(); QString message; if (data["inconclusive"].toBool()) { message = tr("[Inconclusive]"); message += " "; } message += data["message"].toString(); QClipboard *clipboard = QApplication::clipboard(); clipboard->setText(message); } } void ResultsTree::CopyMessageId() { if (mContextItem) { // Make sure we are working with the first column if (mContextItem->column() != 0) mContextItem = mContextItem->parent()->child(mContextItem->row(), 0); QVariantMap data = mContextItem->data().toMap(); QString messageId = data["id"].toString(); QClipboard *clipboard = QApplication::clipboard(); clipboard->setText(messageId); } } void ResultsTree::HideResult() { if (!mSelectionModel) return; QModelIndexList selectedRows = mSelectionModel->selectedRows(); QModelIndex index; foreach(index, selectedRows) { QStandardItem *item = mModel.itemFromIndex(index); //Set the "hide" flag for this item QVariantMap data = item->data().toMap(); data["hide"] = true; item->setData(QVariant(data)); RefreshTree(); emit ResultsHidden(true); } } void ResultsTree::HideAllIdResult() { if (mContextItem) { // Make sure we are working with the first column if (mContextItem->column() != 0) mContextItem = mContextItem->parent()->child(mContextItem->row(), 0); QVariantMap data = mContextItem->data().toMap(); QString messageId = data["id"].toString(); // hide all errors with that message Id int filecount = mModel.rowCount(); for (int i = 0; i < filecount; i++) { //Get file i QStandardItem *file = mModel.item(i, 0); if (!file) { continue; } //Get the amount of errors this file contains int errorcount = file->rowCount(); for (int j = 0; j < errorcount; j++) { //Get the error itself QStandardItem *child = file->child(j, 0); if (!child) { continue; } QVariantMap userdata = child->data().toMap(); if (userdata["id"].toString() == messageId) { userdata["hide"] = true; child->setData(QVariant(userdata)); } } } RefreshTree(); emit ResultsHidden(true); } } void ResultsTree::Context(int application) { StartApplication(mContextItem, application); } void ResultsTree::QuickStartApplication(const QModelIndex &index) { StartApplication(mModel.itemFromIndex(index)); } void ResultsTree::CopyPath(QStandardItem *target, bool fullPath) { if (target) { // Make sure we are working with the first column if (target->column() != 0) target = target->parent()->child(target->row(), 0); QVariantMap data = target->data().toMap(); QString pathStr; //Replace (file) with filename QString file = data["file"].toString(); pathStr = QDir::toNativeSeparators(file); if (!fullPath) { QFileInfo fi(pathStr); pathStr = fi.fileName(); } QClipboard *clipboard = QApplication::clipboard(); clipboard->setText(pathStr); } } QString ResultsTree::SeverityToIcon(Severity::SeverityType severity) const { switch (severity) { case Severity::error: return ":images/dialog-error.png"; case Severity::style: return ":images/applications-development.png"; case Severity::warning: return ":images/dialog-warning.png"; case Severity::portability: return ":images/applications-system.png"; case Severity::performance: return ":images/utilities-system-monitor.png"; case Severity::information: return ":images/dialog-information.png"; default: return ""; } } void ResultsTree::SaveResults(Report *report) const { report->WriteHeader(); for (int i = 0; i < mModel.rowCount(); i++) { QStandardItem *item = mModel.item(i, 0); if (!isRowHidden(i, item->index())) SaveErrors(report, item); } report->WriteFooter(); } void ResultsTree::SaveErrors(Report *report, QStandardItem *item) const { if (!item) { return; } for (int i = 0; i < item->rowCount(); i++) { QStandardItem *error = item->child(i, 0); if (!error) { continue; } if (isRowHidden(i, item->index()) && !mSaveAllErrors) { continue; } //Get error's user data QVariant userdata = error->data(); //Convert it to QVariantMap QVariantMap data = userdata.toMap(); ErrorItem item; item.severity = ShowTypes::ShowTypeToSeverity(ShowTypes::VariantToShowType(data["severity"])); item.summary = data["summary"].toString(); item.message = data["message"].toString(); item.errorId = data["id"].toString(); item.inconclusive = data["inconclusive"].toBool(); item.file0 = data["file0"].toString(); QString file = StripPath(data["file"].toString(), true); unsigned int line = data["line"].toUInt(); item.files << file; item.lines << line; for (int j = 0; j < error->rowCount(); j++) { QStandardItem *child_error = error->child(j, 0); //Get error's user data QVariant child_userdata = child_error->data(); //Convert it to QVariantMap QVariantMap child_data = child_userdata.toMap(); file = StripPath(child_data["file"].toString(), true); line = child_data["line"].toUInt(); item.files << file; item.lines << line; } report->WriteError(item); } } void ResultsTree::UpdateSettings(bool showFullPath, bool saveFullPath, bool saveAllErrors, bool showErrorId) { if (mShowFullPath != showFullPath) { mShowFullPath = showFullPath; RefreshFilePaths(); } mSaveFullPath = saveFullPath; mSaveAllErrors = saveAllErrors; ShowIdColumn(showErrorId); } void ResultsTree::SetCheckDirectory(const QString &dir) { mCheckPath = dir; } QString ResultsTree::StripPath(const QString &path, bool saving) const { if ((!saving && mShowFullPath) || (saving && mSaveFullPath)) { return QString(path); } QDir dir(mCheckPath); return dir.relativeFilePath(path); } void ResultsTree::RefreshFilePaths(QStandardItem *item) { if (!item) { return; } //Mark that this file's path hasn't been updated yet bool updated = false; //Loop through all errors within this file for (int i = 0; i < item->rowCount(); i++) { //Get error i QStandardItem *error = item->child(i, 0); if (!error) { continue; } //Get error's user data QVariant userdata = error->data(); //Convert it to QVariantMap QVariantMap data = userdata.toMap(); //Get list of files QString file = data["file"].toString(); //Update this error's text error->setText(StripPath(file, false)); //If this error has backtraces make sure the files list has enough filenames if (error->hasChildren()) { //Loop through all files within the error for (int j = 0; j < error->rowCount(); j++) { //Get file QStandardItem *child = error->child(j, 0); if (!child) { continue; } //Get child's user data QVariant child_userdata = child->data(); //Convert it to QVariantMap QVariantMap child_data = child_userdata.toMap(); //Get list of files QString child_files = child_data["file"].toString(); //Update file's path child->setText(StripPath(child_files, false)); } } //if the main file hasn't been updated yet, update it now if (!updated) { updated = true; item->setText(error->text()); } } } void ResultsTree::RefreshFilePaths() { qDebug("Refreshing file paths"); //Go through all file items (these are parent items that contain the errors) for (int i = 0; i < mModel.rowCount(); i++) { RefreshFilePaths(mModel.item(i, 0)); } } bool ResultsTree::HasVisibleResults() const { return mVisibleErrors; } bool ResultsTree::HasResults() const { return mModel.rowCount() > 0; } void ResultsTree::Translate() { QStringList labels; labels << tr("File") << tr("Severity") << tr("Line") << tr("Id") << tr("Summary"); mModel.setHorizontalHeaderLabels(labels); //TODO go through all the errors in the tree and translate severity and message } void ResultsTree::ShowIdColumn(bool show) { mShowErrorId = show; if (show) showColumn(3); else hideColumn(3); } void ResultsTree::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) { QTreeView::currentChanged(current, previous); emit SelectionChanged(current); } cppcheck-1.61/gui/resultstree.h000066400000000000000000000264201217722632100165460ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #ifndef RESULTSTREE_H #define RESULTSTREE_H #include #include #include #include #include #include "errorlogger.h" // Severity #include "showtypes.h" class ApplicationList; class Report; class ErrorItem; class ErrorLine; class QModelIndex; class QWidget; class QItemSelectionModel; /// @addtogroup GUI /// @{ /** * @brief Cppcheck's results are shown in this tree * */ class ResultsTree : public QTreeView { Q_OBJECT public: ResultsTree(QWidget * parent = 0); virtual ~ResultsTree(); void Initialize(QSettings *settings, ApplicationList *list); /** * @brief Add a new item to the tree * * @param item Error item data */ bool AddErrorItem(const ErrorItem &item); /** * @brief Clear all errors from the tree * */ void Clear(); /** * @brief Clear errors for a specific file from the tree */ void Clear(const QString &filename); /** * @brief Function to show/hide certain type of errors * Refreshes the tree. * * @param type Type of error to show/hide * @param show Should specified errors be shown (true) or hidden (false) */ void ShowResults(ShowTypes::ShowType type, bool show); /** * @brief Function to filter the displayed list of errors. * Refreshes the tree. * * @param filter String that must be found in the summary, description, file or id */ void FilterResults(const QString& filter); /** * @brief Function to show results that were previous hidden with HideResult() */ void ShowHiddenResults(); /** * @brief Save results to a text stream * */ void SaveResults(Report *report) const; /** * @brief Update tree settings * * @param showFullPath Show full path of files in the tree * @param saveFullPath Save full path of files in reports * @param saveAllErrors Save all visible errors * @param showErrorId Show error id */ void UpdateSettings(bool showFullPath, bool saveFullPath, bool saveAllErrors, bool showErrorId); /** * @brief Set the directory we are checking * * This is used to split error file path to relative if necessary * @param dir Directory we are checking */ void SetCheckDirectory(const QString &dir); /** * @brief Check if there are any visible results in view. * @return true if there is at least one visible warning/error. */ bool HasVisibleResults() const; /** * @brief Do we have results from check? * @return true if there is at least one warning/error, hidden or visible. */ bool HasResults() const; /** * @brief Save all settings * Column widths */ void SaveSettings() const; /** * @brief Change all visible texts language * */ void Translate(); /** * @brief Show optional column "Id" */ void ShowIdColumn(bool show); /** * @brief Returns true if column "Id" is shown */ bool ShowIdColumn() const { return mShowErrorId; } /** * @brief GUI severities. */ ShowTypes mShowSeverities; signals: /** * @brief Signal that results have been hidden or shown * * @param hidden true if there are some hidden results, or false if there are not */ void ResultsHidden(bool hidden); /** * @brief Signal for selection change in result tree. * * @param current Model index to specify new selected item. */ void SelectionChanged(const QModelIndex ¤t); protected slots: /** * @brief Slot to quickstart an error with default application * * @param index Model index to specify which error item to open */ void QuickStartApplication(const QModelIndex &index); /** * @brief Slot for context menu item to open an error with specified application * * @param application Index of the application to open the error */ void Context(int application); /** * @brief Slot for context menu item to copy filename to clipboard * */ void CopyFilename(); /** * @brief Slot for context menu item to copy full path to clipboard * */ void CopyFullPath(); /** * @brief Slot for context menu item to the current error message to clipboard * */ void CopyMessage(); /** * @brief Slot for context menu item to the current error message Id to clipboard * */ void CopyMessageId(); /** * @brief Slot for context menu item to hide the current error message * */ void HideResult(); /** * @brief Slot for context menu item to hide all messages with the current message Id * */ void HideAllIdResult(); /** * @brief Slot for selection change in the results tree. * * @param current Model index to specify new selected item. * @param previous Model index to specify previous selected item. */ virtual void currentChanged(const QModelIndex ¤t, const QModelIndex &previous); protected: /** * @brief Hides/shows full file path on all error file items according to mShowFullPath * */ void RefreshFilePaths(); /** * @brief Hides/shows full file path on all error file items according to mShowFullPath * @param item Parent item whose childrens paths to change */ void RefreshFilePaths(QStandardItem *item); /** * @brief Removes checking directory from given path if mShowFullPath is false * * @param path Path to remove checking directory * @param saving are we saving? Check mSaveFullPath instead * @return Path that has checking directory removed */ QString StripPath(const QString &path, bool saving) const; /** * @brief Save all errors under specified item * @param report Report that errors are saved to * @param item Item whose errors to save */ void SaveErrors(Report *report, QStandardItem *item) const; /** * @brief Convert a severity string to a icon filename * * @param severity Severity */ QString SeverityToIcon(Severity::SeverityType severity) const; /** * @brief Helper function to open an error within target with application* * * @param target Error tree item to open * @param application Index of the application to open with. Giving -1 * (default value) will open the default application. */ void StartApplication(QStandardItem *target, int application = -1); /** * @brief Helper function to copy filename/full path to the clipboard * * @param target Error tree item to open * @param fullPath Are we copying full path or only filename? */ void CopyPath(QStandardItem *target, bool fullPath); /** * @brief Context menu event (user right clicked on the tree) * * @param e Event */ void contextMenuEvent(QContextMenuEvent * e); /** * @brief Add a new error item beneath a file or a backtrace item beneath an error * * @param parent Parent for the item. Either a file item or an error item * @param item Error line data * @param hide Should this be hidden (true) or shown (false) * @param icon Should a default backtrace item icon be added * @return newly created QStandardItem * */ QStandardItem *AddBacktraceFiles(QStandardItem *parent, const ErrorLine &item, const bool hide, const QString &icon); /** * @brief Refresh tree by checking which of the items should be shown * and which should be hidden * */ void RefreshTree(); /** * @brief Convert Severity to translated string for GUI. * @param severity Severity to convert * @return Severity as translated string */ static QString SeverityToTranslatedString(Severity::SeverityType severity); /** * @brief Load all settings * Column widths */ void LoadSettings(); /** * @brief Ask directory where file is located. * @param file File name. * @return Directory user chose. */ QString AskFileDir(const QString &file); /** * @brief Create new normal item. * * Normal item has left alignment and text set also as tooltip. * @param name name for the item * @return new QStandardItem */ static QStandardItem *CreateNormalItem(const QString &name); /** * @brief Create new line number item. * * Line number item has right align and text set as tooltip. * @param linenumber name for the item * @return new QStandardItem */ static QStandardItem *CreateLineNumberItem(const QString &linenumber); /** * @brief Finds a file item * * @param name name of the file item to find * @return pointer to file item or null if none found */ QStandardItem *FindFileItem(const QString &name) const; /** * @brief Ensures there's a item in the model for the specified file * * @param fullpath Full path to the file item. * @param file0 Source file * @param hide is the error (we want this file item for) hidden? * @return QStandardItem to be used as a parent for all errors for specified file */ QStandardItem *EnsureFileItem(const QString &fullpath, const QString &file0, bool hide); /** * @brief Show a file item * * @param name Filename of the fileitem */ void ShowFileItem(const QString &name); /** * @brief Item model for tree * */ QStandardItemModel mModel; /** * @brief Program settings * */ QSettings *mSettings; /** * @brief A string used to filter the results for display. * */ QString mFilter; /** * @brief List of applications to open errors with * */ ApplicationList *mApplications; /** * @brief Right clicked item (used by context menu slots) * */ QStandardItem *mContextItem; /** * @brief Should full path of files be shown (true) or relative (false) * */ bool mShowFullPath; /** * @brief Should full path of files be saved * */ bool mSaveFullPath; /** * @brief Save all errors (true) or only visible (false) * */ bool mSaveAllErrors; /** * @brief true if optional column "Id" is shown * */ bool mShowErrorId; /** * @brief Path we are currently checking * */ QString mCheckPath; /** * @brief Are there any visible errors * */ bool mVisibleErrors; private: QItemSelectionModel *mSelectionModel; }; /// @} #endif // RESULTSTREE_H cppcheck-1.61/gui/resultsview.cpp000066400000000000000000000222151217722632100171120ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include #include #include #include #include #include #include "common.h" #include "erroritem.h" #include "resultsview.h" #include "report.h" #include "txtreport.h" #include "xmlreport.h" #include "xmlreportv1.h" #include "xmlreportv2.h" #include "csvreport.h" #include "applicationlist.h" #include "checkstatistics.h" ResultsView::ResultsView(QWidget * parent) : QWidget(parent), mErrorsFound(false), mShowNoErrorsMessage(true), mStatistics(new CheckStatistics(this)) { mUI.setupUi(this); connect(mUI.mTree, SIGNAL(ResultsHidden(bool)), this, SIGNAL(ResultsHidden(bool))); connect(mUI.mTree, SIGNAL(SelectionChanged(const QModelIndex &)), this, SLOT(UpdateDetails(const QModelIndex &))); } void ResultsView::Initialize(QSettings *settings, ApplicationList *list) { mUI.mProgress->setMinimum(0); mUI.mProgress->setVisible(false); QByteArray state = settings->value(SETTINGS_MAINWND_SPLITTER_STATE).toByteArray(); mUI.mVerticalSplitter->restoreState(state); mShowNoErrorsMessage = settings->value(SETTINGS_SHOW_NO_ERRORS, true).toBool(); mUI.mTree->Initialize(settings, list); } ResultsView::~ResultsView() { //dtor } void ResultsView::Clear(bool results) { if (results) { mUI.mTree->Clear(); mErrorsFound = false; } mUI.mDetails->setText(""); mStatistics->Clear(); //Clear the progressbar mUI.mProgress->setMaximum(PROGRESS_MAX); mUI.mProgress->setValue(0); mUI.mProgress->setFormat("%p%"); } void ResultsView::Clear(const QString &filename) { mUI.mTree->Clear(filename); /** * @todo Optimize this.. It is inefficient to check this every time. */ // If the results list got empty.. if (!mUI.mTree->HasResults()) mErrorsFound = false; } void ResultsView::Progress(int value, const QString& description) { mUI.mProgress->setValue(value); mUI.mProgress->setFormat(QString("%p% (%1)").arg(description)); } void ResultsView::Error(const ErrorItem &item) { mErrorsFound = true; if (mUI.mTree->AddErrorItem(item)) { emit GotResults(); mStatistics->AddItem(ShowTypes::SeverityToShowType(item.severity)); } } void ResultsView::ShowResults(ShowTypes::ShowType type, bool show) { mUI.mTree->ShowResults(type, show); } void ResultsView::CollapseAllResults() { mUI.mTree->collapseAll(); } void ResultsView::ExpandAllResults() { mUI.mTree->expandAll(); } void ResultsView::ShowHiddenResults() { mUI.mTree->ShowHiddenResults(); } void ResultsView::FilterResults(const QString& filter) { mUI.mTree->FilterResults(filter); } void ResultsView::Save(const QString &filename, Report::Type type) const { if (!mErrorsFound) { QMessageBox msgBox; msgBox.setText(tr("No errors found, nothing to save.")); msgBox.setIcon(QMessageBox::Critical); msgBox.exec(); } Report *report = NULL; switch (type) { case Report::CSV: report = new CsvReport(filename); break; case Report::TXT: report = new TxtReport(filename); break; case Report::XML: report = new XmlReportV1(filename); break; case Report::XMLV2: report = new XmlReportV2(filename); break; } if (report) { if (report->Create()) mUI.mTree->SaveResults(report); else { QMessageBox msgBox; msgBox.setText(tr("Failed to save the report.")); msgBox.setIcon(QMessageBox::Critical); msgBox.exec(); } delete report; report = NULL; } else { QMessageBox msgBox; msgBox.setText(tr("Failed to save the report.")); msgBox.setIcon(QMessageBox::Critical); msgBox.exec(); } } void ResultsView::UpdateSettings(bool showFullPath, bool saveFullPath, bool saveAllErrors, bool showNoErrorsMessage, bool showErrorId) { mUI.mTree->UpdateSettings(showFullPath, saveFullPath, saveAllErrors, showErrorId); mShowNoErrorsMessage = showNoErrorsMessage; } void ResultsView::SetCheckDirectory(const QString &dir) { mUI.mTree->SetCheckDirectory(dir); } void ResultsView::CheckingStarted(int count) { mUI.mProgress->setVisible(true); mUI.mProgress->setMaximum(PROGRESS_MAX); mUI.mProgress->setValue(0); mUI.mProgress->setFormat(tr("%p% (%1 of %2 files checked)").arg(0).arg(count)); } void ResultsView::CheckingFinished() { mUI.mProgress->setVisible(false); mUI.mProgress->setFormat("%p%"); //Should we inform user of non visible/not found errors? if (mShowNoErrorsMessage) { //Tell user that we found no errors if (!mErrorsFound) { QMessageBox msg(QMessageBox::Information, tr("Cppcheck"), tr("No errors found."), QMessageBox::Ok, this); msg.exec(); } //If we have errors but they aren't visible, tell user about it else if (!mUI.mTree->HasVisibleResults()) { QString text = tr("Errors were found, but they are configured to be hidden.\n"\ "To toggle what kind of errors are shown, open view menu."); QMessageBox msg(QMessageBox::Information, tr("Cppcheck"), text, QMessageBox::Ok, this); msg.exec(); } } } bool ResultsView::HasVisibleResults() const { return mUI.mTree->HasVisibleResults(); } bool ResultsView::HasResults() const { return mUI.mTree->HasResults(); } void ResultsView::SaveSettings(QSettings *settings) { mUI.mTree->SaveSettings(); QByteArray state = mUI.mVerticalSplitter->saveState(); settings->setValue(SETTINGS_MAINWND_SPLITTER_STATE, state); mUI.mVerticalSplitter->restoreState(state); } void ResultsView::Translate() { mUI.mTree->Translate(); } void ResultsView::DisableProgressbar() { mUI.mProgress->setEnabled(false); } void ResultsView::ReadErrorsXml(const QString &filename) { const int version = XmlReport::determineVersion(filename); if (version == 0) { QMessageBox msgBox; msgBox.setText(tr("Failed to read the report.")); msgBox.setIcon(QMessageBox::Critical); msgBox.exec(); return; } XmlReport *report = NULL; if (version == 1) report = new XmlReportV1(filename); else if (version == 2) report = new XmlReportV2(filename); QList errors; if (report) { if (report->Open()) errors = report->Read(); else { QMessageBox msgBox; msgBox.setText(tr("Failed to read the report.")); msgBox.setIcon(QMessageBox::Critical); msgBox.exec(); } delete report; report = NULL; } else { QMessageBox msgBox; msgBox.setText(tr("Failed to read the report.")); msgBox.setIcon(QMessageBox::Critical); msgBox.exec(); } ErrorItem item; foreach(item, errors) { mUI.mTree->AddErrorItem(item); } mUI.mTree->SetCheckDirectory(""); } void ResultsView::UpdateDetails(const QModelIndex &index) { QStandardItemModel *model = qobject_cast(mUI.mTree->model()); QStandardItem *item = model->itemFromIndex(index); if (!item) { mUI.mDetails->setText(""); return; } // Make sure we are working with the first column if (item->parent() && item->column() != 0) item = item->parent()->child(item->row(), 0); QVariantMap data = item->data().toMap(); // If there is no severity data then it is a parent item without summary and message if (!data.contains("severity")) { mUI.mDetails->setText(""); return; } const QString summary = data["summary"].toString(); const QString message = data["message"].toString(); QString formattedMsg = QString("%1: %2\n%3: %4") .arg(tr("Summary")).arg(summary) .arg(tr("Message")).arg(message); if (mUI.mTree->ShowIdColumn()) formattedMsg.prepend(tr("Id") + ": " + data["id"].toString() + "\n"); mUI.mDetails->setText(formattedMsg); } cppcheck-1.61/gui/resultsview.h000066400000000000000000000133441217722632100165620ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #ifndef RESULTSVIEW_H #define RESULTSVIEW_H #include #include "report.h" #include "showtypes.h" #include "ui_resultsview.h" class ErrorItem; class ApplicationList; class QModelIndex; class QSettings; class CheckStatistics; /// @addtogroup GUI /// @{ /** * @brief Widget to show cppcheck progressbar and result * */ class ResultsView : public QWidget { Q_OBJECT public: ResultsView(QWidget * parent = 0); void Initialize(QSettings *settings, ApplicationList *list); virtual ~ResultsView(); /** * @brief Function to show/hide certain type of errors * Refreshes the tree. * * @param type Type of error to show/hide * @param show Should specified errors be shown (true) or hidden (false) */ void ShowResults(ShowTypes::ShowType type, bool show); /** * @brief Clear results and statistics and reset progressinfo. * @param results Remove all the results from view? */ void Clear(bool results); /** * @brief Remove a file from the results. */ void Clear(const QString &filename); /** * @brief Save results to a file * * @param filename Filename to save results to * @param type Type of the report. */ void Save(const QString &filename, Report::Type type) const; /** * @brief Update tree settings * * @param showFullPath Show full path of files in the tree * @param saveFullPath Save full path of files in reports * @param saveAllErrors Save all visible errors * @param showNoErrorsMessage Show "no errors"? * @param showErrorId Show error id? */ void UpdateSettings(bool showFullPath, bool saveFullPath, bool saveAllErrors, bool showNoErrorsMessage, bool showErrorId); /** * @brief Set the directory we are checking * * This is used to split error file path to relative if necessary * @param dir Directory we are checking */ void SetCheckDirectory(const QString &dir); /** * @brief Inform the view that checking has started * * @param count Count of files to be checked. */ void CheckingStarted(int count); /** * @brief Inform the view that checking finished. * */ void CheckingFinished(); /** * @brief Do we have visible results to show? * * @return true if there is at least one warning/error to show. */ bool HasVisibleResults() const; /** * @brief Do we have results from check? * * @return true if there is at least one warning/error, hidden or visible. */ bool HasResults() const; /** * @brief Save View's settings * * @param settings program settings. */ void SaveSettings(QSettings *settings); /** * @brief Translate this view * */ void Translate(); void DisableProgressbar(); /** * @brief Read errors from report XML file. * @param filename Report file to read. * */ void ReadErrorsXml(const QString &filename); /** * @brief Return checking statistics. * @return Pointer to checking statistics. */ CheckStatistics *GetStatistics() const { return mStatistics; } /** * @brief Return Showtypes. * @return Pointer to Showtypes. */ ShowTypes * GetShowTypes() const { return &mUI.mTree->mShowSeverities; } signals: /** * @brief Signal to be emitted when we have results * */ void GotResults(); /** * @brief Signal that results have been hidden or shown * * @param hidden true if there are some hidden results, or false if there are not */ void ResultsHidden(bool hidden); public slots: /** * @brief Slot for updating the checking progress * * @param value Current progress value * @param description Description to accompany the progress */ void Progress(int value, const QString& description); /** * @brief Slot for new error to be displayed * * @param item Error data */ void Error(const ErrorItem &item); /** * @brief Collapse all results in the result list. */ void CollapseAllResults(); /** * @brief Expand all results in the result list. */ void ExpandAllResults(); /** * @brief Filters the results in the result list. */ void FilterResults(const QString& filter); /** * @brief Show hidden results in the result list. */ void ShowHiddenResults(); /** * @brief Update detailed message when selected item is changed. * * @param index Position of new selected item. */ void UpdateDetails(const QModelIndex &index); protected: /** * @brief Have any errors been found */ bool mErrorsFound; /** * @brief Should we show a "No errors found dialog" every time no errors were found? */ bool mShowNoErrorsMessage; Ui::ResultsView mUI; CheckStatistics *mStatistics; private: }; /// @} #endif // RESULTSVIEW_H cppcheck-1.61/gui/resultsview.ui000066400000000000000000000042511217722632100167450ustar00rootroot00000000000000 ResultsView 0 0 459 357 0 0 16777215 16777215 Results 0 0 0 24 Qt::Vertical 0 0 QAbstractItemView::ExtendedSelection false true ResultsTree QTreeView
resultstree.h
mTree mDetails
cppcheck-1.61/gui/scratchpad.cpp000066400000000000000000000023731217722632100166350ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include "scratchpad.h" #include "mainwindow.h" #include ScratchPad::ScratchPad(MainWindow& mainWindow) : QDialog(&mainWindow) , mMainWindow(mainWindow) { mUI.setupUi(this); connect(mUI.mCheckButton, SIGNAL(clicked()), this, SLOT(CheckButtonClicked())); } void ScratchPad::CheckButtonClicked() { QString filename = mUI.lineEdit->text(); if (filename.isEmpty()) filename = "test.cpp"; mMainWindow.CheckCode(mUI.plainTextEdit->toPlainText(), filename); } cppcheck-1.61/gui/scratchpad.h000066400000000000000000000023631217722632100163010ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #ifndef SCRATCHPAD_H #define SCRATCHPAD_H #include #include "ui_scratchpad.h" class MainWindow; /// @addtogroup GUI /// @{ /** * @brief A window with a text field that . */ class ScratchPad : public QDialog { Q_OBJECT public: ScratchPad(MainWindow& mainWindow); private slots: /** * @brief Called when check button is clicked. */ void CheckButtonClicked(); private: Ui::ScratchPad mUI; MainWindow& mMainWindow; }; /// @} #endif // SCRATCHPAD_H cppcheck-1.61/gui/scratchpad.ui000066400000000000000000000046541217722632100164740ustar00rootroot00000000000000 ScratchPad 0 0 500 600 Scratchpad Courier New 10 0 Qt::Horizontal 40 20 filename Check 0 0 Qt::Horizontal QDialogButtonBox::Close mButtonBox rejected() ScratchPad reject() 20 20 20 20 cppcheck-1.61/gui/settings.ui000066400000000000000000000307201217722632100162110ustar00rootroot00000000000000 Settings 0 0 589 319 Preferences 0 General QLayout::SetDefaultConstraint 0 0 Number of threads: mJobs 0 0 100 20 100 20 009; 3 Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Ideal count: TextLabel Qt::Horizontal 40 20 Force checking all #ifdef configurations Show full path of files Show "No errors found" message when no errors found Display error Id in column "Id" Enable inline suppressions Qt::Vertical 20 40 Paths Include paths: QAbstractItemView::SelectRows Add... Edit Remove Qt::Vertical 20 40 Applications Add... Edit... Remove Set as default Qt::Vertical 20 40 Reports Save all errors when creating report Save full path to files in reports Qt::Vertical 20 40 Language QAbstractItemView::SelectRows Advanced &Show inconclusive errors S&how internal warnings in log Qt::Vertical 20 40 Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok tabWidget mJobs mForce mShowFullPath mShowNoErrorsMessage mInlineSuppressions mListIncludePaths mBtnAddIncludePath mBtnEditIncludePath mBtnRemoveIncludePath mListWidget mBtnAddApplication mBtnEditApplication mBtnRemoveApplication mBtnDefaultApplication mSaveAllErrors mSaveFullPath mListLanguages mEnableInconclusive mShowDebugWarnings mButtons mButtons accepted() Settings accept() 248 254 157 274 mButtons rejected() Settings reject() 316 260 286 274 cppcheck-1.61/gui/settingsdialog.cpp000066400000000000000000000262541217722632100175450ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include #include #include #include #include #include #include "settingsdialog.h" #include "applicationdialog.h" #include "applicationlist.h" #include "translationhandler.h" #include "common.h" SettingsDialog::SettingsDialog(ApplicationList *list, TranslationHandler *translator, QWidget *parent) : QDialog(parent), mApplications(list), mTempApplications(new ApplicationList(this)), mTranslator(translator) { mUI.setupUi(this); QSettings settings; mTempApplications->Copy(list); mUI.mJobs->setText(settings.value(SETTINGS_CHECK_THREADS, 1).toString()); mUI.mForce->setCheckState(BoolToCheckState(settings.value(SETTINGS_CHECK_FORCE, false).toBool())); mUI.mShowFullPath->setCheckState(BoolToCheckState(settings.value(SETTINGS_SHOW_FULL_PATH, false).toBool())); mUI.mShowNoErrorsMessage->setCheckState(BoolToCheckState(settings.value(SETTINGS_SHOW_NO_ERRORS, false).toBool())); mUI.mShowDebugWarnings->setCheckState(BoolToCheckState(settings.value(SETTINGS_SHOW_DEBUG_WARNINGS, false).toBool())); mUI.mSaveAllErrors->setCheckState(BoolToCheckState(settings.value(SETTINGS_SAVE_ALL_ERRORS, false).toBool())); mUI.mSaveFullPath->setCheckState(BoolToCheckState(settings.value(SETTINGS_SAVE_FULL_PATH, false).toBool())); mUI.mInlineSuppressions->setCheckState(BoolToCheckState(settings.value(SETTINGS_INLINE_SUPPRESSIONS, false).toBool())); mUI.mEnableInconclusive->setCheckState(BoolToCheckState(settings.value(SETTINGS_INCONCLUSIVE_ERRORS, false).toBool())); mUI.mShowErrorId->setCheckState(BoolToCheckState(settings.value(SETTINGS_SHOW_ERROR_ID, false).toBool())); connect(mUI.mButtons, SIGNAL(accepted()), this, SLOT(Ok())); connect(mUI.mButtons, SIGNAL(rejected()), this, SLOT(reject())); connect(mUI.mBtnAddApplication, SIGNAL(clicked()), this, SLOT(AddApplication())); connect(mUI.mBtnRemoveApplication, SIGNAL(clicked()), this, SLOT(RemoveApplication())); connect(mUI.mBtnEditApplication, SIGNAL(clicked()), this, SLOT(EditApplication())); connect(mUI.mBtnDefaultApplication, SIGNAL(clicked()), this, SLOT(DefaultApplication())); connect(mUI.mListWidget, SIGNAL(itemDoubleClicked(QListWidgetItem *)), this, SLOT(EditApplication())); connect(mUI.mBtnAddIncludePath, SIGNAL(clicked()), this, SLOT(AddIncludePath())); connect(mUI.mBtnRemoveIncludePath, SIGNAL(clicked()), this, SLOT(RemoveIncludePath())); connect(mUI.mBtnEditIncludePath, SIGNAL(clicked()), this, SLOT(EditIncludePath())); mUI.mListWidget->setSortingEnabled(false); PopulateApplicationList(); const int count = QThread::idealThreadCount(); if (count != -1) mUI.mLblIdealThreads->setText(QString::number(count)); else mUI.mLblIdealThreads->setText(tr("N/A")); LoadSettings(); InitTranslationsList(); InitIncludepathsList(); } SettingsDialog::~SettingsDialog() { SaveSettings(); } void SettingsDialog::AddIncludePath(const QString &path) { if (path.isNull() || path.isEmpty()) return; QListWidgetItem *item = new QListWidgetItem(path); item->setFlags(item->flags() | Qt::ItemIsEditable); mUI.mListIncludePaths->addItem(item); } void SettingsDialog::InitIncludepathsList() { QSettings settings; const QString allPaths = settings.value(SETTINGS_GLOBAL_INCLUDE_PATHS).toString(); const QStringList paths = allPaths.split(";", QString::SkipEmptyParts); foreach(QString path, paths) { AddIncludePath(path); } } void SettingsDialog::InitTranslationsList() { const QString current = mTranslator->GetCurrentLanguage(); QList translations = mTranslator->GetTranslations(); foreach(TranslationInfo translation, translations) { QListWidgetItem *item = new QListWidgetItem; item->setText(translation.mName); item->setData(LangCodeRole, QVariant(translation.mCode)); mUI.mListLanguages->addItem(item); if (translation.mCode == current) mUI.mListLanguages->setCurrentItem(item); } } Qt::CheckState SettingsDialog::BoolToCheckState(bool yes) { if (yes) { return Qt::Checked; } return Qt::Unchecked; } bool SettingsDialog::CheckStateToBool(Qt::CheckState state) { if (state == Qt::Checked) { return true; } return false; } void SettingsDialog::LoadSettings() { QSettings settings; resize(settings.value(SETTINGS_CHECK_DIALOG_WIDTH, 800).toInt(), settings.value(SETTINGS_CHECK_DIALOG_HEIGHT, 600).toInt()); } void SettingsDialog::SaveSettings() const { QSettings settings; settings.setValue(SETTINGS_CHECK_DIALOG_WIDTH, size().width()); settings.setValue(SETTINGS_CHECK_DIALOG_HEIGHT, size().height()); } void SettingsDialog::SaveSettingValues() const { int jobs = mUI.mJobs->text().toInt(); if (jobs <= 0) { jobs = 1; } QSettings settings; settings.setValue(SETTINGS_CHECK_THREADS, jobs); SaveCheckboxValue(&settings, mUI.mForce, SETTINGS_CHECK_FORCE); SaveCheckboxValue(&settings, mUI.mSaveAllErrors, SETTINGS_SAVE_ALL_ERRORS); SaveCheckboxValue(&settings, mUI.mSaveFullPath, SETTINGS_SAVE_FULL_PATH); SaveCheckboxValue(&settings, mUI.mShowFullPath, SETTINGS_SHOW_FULL_PATH); SaveCheckboxValue(&settings, mUI.mShowNoErrorsMessage, SETTINGS_SHOW_NO_ERRORS); SaveCheckboxValue(&settings, mUI.mShowDebugWarnings, SETTINGS_SHOW_DEBUG_WARNINGS); SaveCheckboxValue(&settings, mUI.mInlineSuppressions, SETTINGS_INLINE_SUPPRESSIONS); SaveCheckboxValue(&settings, mUI.mEnableInconclusive, SETTINGS_INCONCLUSIVE_ERRORS); SaveCheckboxValue(&settings, mUI.mShowErrorId, SETTINGS_SHOW_ERROR_ID); QListWidgetItem *currentLang = mUI.mListLanguages->currentItem(); const QString langcode = currentLang->data(LangCodeRole).toString(); settings.setValue(SETTINGS_LANGUAGE, langcode); const int count = mUI.mListIncludePaths->count(); QString includePaths; for (int i = 0; i < count; i++) { QListWidgetItem *item = mUI.mListIncludePaths->item(i); includePaths += item->text(); includePaths += ";"; } settings.setValue(SETTINGS_GLOBAL_INCLUDE_PATHS, includePaths); } void SettingsDialog::SaveCheckboxValue(QSettings *settings, QCheckBox *box, const QString &name) { settings->setValue(name, CheckStateToBool(box->checkState())); } void SettingsDialog::AddApplication() { Application app; ApplicationDialog dialog(tr("Add a new application"), app, this); if (dialog.exec() == QDialog::Accepted) { mTempApplications->AddApplication(app); mUI.mListWidget->addItem(app.getName()); } } void SettingsDialog::RemoveApplication() { QList selected = mUI.mListWidget->selectedItems(); foreach(QListWidgetItem *item, selected) { const int removeIndex = mUI.mListWidget->row(item); const int currentDefault = mTempApplications->GetDefaultApplication(); mTempApplications->RemoveApplication(removeIndex); if (removeIndex == currentDefault) // If default app is removed set default to unknown mTempApplications->SetDefault(-1); else if (removeIndex < currentDefault) // Move default app one up if earlier app was removed mTempApplications->SetDefault(currentDefault - 1); } mUI.mListWidget->clear(); PopulateApplicationList(); } void SettingsDialog::EditApplication() { QList selected = mUI.mListWidget->selectedItems(); QListWidgetItem *item = 0; foreach(item, selected) { int row = mUI.mListWidget->row(item); Application& app = mTempApplications->GetApplication(row); ApplicationDialog dialog(tr("Modify an application"), app, this); if (dialog.exec() == QDialog::Accepted) { item->setText(app.getName()); } } } void SettingsDialog::DefaultApplication() { QList selected = mUI.mListWidget->selectedItems(); if (!selected.isEmpty()) { int index = mUI.mListWidget->row(selected[0]); mTempApplications->SetDefault(index); mUI.mListWidget->clear(); PopulateApplicationList(); } } void SettingsDialog::PopulateApplicationList() { const int defapp = mTempApplications->GetDefaultApplication(); for (int i = 0; i < mTempApplications->GetApplicationCount(); i++) { const Application& app = mTempApplications->GetApplication(i); QString name = app.getName(); if (i == defapp) { name += " "; name += tr("[Default]"); } mUI.mListWidget->addItem(name); } // Select default application, or if there is no default app then the // first item. if (defapp == -1) mUI.mListWidget->setCurrentRow(0); else { if (mTempApplications->GetApplicationCount() > defapp) mUI.mListWidget->setCurrentRow(defapp); else mUI.mListWidget->setCurrentRow(0); } } void SettingsDialog::Ok() { mApplications->Copy(mTempApplications); accept(); } bool SettingsDialog::ShowFullPath() const { return CheckStateToBool(mUI.mShowFullPath->checkState()); } bool SettingsDialog::SaveFullPath() const { return CheckStateToBool(mUI.mSaveFullPath->checkState()); } bool SettingsDialog::SaveAllErrors() const { return CheckStateToBool(mUI.mSaveAllErrors->checkState()); } bool SettingsDialog::ShowNoErrorsMessage() const { return CheckStateToBool(mUI.mShowNoErrorsMessage->checkState()); } bool SettingsDialog::ShowErrorId() const { return CheckStateToBool(mUI.mShowErrorId->checkState()); } void SettingsDialog::AddIncludePath() { QString selectedDir = QFileDialog::getExistingDirectory(this, tr("Select include directory"), GetPath(SETTINGS_LAST_INCLUDE_PATH)); if (!selectedDir.isEmpty()) { AddIncludePath(selectedDir); SetPath(SETTINGS_LAST_INCLUDE_PATH, selectedDir); } } void SettingsDialog::RemoveIncludePath() { const int row = mUI.mListIncludePaths->currentRow(); QListWidgetItem *item = mUI.mListIncludePaths->takeItem(row); delete item; } void SettingsDialog::EditIncludePath() { QListWidgetItem *item = mUI.mListIncludePaths->currentItem(); mUI.mListIncludePaths->editItem(item); } cppcheck-1.61/gui/settingsdialog.h000066400000000000000000000116251217722632100172060ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #ifndef SETTINGSDIALOG_H #define SETTINGSDIALOG_H #include #include "ui_settings.h" class QSettings; class QWidget; class ApplicationList; class TranslationHandler; /// @addtogroup GUI /// @{ /** * @brief Settings dialog * */ class SettingsDialog : public QDialog { Q_OBJECT public: SettingsDialog(ApplicationList *list, TranslationHandler *translator, QWidget *parent = 0); virtual ~SettingsDialog(); /** * @brief Save all values to QSettings * */ void SaveSettingValues() const; /** * @brief Get checkbox value for mShowFullPath * * @return should full path of errors be shown in the tree */ bool ShowFullPath() const; /** * @brief Get checkbox value for mSaveFullPath * * @return should full path of files be saved when creating a report */ bool SaveFullPath() const; /** * @brief Get checkbox value for mNoErrorsMessage * * @return Should "no errors message" be hidden */ bool ShowNoErrorsMessage() const; /** * @brief Get checkbox value for mShowIdColumn * * @return Should error id column be displayed */ bool ShowErrorId() const; /** * @brief Get checkbox value for mSaveAllErrors * * @return should all errors be saved to report */ bool SaveAllErrors() const; protected slots: /** * @brief Slot for clicking OK. * */ void Ok(); /** * @brief Slot for adding a new application to the list * */ void AddApplication(); /** * @brief Slot for deleting an application from the list * */ void RemoveApplication(); /** * @brief Slot for modifying an application in the list * */ void EditApplication(); /** * @brief Slot for making the selected application as the default (first) * */ void DefaultApplication(); /** * @brief Slot for adding new include path * */ void AddIncludePath(); /** * @brief Slot for removing an include path. * */ void RemoveIncludePath(); /** * @brief Slot for editing an include path. * */ void EditIncludePath(); protected: /** * @brief Add new include path to the list. * @param path Path to add. * */ void AddIncludePath(const QString &path); /** * @brief Clear all applications from the list and re insert them from mTempApplications * */ void PopulateApplicationList(); /** * @brief Load saved values * Loads dialog size and column widths. * */ void SaveSettings() const; /** * @brief Save settings * Save dialog size and column widths. * */ void LoadSettings(); /** * @brief Save a single checkboxes value * * @param settings Pointer to Settings. * @param box checkbox to save * @param name name for QSettings to store the value */ static void SaveCheckboxValue(QSettings *settings, QCheckBox *box, const QString &name); /** * @brief Convert bool to Qt::CheckState * * @param yes value to convert * @return value converted to Qt::CheckState */ static Qt::CheckState BoolToCheckState(bool yes); /** * @brief Converts Qt::CheckState to bool * * @param state Qt::CheckState to convert * @return converted value */ static bool CheckStateToBool(Qt::CheckState state); /** * @brief Populate the include paths-list. */ void InitIncludepathsList(); /** * @brief Populate the translations list. */ void InitTranslationsList(); /** * @brief List of applications user has specified * */ ApplicationList *mApplications; /** * @brief Temporary list of applications * This will be copied to actual list of applications (mApplications) * when user clicks ok. */ ApplicationList *mTempApplications; /** * @brief List of translations. * */ TranslationHandler *mTranslator; /** * @brief Dialog from UI designer * */ Ui::Settings mUI; private: static const int LangCodeRole = Qt::UserRole; }; /// @} #endif // SETTINGSDIALOG_H cppcheck-1.61/gui/showtypes.cpp000066400000000000000000000074141217722632100165670ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include "common.h" #include "showtypes.h" #include "errorlogger.h" ShowTypes::ShowTypes() { load(); } ShowTypes::~ShowTypes() { save(); } ShowTypes::ShowType ShowTypes::SeverityToShowType(Severity::SeverityType severity) { switch (severity) { case Severity::none: return ShowTypes::ShowNone; case Severity::error: return ShowTypes::ShowErrors; case Severity::style: return ShowTypes::ShowStyle; case Severity::warning: return ShowTypes::ShowWarnings; case Severity::performance: return ShowTypes::ShowPerformance; case Severity::portability: return ShowTypes::ShowPortability; case Severity::information: return ShowTypes::ShowInformation; default: return ShowTypes::ShowNone; } } Severity::SeverityType ShowTypes::ShowTypeToSeverity(ShowTypes::ShowType type) { switch (type) { case ShowTypes::ShowStyle: return Severity::style; case ShowTypes::ShowErrors: return Severity::error; case ShowTypes::ShowWarnings: return Severity::warning; case ShowTypes::ShowPerformance: return Severity::performance; case ShowTypes::ShowPortability: return Severity::portability; case ShowTypes::ShowInformation: return Severity::information; case ShowTypes::ShowNone: default: return Severity::none; } } ShowTypes::ShowType ShowTypes::VariantToShowType(const QVariant &data) { const int value = data.toInt(); if (value < ShowTypes::ShowStyle || value > ShowTypes::ShowErrors) { return ShowTypes::ShowNone; } return (ShowTypes::ShowType)value; } void ShowTypes::load() { QSettings settings; mVisible[ShowStyle] = settings.value(SETTINGS_SHOW_STYLE, true).toBool(); mVisible[ShowErrors] = settings.value(SETTINGS_SHOW_ERRORS, true).toBool(); mVisible[ShowWarnings] = settings.value(SETTINGS_SHOW_WARNINGS, true).toBool(); mVisible[ShowPortability] = settings.value(SETTINGS_SHOW_PORTABILITY, true).toBool(); mVisible[ShowPerformance] = settings.value(SETTINGS_SHOW_PERFORMANCE, true).toBool(); mVisible[ShowInformation] = settings.value(SETTINGS_SHOW_INFORMATION, true).toBool(); } void ShowTypes::save() const { QSettings settings; settings.setValue(SETTINGS_SHOW_STYLE, mVisible[ShowStyle]); settings.setValue(SETTINGS_SHOW_ERRORS, mVisible[ShowErrors]); settings.setValue(SETTINGS_SHOW_WARNINGS, mVisible[ShowWarnings]); settings.setValue(SETTINGS_SHOW_PORTABILITY, mVisible[ShowPortability]); settings.setValue(SETTINGS_SHOW_PERFORMANCE, mVisible[ShowPerformance]); settings.setValue(SETTINGS_SHOW_INFORMATION, mVisible[ShowInformation]); } bool ShowTypes::isShown(ShowTypes::ShowType category) const { return mVisible[category]; } bool ShowTypes::isShown(Severity::SeverityType severity) const { return isShown(ShowTypes::SeverityToShowType(severity)); } void ShowTypes::show(ShowTypes::ShowType category, bool showing) { mVisible[category] = showing; } cppcheck-1.61/gui/showtypes.h000066400000000000000000000066751217722632100162440ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #ifndef SHOWTYPES_H #define SHOWTYPES_H #include #include "errorlogger.h" /// @addtogroup GUI /// @{ /** * @brief A class for different show types we have. * This class contains enum type for the different show types we have. Each * show type presents one severity selectable in the GUI. In addition there * are several supporting functions. * * Notice that the "visibility" settings are automatically loaded when the * class is constructed and saved when the class is destroyed. */ class ShowTypes { public: /** * @brief Show types we have (i.e. severities in the GUI). */ enum ShowType { ShowStyle = 0, ShowWarnings, ShowPerformance, ShowPortability, ShowInformation, ShowErrors, // Keep this as last real item ShowNone }; /** * @brief Constructor. * @note Loads visibility settings. */ ShowTypes(); /** * @brief Destructor. * @note Saves visibility settings. */ ~ShowTypes(); /** * @brief Load visibility settings from the platform's settings storage. */ void load(); /** * @brief Save visibility settings to the platform's settings storage. */ void save() const; /** * @brief Is the showtype visible in the GUI? * @param category Showtype to check. * @return true if the showtype is visible. */ bool isShown(ShowTypes::ShowType category) const; /** * @brief Is the severity visible in the GUI? * @param severity severity to check. * @return true if the severity is visible. */ bool isShown(Severity::SeverityType severity) const; /** * @brief Show/hide the showtype. * @param category Showtype whose visibility to set. * @param showing true if the severity is set visible. */ void show(ShowTypes::ShowType category, bool showing); /** * @brief Convert severity string to ShowTypes value * @param severity Error severity * @return Severity converted to ShowTypes value */ static ShowTypes::ShowType SeverityToShowType(Severity::SeverityType severity); /** * @brief Convert ShowType to severity string * @param type ShowType to convert * @return ShowType converted to severity */ static Severity::SeverityType ShowTypeToSeverity(ShowTypes::ShowType type); /** * @brief Convert QVariant (that contains an int) to Showtypes value * * @param data QVariant (that contains an int) to be converted * @return data converted to ShowTypes */ static ShowTypes::ShowType VariantToShowType(const QVariant &data); bool mVisible[ShowNone]; }; /// @} #endif // SHOWTYPES_H cppcheck-1.61/gui/stats.ui000066400000000000000000000303351217722632100155110ustar00rootroot00000000000000 StatsDialog 0 0 502 272 Statistics QTabWidget::Rounded 2 Project Project: 0 0 true Paths: true 0 0 true false true true Include paths: true 0 0 true Defines: true 0 0 true Qt::Vertical 20 40 Previous Scan Path Selected: Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop Number of Files Scanned: Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing Scan Duration: Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing Qt::Vertical 20 40 0 0 true Statistics Errors: TextLabel Warnings: TextLabel Stylistic warnings: TextLabel Portability warnings: TextLabel Performance issues: TextLabel Information messages: TextLabel 0 Qt::Horizontal 40 20 Copy to Clipboard 0 0 Qt::Horizontal QDialogButtonBox::Close mTabWidget mProject mPaths mIncludePaths mDefines mCopyToClipboard mButtonBox mPath mButtonBox accepted() StatsDialog accept() 483 310 157 274 mButtonBox rejected() StatsDialog reject() 483 310 286 274 cppcheck-1.61/gui/statsdialog.cpp000066400000000000000000000262731217722632100170440ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include #include #include #include #include "project.h" #include "projectfile.h" #include "statsdialog.h" #include "checkstatistics.h" StatsDialog::StatsDialog(QWidget *parent) : QDialog(parent) { mUI.setupUi(this); connect(mUI.mCopyToClipboard, SIGNAL(pressed()), this, SLOT(copyToClipboard())); } void StatsDialog::setProject(const Project& project) { ProjectFile *projectFile = project.GetProjectFile(); if (projectFile) { mUI.mProject->setText(projectFile->GetRootPath()); mUI.mPaths->setText(projectFile->GetCheckPaths().join(";")); mUI.mIncludePaths->setText(projectFile->GetIncludeDirs().join(";")); mUI.mDefines->setText(projectFile->GetDefines().join(";")); } else { mUI.mProject->setText(""); mUI.mPaths->setText(""); mUI.mIncludePaths->setText(""); mUI.mDefines->setText(""); } } void StatsDialog::setPathSelected(const QString& path) { mUI.mPath->setText(path); } void StatsDialog::setNumberOfFilesScanned(int num) { mUI.mNumberOfFilesScanned->setText(QString::number(num)); } void StatsDialog::setScanDuration(double seconds) { // Factor the duration into units (days/hours/minutes/seconds) int secs = seconds; int days = secs / (24 * 60 * 60); secs -= days * (24 * 60 * 60); int hours = secs / (60 * 60); secs -= hours * (60 * 60); int mins = secs / 60; secs -= mins * 60; // Concatenate the two most significant units (e.g. "1 day and 3 hours") QStringList parts; if (days) parts << ((days == 1) ? tr("1 day") : tr("%1 days").arg(days)); if (hours) parts << ((hours == 1) ? tr("1 hour") : tr("%1 hours").arg(hours)); if (mins && parts.size() < 2) parts << ((mins == 1) ? tr("1 minute") : tr("%1 minutes").arg(mins)); if (secs && parts.size() < 2) parts << ((secs == 1) ? tr("1 second") : tr("%1 seconds").arg(secs)); // For durations < 1s, show the fraction of a second (e.g. "0.7 seconds") if (parts.isEmpty()) parts << tr("0.%1 seconds").arg(int(10.0 *(seconds - secs))); mUI.mScanDuration->setText(parts.join(tr(" and "))); } void StatsDialog::copyToClipboard() { QClipboard *clipboard = QApplication::clipboard(); if (clipboard) { const QString projSettings(tr("Project Settings")); const QString project(tr("Project")); const QString paths(tr("Paths")); const QString incPaths(tr("Include paths")); const QString defines(tr("Defines")); const QString prevScan(tr("Previous Scan")); const QString selPath(tr("Path selected")); const QString numFiles(tr("Number of files scanned")); const QString duration(tr("Scan duration")); const QString stats(tr("Statistics")); const QString errors(tr("Errors")); const QString warnings(tr("Warnings")); const QString style(tr("Style warnings")); const QString portability(tr("Portability warnings")); const QString performance(tr("Performance warnings")); const QString information(tr("Information messages")); // Plain text summary const QString settings = QString( "%1\n" "\t%2:\t%3\n" "\t%4:\t%5\n" "\t%6:\t%7\n" "\t%8:\t%9\n" ) .arg(projSettings) .arg(project) .arg(mUI.mProject->text()) .arg(paths) .arg(mUI.mPaths->text()) .arg(incPaths) .arg(mUI.mIncludePaths->text()) .arg(defines) .arg(mUI.mDefines->text()); const QString previous = QString( "%1\n" "\t%2:\t%3\n" "\t%4:\t%5\n" "\t%6:\t%7\n" ) .arg(prevScan) .arg(selPath) .arg(mUI.mPath->text()) .arg(numFiles) .arg(mUI.mNumberOfFilesScanned->text()) .arg(duration) .arg(mUI.mScanDuration->text()); const QString statistics = QString( "%1\n" "\t%2:\t%3\n" "\t%4:\t%5\n" "\t%6:\t%7\n" "\t%8:\t%9\n" "\t%10:\t%11\n" "\t%12:\t%13\n" ) .arg(stats) .arg(errors) .arg(mStatistics->GetCount(ShowTypes::ShowErrors)) .arg(warnings) .arg(mStatistics->GetCount(ShowTypes::ShowWarnings)) .arg(style) .arg(mStatistics->GetCount(ShowTypes::ShowStyle)) .arg(portability) .arg(mStatistics->GetCount(ShowTypes::ShowPortability)) .arg(performance) .arg(mStatistics->GetCount(ShowTypes::ShowPerformance)) .arg(information) .arg(mStatistics->GetCount(ShowTypes::ShowInformation)); const QString textSummary = settings + previous + statistics; // HTML summary const QString htmlSettings = QString( "

%1

\n" "\n" " \n" " \n" " \n" " \n" "
%2:%3
%4:%5
%6:%7
%8:%9
\n" ) .arg(projSettings) .arg(project) .arg(mUI.mProject->text()) .arg(paths) .arg(mUI.mPaths->text()) .arg(incPaths) .arg(mUI.mIncludePaths->text()) .arg(defines) .arg(mUI.mDefines->text()); const QString htmlPrevious = QString( "

%1

\n" "\n" " \n" " \n" " \n" "
%2:%3
%4:%5
%6:%7
\n" ) .arg(prevScan) .arg(selPath) .arg(mUI.mPath->text()) .arg(numFiles) .arg(mUI.mNumberOfFilesScanned->text()) .arg(duration) .arg(mUI.mScanDuration->text()); const QString htmlStatistics = QString( "

%1

\n" " %2:%3\n" " %4:%5\n" " %6:%7\n" " %8:%9\n" " %10:%11\n" " %12:%13\n" "\n" ) .arg(stats) .arg(errors) .arg(mStatistics->GetCount(ShowTypes::ShowErrors)) .arg(warnings) .arg(mStatistics->GetCount(ShowTypes::ShowWarnings)) .arg(style) .arg(mStatistics->GetCount(ShowTypes::ShowStyle)) .arg(portability) .arg(mStatistics->GetCount(ShowTypes::ShowPortability)) .arg(performance) .arg(mStatistics->GetCount(ShowTypes::ShowPerformance)) .arg(information) .arg(mStatistics->GetCount(ShowTypes::ShowInformation)); const QString htmlSummary = htmlSettings + htmlPrevious + htmlStatistics; QMimeData *mimeData = new QMimeData(); mimeData->setText(textSummary); mimeData->setHtml(htmlSummary); clipboard->setMimeData(mimeData); } } void StatsDialog::setStatistics(const CheckStatistics *stats) { mStatistics = const_cast(stats); mUI.mLblErrors->setText(QString("%1").arg(stats->GetCount(ShowTypes::ShowErrors))); mUI.mLblWarnings->setText(QString("%1").arg(stats->GetCount(ShowTypes::ShowWarnings))); mUI.mLblStyle->setText(QString("%1").arg(stats->GetCount(ShowTypes::ShowStyle))); mUI.mLblPortability->setText(QString("%1").arg(stats->GetCount(ShowTypes::ShowPortability))); mUI.mLblPerformance->setText(QString("%1").arg(stats->GetCount(ShowTypes::ShowPerformance))); mUI.mLblInformation->setText(QString("%1").arg(stats->GetCount(ShowTypes::ShowInformation))); } cppcheck-1.61/gui/statsdialog.h000066400000000000000000000035361217722632100165060ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #ifndef STATSDIALOG_H #define STATSDIALOG_H #include #include "ui_stats.h" class Project; class CheckStatistics; /// @addtogroup GUI /// @{ /** * @brief A dialog that shows project and scan statistics. * */ class StatsDialog : public QDialog { Q_OBJECT public: StatsDialog(QWidget *parent = 0); /** * @brief Sets the project to extract statistics from */ void setProject(const Project& project); /** * @brief Sets the string to display beside "Path Selected:" */ void setPathSelected(const QString& path); /** * @brief Sets the number to display beside "Number of Files Scanned:" */ void setNumberOfFilesScanned(int num); /** * @brief Sets the number of seconds to display beside "Scan Duration:" */ void setScanDuration(double seconds); /** * @brief Sets the numbers of different error/warnings found." */ void setStatistics(const CheckStatistics *stats); private slots: void copyToClipboard(); private: Ui::StatsDialog mUI; CheckStatistics *mStatistics; }; /// @} #endif // STATSDIALOG_H cppcheck-1.61/gui/test/000077500000000000000000000000001217722632100147675ustar00rootroot00000000000000cppcheck-1.61/gui/test/benchmark/000077500000000000000000000000001217722632100167215ustar00rootroot00000000000000cppcheck-1.61/gui/test/benchmark/benchmark.pro000066400000000000000000000000701217722632100213720ustar00rootroot00000000000000CONFIG += ordered TEMPLATE = subdirs SUBDIRS = simple cppcheck-1.61/gui/test/benchmark/common.pri000066400000000000000000000003311217722632100207220ustar00rootroot00000000000000CONFIG += qtestlib #DEPENDPATH += . .. INCLUDEPATH += . ../.. ../../../../lib LIBS += -L../../../../externals -lpcre INCLUDEPATH += ../../../externals BASEPATH = ../../../../lib/ include($$PWD/../../../lib/lib.pri) cppcheck-1.61/gui/test/benchmark/simple/000077500000000000000000000000001217722632100202125ustar00rootroot00000000000000cppcheck-1.61/gui/test/benchmark/simple/benchmarksimple.cpp000066400000000000000000000043301217722632100240620ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include #include #include #include #include #include "benchmarksimple.h" #include "tokenize.h" #include "token.h" #include "settings.h" #include "errorlogger.h" void BenchmarkSimple::tokenize() { QFile file(QString(SRCDIR) + "/../../data/benchmark/simple.cpp"); QByteArray data = file.readAll(); Settings settings; settings.debugwarnings = true; // tokenize.. Tokenizer tokenizer(&settings, this); std::istringstream istr(data.constData()); QBENCHMARK { tokenizer.tokenize(istr, "test.cpp"); } } void BenchmarkSimple::simplify() { QFile file(QString(SRCDIR) + "/../../data/benchmark/simple.cpp"); QByteArray data = file.readAll(); Settings settings; settings.debugwarnings = true; // tokenize.. Tokenizer tokenizer(&settings, this); std::istringstream istr(data.constData()); tokenizer.tokenize(istr, "test.cpp"); QBENCHMARK { tokenizer.simplifyTokenList(); } } void BenchmarkSimple::tokenizeAndSimplify() { QFile file(QString(SRCDIR) + "/../../data/benchmark/simple.cpp"); QByteArray data = file.readAll(); Settings settings; settings.debugwarnings = true; // tokenize.. Tokenizer tokenizer(&settings, this); std::istringstream istr(data.constData()); QBENCHMARK { tokenizer.tokenize(istr, "test.cpp"); tokenizer.simplifyTokenList(); } } QTEST_MAIN(BenchmarkSimple) cppcheck-1.61/gui/test/benchmark/simple/benchmarksimple.h000066400000000000000000000023371217722632100235340ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include #include "errorlogger.h" class BenchmarkSimple: public QObject, public ErrorLogger { Q_OBJECT private slots: void tokenize(); void simplify(); void tokenizeAndSimplify(); private: // Empty implementations of ErrorLogger methods. // We don't care about the output in the benchmark tests. void reportOut(const std::string & outmsg) { } void reportErr(const ErrorLogger::ErrorMessage &msg) { } }; cppcheck-1.61/gui/test/benchmark/simple/simple.pro000066400000000000000000000003711217722632100222260ustar00rootroot00000000000000TEMPLATE = app TARGET = benchmark-simple DEPENDPATH += . INCLUDEPATH += . OBJECTS_DIR = ../../build MOC_DIR = ../../build include(../common.pri) DEFINES += SRCDIR=\\\"$$PWD\\\" # tests SOURCES += benchmarksimple.cpp HEADERS += benchmarksimple.h cppcheck-1.61/gui/test/common.pri000066400000000000000000000012021217722632100167660ustar00rootroot00000000000000CONFIG += qtestlib #DEPENDPATH += . .. INCLUDEPATH += . ../.. ../../../lib LIBS += -L../../../externals -lpcre INCLUDEPATH += ../../externals BASEPATH = ../../../lib/ include($$PWD/../../lib/lib.pri) # GUI SOURCES += ../../erroritem.cpp \ ../../filelist.cpp \ ../../projectfile.cpp \ ../../report.cpp \ ../../translationhandler.cpp \ ../../xmlreport.cpp \ ../../xmlreportv1.cpp \ ../../xmlreportv2.cpp HEADERS += ../../erroritem.h \ ../../filelist.h \ ../../projectfile.h \ ../../report.h \ ../../translationhandler.h \ ../../xmlreport.h \ ../../xmlreportv1.h \ ../../xmlreportv2.h cppcheck-1.61/gui/test/data/000077500000000000000000000000001217722632100157005ustar00rootroot00000000000000cppcheck-1.61/gui/test/data/benchmark/000077500000000000000000000000001217722632100176325ustar00rootroot00000000000000cppcheck-1.61/gui/test/data/benchmark/simple.cpp000066400000000000000000004106071217722632100216370ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ //--------------------------------------------------------------------------- // Remove includes from the benchmark run // Included files aren't found anyway //#include "checkother.h" //#include "mathlib.h" //#include "symboldatabase.h" //#include // std::isupper //#include // fabs() //#include //--------------------------------------------------------------------------- // Register this check class (by creating a static instance of it) namespace { CheckOther instance; } //--------------------------------------------------------------------------- void CheckOther::checkIncrementBoolean() { if (!_settings->isEnabled("style")) return; for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { if (Token::Match(tok, "%var% ++")) { if (tok->varId()) { const Token *declTok = Token::findmatch(_tokenizer->tokens(), "bool %varid%", tok->varId()); if (declTok) incrementBooleanError(tok); } } } } void CheckOther::incrementBooleanError(const Token *tok) { reportError( tok, Severity::style, "incrementboolean", "The use of a variable of type bool with the ++ postfix operator is always true and deprecated by the C++ Standard.\n" "The operand of a postfix increment operator may be of type bool but it is deprecated by C++ Standard (Annex D-1) and the operand is always set to true\n" ); } //--------------------------------------------------------------------------- void CheckOther::clarifyCalculation() { if (!_settings->isEnabled("style")) return; for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { if (tok->strAt(1) == "?") { // condition const Token *cond = tok; if (cond->isName() || cond->isNumber()) cond = cond->previous(); else if (cond->str() == ")") cond = cond->link()->previous(); else continue; // calculation if (!cond->isArithmeticalOp()) continue; const std::string &op = cond->str(); cond = cond->previous(); // skip previous multiplications.. while (cond && cond->strAt(-1) == "*" && (cond->isName() || cond->isNumber())) cond = cond->tokAt(-2); if (!cond) continue; // first multiplication operand if (cond->str() == ")") { clarifyCalculationError(cond, op); } else if (cond->isName() || cond->isNumber()) { if (Token::Match(cond->previous(),("return|=|+|-|,|(|"+op).c_str())) clarifyCalculationError(cond, op); } } } } void CheckOther::clarifyCalculationError(const Token *tok, const std::string &op) { // suspicious calculation const std::string calc("'a" + op + "b?c:d'"); // recommended calculation #1 const std::string s1("'(a" + op + "b)?c:d'"); // recommended calculation #2 const std::string s2("'a" + op + "(b?c:d)'"); reportError(tok, Severity::style, "clarifyCalculation", "Clarify calculation precedence for " + op + " and ?\n" "Suspicious calculation. Please use parentheses to clarify the code. " "The code " + calc + " should be written as either " + s1 + " or " + s2 + "."); } // Clarify condition '(x = a < 0)' into '((x = a) < 0)' or '(x = (a < 0))' void CheckOther::clarifyCondition() { if (!_settings->isEnabled("style")) return; for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { if (Token::Match(tok, "( %var% =")) { for (const Token *tok2 = tok->tokAt(2); tok2; tok2 = tok2->next()) { if (tok2->str() == "(" || tok2->str() == "[") tok2 = tok2->link(); else if (Token::Match(tok2, "&&|%oror%|?|)")) break; else if (Token::Match(tok2, "<|<=|==|!=|>|>= %num% )")) { clarifyConditionError(tok); break; } } } } } void CheckOther::clarifyConditionError(const Token *tok) { reportError(tok, Severity::style, "clarifyCondition", "Suspicious condition (assignment+comparison), it can be clarified with parentheses"); } void CheckOther::warningOldStylePointerCast() { if (!_settings->isEnabled("style") || (_tokenizer->tokens() && _tokenizer->fileLine(_tokenizer->tokens()).find(".cpp") == std::string::npos)) return; for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { // Old style pointer casting.. if (!Token::Match(tok, "( const| %type% * ) %var%") && !Token::Match(tok, "( const| %type% * ) (| new")) continue; int addToIndex = 0; if (tok->tokAt(1)->str() == "const") addToIndex = 1; if (tok->tokAt(4 + addToIndex)->str() == "const") continue; // Is "type" a class? const std::string pattern("class " + tok->tokAt(1 + addToIndex)->str()); if (!Token::findmatch(_tokenizer->tokens(), pattern.c_str())) continue; cstyleCastError(tok); } } //--------------------------------------------------------------------------- // fflush(stdin) <- fflush only applies to output streams in ANSI C //--------------------------------------------------------------------------- void CheckOther::checkFflushOnInputStream() { const Token *tok = _tokenizer->tokens(); while (tok && ((tok = Token::findsimplematch(tok, "fflush ( stdin )")) != NULL)) { fflushOnInputStreamError(tok, tok->strAt(2)); tok = tok->tokAt(4); } } void CheckOther::checkSizeofForNumericParameter() { for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { if (Token::Match(tok, "sizeof ( %num% )") || Token::Match(tok, "sizeof ( - %num% )") || Token::Match(tok, "sizeof %num%") || Token::Match(tok, "sizeof - %num%") ) { sizeofForNumericParameterError(tok); } } } void CheckOther::checkSizeofForArrayParameter() { for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { if (Token::Match(tok, "sizeof ( %var% )") || Token::Match(tok, "sizeof %var%")) { int tokIdx = 1; if (tok->tokAt(tokIdx)->str() == "(") { ++tokIdx; } if (tok->tokAt(tokIdx)->varId() > 0) { const Token *declTok = Token::findmatch(_tokenizer->tokens(), "%varid%", tok->tokAt(tokIdx)->varId()); if (declTok) { if (Token::simpleMatch(declTok->next(), "[")) { declTok = declTok->next()->link(); // multidimensional array while (Token::simpleMatch(declTok->next(), "[")) { declTok = declTok->next()->link(); } if (!(Token::Match(declTok->next(), "= %str%")) && !(Token::simpleMatch(declTok->next(), "= {")) && !(Token::simpleMatch(declTok->next(), ";"))) { if (Token::simpleMatch(declTok->next(), ",")) { declTok = declTok->next(); while (!Token::simpleMatch(declTok, ";")) { if (Token::simpleMatch(declTok, ")")) { sizeofForArrayParameterError(tok); break; } if (Token::Match(declTok, "(|[|{")) { declTok = declTok->link(); } declTok = declTok->next(); } } } if (Token::simpleMatch(declTok->next(), ")")) { sizeofForArrayParameterError(tok); } } } } } } } //--------------------------------------------------------------------------- // switch (x) // { // case 2: // y = a; // <- this assignment is redundant // case 3: // y = b; // <- case 2 falls through and sets y twice // } //--------------------------------------------------------------------------- void CheckOther::checkRedundantAssignmentInSwitch() { const char switchPattern[] = "switch ( %any% ) { case"; const char breakPattern[] = "break|continue|return|exit|goto|throw"; const char functionPattern[] = "%var% ("; // Find the beginning of a switch. E.g.: // switch (var) { ... const Token *tok = Token::findmatch(_tokenizer->tokens(), switchPattern); while (tok) { // Check the contents of the switch statement std::map varsAssigned; int indentLevel = 0; for (const Token *tok2 = tok->tokAt(5); tok2; tok2 = tok2->next()) { if (tok2->str() == "{") { // Inside a conditional or loop. Don't mark variable accesses as being redundant. E.g.: // case 3: b = 1; // case 4: if (a) { b = 2; } // Doesn't make the b=1 redundant because it's conditional if (Token::Match(tok2->previous(), ")|else {") && tok2->link()) { const Token* endOfConditional = tok2->link(); for (const Token* tok3 = tok2; tok3 != endOfConditional; tok3 = tok3->next()) { if (tok3->varId() != 0) varsAssigned.erase(tok3->varId()); else if (Token::Match(tok3, functionPattern) || Token::Match(tok3, breakPattern)) varsAssigned.clear(); } tok2 = endOfConditional; } else ++ indentLevel; } else if (tok2->str() == "}") { -- indentLevel; // End of the switch block if (indentLevel < 0) break; } // Variable assignment. Report an error if it's assigned to twice before a break. E.g.: // case 3: b = 1; // <== redundant // case 4: b = 2; if (Token::Match(tok2->previous(), ";|{|}|: %var% = %any% ;") && tok2->varId() != 0) { std::map::iterator i = varsAssigned.find(tok2->varId()); if (i == varsAssigned.end()) varsAssigned[tok2->varId()] = tok2; else redundantAssignmentInSwitchError(i->second, i->second->str()); } // Not a simple assignment so there may be good reason if this variable is assigned to twice. E.g.: // case 3: b = 1; // case 4: b++; else if (tok2->varId() != 0) varsAssigned.erase(tok2->varId()); // Reset our record of assignments if there is a break or function call. E.g.: // case 3: b = 1; break; if (Token::Match(tok2, functionPattern) || Token::Match(tok2, breakPattern)) varsAssigned.clear(); } tok = Token::findmatch(tok->next(), switchPattern); } } void CheckOther::checkSwitchCaseFallThrough() { if (!(_settings->isEnabled("style") && _settings->experimental)) return; const char switchPattern[] = "switch ("; const char breakPattern[] = "break|continue|return|exit|goto|throw"; // Find the beginning of a switch. E.g.: // switch (var) { ... const Token *tok = Token::findmatch(_tokenizer->tokens(), switchPattern); while (tok) { // Check the contents of the switch statement std::stack > ifnest; std::stack loopnest; std::stack scopenest; bool justbreak = true; bool firstcase = true; for (const Token *tok2 = tok->tokAt(1)->link()->tokAt(2); tok2; tok2 = tok2->next()) { if (Token::simpleMatch(tok2, "if (")) { tok2 = tok2->tokAt(1)->link()->next(); if (tok2->link() == NULL) { std::ostringstream errmsg; errmsg << "unmatched if in switch: " << tok2->linenr(); reportError(_tokenizer->tokens(), Severity::debug, "debug", errmsg.str()); break; } ifnest.push(std::make_pair(tok2->link(), false)); justbreak = false; } else if (Token::simpleMatch(tok2, "while (")) { tok2 = tok2->tokAt(1)->link()->next(); // skip over "do { } while ( ) ;" case if (tok2->str() == "{") { if (tok2->link() == NULL) { std::ostringstream errmsg; errmsg << "unmatched while in switch: " << tok2->linenr(); reportError(_tokenizer->tokens(), Severity::debug, "debug", errmsg.str()); break; } loopnest.push(tok2->link()); } justbreak = false; } else if (Token::simpleMatch(tok2, "do {")) { tok2 = tok2->tokAt(1); if (tok2->link() == NULL) { std::ostringstream errmsg; errmsg << "unmatched do in switch: " << tok2->linenr(); reportError(_tokenizer->tokens(), Severity::debug, "debug", errmsg.str()); break; } loopnest.push(tok2->link()); justbreak = false; } else if (Token::simpleMatch(tok2, "for (")) { tok2 = tok2->tokAt(1)->link()->next(); if (tok2->link() == NULL) { std::ostringstream errmsg; errmsg << "unmatched for in switch: " << tok2->linenr(); reportError(_tokenizer->tokens(), Severity::debug, "debug", errmsg.str()); break; } loopnest.push(tok2->link()); justbreak = false; } else if (Token::Match(tok2, switchPattern)) { // skip over nested switch, we'll come to that soon tok2 = tok2->tokAt(1)->link()->next()->link(); } else if (Token::Match(tok2, breakPattern)) { if (loopnest.empty()) { justbreak = true; } tok2 = Token::findsimplematch(tok2, ";"); } else if (Token::Match(tok2, "case|default")) { if (!justbreak && !firstcase) { switchCaseFallThrough(tok2); } tok2 = Token::findsimplematch(tok2, ":"); justbreak = true; firstcase = false; } else if (tok2->str() == "{") { scopenest.push(tok2->link()); } else if (tok2->str() == "}") { if (!ifnest.empty() && tok2 == ifnest.top().first) { if (tok2->next()->str() == "else") { tok2 = tok2->tokAt(2); ifnest.pop(); if (tok2->link() == NULL) { std::ostringstream errmsg; errmsg << "unmatched if in switch: " << tok2->linenr(); reportError(_tokenizer->tokens(), Severity::debug, "debug", errmsg.str()); break; } ifnest.push(std::make_pair(tok2->link(), justbreak)); justbreak = false; } else { justbreak &= ifnest.top().second; ifnest.pop(); } } else if (!loopnest.empty() && tok2 == loopnest.top()) { loopnest.pop(); } else if (!scopenest.empty() && tok2 == scopenest.top()) { scopenest.pop(); } else { if (!ifnest.empty() || !loopnest.empty() || !scopenest.empty()) { std::ostringstream errmsg; errmsg << "unexpected end of switch: "; errmsg << "ifnest=" << ifnest.size(); if (!ifnest.empty()) errmsg << "," << ifnest.top().first->linenr(); errmsg << ", loopnest=" << loopnest.size(); if (!loopnest.empty()) errmsg << "," << loopnest.top()->linenr(); errmsg << ", scopenest=" << scopenest.size(); if (!scopenest.empty()) errmsg << "," << scopenest.top()->linenr(); reportError(_tokenizer->tokens(), Severity::debug, "debug", errmsg.str()); } // end of switch block break; } } else if (tok2->str() != ";") { justbreak = false; } } tok = Token::findmatch(tok->next(), switchPattern); } } //--------------------------------------------------------------------------- // int x = 1; // x = x; // <- redundant assignment to self // // int y = y; // <- redundant initialization to self //--------------------------------------------------------------------------- void CheckOther::checkSelfAssignment() { if (!_settings->isEnabled("style")) return; // POD variables.. std::set pod; for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { if (tok->isStandardType() && Token::Match(tok->tokAt(2), "[,);]") && tok->next()->varId()) pod.insert(tok->next()->varId()); } const char selfAssignmentPattern[] = "%var% = %var% ;|=|)"; const Token *tok = Token::findmatch(_tokenizer->tokens(), selfAssignmentPattern); while (tok) { if (Token::Match(tok->previous(), "[;{}]") && tok->varId() && tok->varId() == tok->tokAt(2)->varId() && pod.find(tok->varId()) != pod.end()) { selfAssignmentError(tok, tok->str()); } tok = Token::findmatch(tok->next(), selfAssignmentPattern); } } //--------------------------------------------------------------------------- // int a = 1; // assert(a = 2); // <- assert should not have a side-effect //--------------------------------------------------------------------------- void CheckOther::checkAssignmentInAssert() { if (!_settings->isEnabled("style")) return; const char assertPattern[] = "assert ( %any%"; const Token *tok = Token::findmatch(_tokenizer->tokens(), assertPattern); const Token *endTok = tok ? tok->next()->link() : NULL; while (tok && endTok) { const Token* varTok = Token::findmatch(tok->tokAt(2), "%var% --|++|+=|-=|*=|/=|&=|^=|=", endTok); if (varTok) { assignmentInAssertError(tok, varTok->str()); } else if (NULL != (varTok = Token::findmatch(tok->tokAt(2), "--|++ %var%", endTok))) { assignmentInAssertError(tok, varTok->strAt(1)); } tok = Token::findmatch(endTok->next(), assertPattern); endTok = tok ? tok->next()->link() : NULL; } } //--------------------------------------------------------------------------- // if ((x != 1) || (x != 3)) // <- always true // if ((x == 1) && (x == 3)) // <- always false // if ((x < 1) && (x > 3)) // <- always false // if ((x > 3) || (x < 10)) // <- always true //--------------------------------------------------------------------------- void CheckOther::checkIncorrectLogicOperator() { if (!_settings->isEnabled("style")) return; const char conditionPattern[] = "if|while ("; const Token *tok = Token::findmatch(_tokenizer->tokens(), conditionPattern); const Token *endTok = tok ? tok->next()->link() : NULL; while (tok && endTok) { // Find a pair of OR'd terms, with or without parentheses // e.g. if (x != 3 || x != 4) const Token *logicTok = NULL, *term1Tok = NULL, *term2Tok = NULL; const Token *op1Tok = NULL, *op2Tok = NULL, *op3Tok = NULL, *nextTok = NULL; if (NULL != (logicTok = Token::findmatch(tok, "( %any% !=|==|<|>|>=|<= %any% ) &&|%oror% ( %any% !=|==|<|>|>=|<= %any% ) %any%", endTok))) { term1Tok = logicTok->next(); term2Tok = logicTok->tokAt(7); op1Tok = logicTok->tokAt(2); op2Tok = logicTok->tokAt(5); op3Tok = logicTok->tokAt(8); nextTok = logicTok->tokAt(11); } else if (NULL != (logicTok = Token::findmatch(tok, "%any% !=|==|<|>|>=|<= %any% &&|%oror% %any% !=|==|<|>|>=|<= %any% %any%", endTok))) { term1Tok = logicTok; term2Tok = logicTok->tokAt(4); op1Tok = logicTok->tokAt(1); op2Tok = logicTok->tokAt(3); op3Tok = logicTok->tokAt(5); nextTok = logicTok->tokAt(7); } if (logicTok) { // Find the common variable and the two different-valued constants unsigned int variableTested = 0; std::string firstConstant, secondConstant; bool varFirst1, varFirst2; unsigned int varId; if (Token::Match(term1Tok, "%var% %any% %num%")) { varId = term1Tok->varId(); if (!varId) { tok = Token::findmatch(endTok->next(), conditionPattern); endTok = tok ? tok->next()->link() : NULL; continue; } varFirst1 = true; firstConstant = term1Tok->tokAt(2)->str(); } else if (Token::Match(term1Tok, "%num% %any% %var%")) { varId = term1Tok->tokAt(2)->varId(); if (!varId) { tok = Token::findmatch(endTok->next(), conditionPattern); endTok = tok ? tok->next()->link() : NULL; continue; } varFirst1 = false; firstConstant = term1Tok->str(); } else { tok = Token::findmatch(endTok->next(), conditionPattern); endTok = tok ? tok->next()->link() : NULL; continue; } if (Token::Match(term2Tok, "%var% %any% %num%")) { const unsigned int varId2 = term2Tok->varId(); if (!varId2 || varId != varId2) { tok = Token::findmatch(endTok->next(), conditionPattern); endTok = tok ? tok->next()->link() : NULL; continue; } varFirst2 = true; secondConstant = term2Tok->tokAt(2)->str(); variableTested = varId; } else if (Token::Match(term2Tok, "%num% %any% %var%")) { const unsigned int varId2 = term1Tok->tokAt(2)->varId(); if (!varId2 || varId != varId2) { tok = Token::findmatch(endTok->next(), conditionPattern); endTok = tok ? tok->next()->link() : NULL; continue; } varFirst2 = false; secondConstant = term2Tok->str(); variableTested = varId; } else { tok = Token::findmatch(endTok->next(), conditionPattern); endTok = tok ? tok->next()->link() : NULL; continue; } if (variableTested == 0 || firstConstant.empty() || secondConstant.empty()) { tok = Token::findmatch(endTok->next(), conditionPattern); endTok = tok ? tok->next()->link() : NULL; continue; } enum Position { First, Second, NA }; enum Relation { Equal, NotEqual, Less, LessEqual, More, MoreEqual }; struct Condition { const char *before; Position position1; const char *op1TokStr; const char *op2TokStr; Position position2; const char *op3TokStr; const char *after; Relation relation; bool state; } conditions[] = { { "!!&&", NA, "!=", "||", NA, "!=", "!!&&", NotEqual, true }, // (x != 1) || (x != 3) <- always true { "(", NA, "==", "&&", NA, "==", ")", NotEqual, false }, // (x == 1) && (x == 3) <- always false { "(", First, "<", "&&", First, ">", ")", LessEqual, false }, // (x < 1) && (x > 3) <- always false { "(", First, ">", "&&", First, "<", ")", MoreEqual, false }, // (x > 3) && (x < 1) <- always false { "(", Second, ">", "&&", First, ">", ")", LessEqual, false }, // (1 > x) && (x > 3) <- always false { "(", First, ">", "&&", Second, ">", ")", MoreEqual, false }, // (x > 3) && (1 > x) <- always false { "(", First, "<", "&&", Second, "<", ")", LessEqual, false }, // (x < 1) && (3 < x) <- always false { "(", Second, "<", "&&", First, "<", ")", MoreEqual, false }, // (3 < x) && (x < 1) <- always false { "(", Second, ">", "&&", Second, "<", ")", LessEqual, false }, // (1 > x) && (3 < x) <- always false { "(", Second, "<", "&&", Second, ">", ")", MoreEqual, false }, // (3 < x) && (1 > x) <- always false { "(", First , ">|>=", "||", First, "<|<=", ")", Less, true }, // (x > 3) || (x < 10) <- always true { "(", First , "<|<=", "||", First, ">|>=", ")", More, true }, // (x < 10) || (x > 3) <- always true { "(", Second, "<|<=", "||", First, "<|<=", ")", Less, true }, // (3 < x) || (x < 10) <- always true { "(", First, "<|<=", "||", Second, "<|<=", ")", More, true }, // (x < 10) || (3 < x) <- always true { "(", First, ">|>=", "||", Second, ">|>=", ")", Less, true }, // (x > 3) || (10 > x) <- always true { "(", Second, ">|>=", "||", First, ">|>=", ")", More, true }, // (10 > x) || (x > 3) <- always true { "(", Second, "<|<=", "||", Second, ">|<=", ")", Less, true }, // (3 < x) || (10 > x) <- always true { "(", Second, ">|>=", "||", Second, "<|<=", ")", More, true }, // (10 > x) || (3 < x) <- always true }; for (unsigned int i = 0; i < (sizeof(conditions) / sizeof(conditions[0])); i++) { if (!((conditions[i].position1 == NA) || (((conditions[i].position1 == First) && varFirst1) || ((conditions[i].position1 == Second) && !varFirst1)))) continue; if (!((conditions[i].position2 == NA) || (((conditions[i].position2 == First) && varFirst2) || ((conditions[i].position2 == Second) && !varFirst2)))) continue; if (!Token::Match(op1Tok, conditions[i].op1TokStr)) continue; if (!Token::Match(op2Tok, conditions[i].op2TokStr)) continue; if (!Token::Match(op3Tok, conditions[i].op3TokStr)) continue; if (!Token::Match(logicTok->previous(), conditions[i].before)) continue; if (!Token::Match(nextTok, conditions[i].after)) continue; if ((conditions[i].relation == Equal && MathLib::isEqual(firstConstant, secondConstant)) || (conditions[i].relation == NotEqual && MathLib::isNotEqual(firstConstant, secondConstant)) || (conditions[i].relation == Less && MathLib::isLess(firstConstant, secondConstant)) || (conditions[i].relation == LessEqual && MathLib::isLessEqual(firstConstant, secondConstant)) || (conditions[i].relation == More && MathLib::isGreater(firstConstant, secondConstant)) || (conditions[i].relation == MoreEqual && MathLib::isGreaterEqual(firstConstant, secondConstant))) incorrectLogicOperatorError(term1Tok, conditions[i].state); } } tok = Token::findmatch(endTok->next(), conditionPattern); endTok = tok ? tok->next()->link() : NULL; } } //--------------------------------------------------------------------------- // try {} catch (std::exception err) {} <- Should be "std::exception& err" //--------------------------------------------------------------------------- void CheckOther::checkCatchExceptionByValue() { if (!_settings->isEnabled("style")) return; const char catchPattern[] = "} catch ("; const Token *tok = Token::findmatch(_tokenizer->tokens(), catchPattern); const Token *endTok = tok ? tok->tokAt(2)->link() : NULL; while (tok && endTok) { // Find a pass-by-value declaration in the catch(), excluding basic types // e.g. catch (std::exception err) const Token *tokType = Token::findmatch(tok, "%type% %var% )", endTok); if (tokType && !tokType->isStandardType()) { catchExceptionByValueError(tokType); } tok = Token::findmatch(endTok->next(), catchPattern); endTok = tok ? tok->tokAt(2)->link() : NULL; } } //--------------------------------------------------------------------------- // strtol(str, 0, radix) <- radix must be 0 or 2-36 //--------------------------------------------------------------------------- void CheckOther::invalidFunctionUsage() { // strtol and strtoul.. for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { if (!Token::Match(tok, "strtol|strtoul (")) continue; // Locate the third parameter of the function call.. int param = 1; for (const Token *tok2 = tok->tokAt(2); tok2; tok2 = tok2->next()) { if (tok2->str() == "(") tok2 = tok2->link(); else if (tok2->str() == ")") break; else if (tok2->str() == ",") { ++param; if (param == 3) { if (Token::Match(tok2, ", %num% )")) { const MathLib::bigint radix = MathLib::toLongNumber(tok2->next()->str()); if (!(radix == 0 || (radix >= 2 && radix <= 36))) { dangerousUsageStrtolError(tok2); } } break; } } } } // sprintf|snprintf overlapping data for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { // Get variable id of target buffer.. unsigned int varid = 0; if (Token::Match(tok, "sprintf|snprintf ( %var% ,")) varid = tok->tokAt(2)->varId(); else if (Token::Match(tok, "sprintf|snprintf ( %var% . %var% ,")) varid = tok->tokAt(4)->varId(); if (varid == 0) continue; // goto "," const Token *tok2 = tok->tokAt(3); while (tok2 && tok2->str() != ",") tok2 = tok2->next(); if (!tok2) continue; // is any source buffer overlapping the target buffer? int parlevel = 0; while ((tok2 = tok2->next()) != NULL) { if (tok2->str() == "(") ++parlevel; else if (tok2->str() == ")") { --parlevel; if (parlevel < 0) break; } else if (parlevel == 0 && Token::Match(tok2, ", %varid% [,)]", varid)) { sprintfOverlappingDataError(tok2->next(), tok2->next()->str()); break; } } } } //--------------------------------------------------------------------------- void CheckOther::invalidScanf() { if (!_settings->isEnabled("style")) return; for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { const Token *formatToken = 0; if (Token::Match(tok, "scanf|vscanf ( %str% ,")) formatToken = tok->tokAt(2); else if (Token::Match(tok, "fscanf|vfscanf ( %var% , %str% ,")) formatToken = tok->tokAt(4); else continue; bool format = false; // scan the string backwards, so we dont need to keep states const std::string &formatstr(formatToken->str()); for (unsigned int i = 1; i < formatstr.length(); i++) { if (formatstr[i] == '%') format = !format; else if (!format) continue; else if (std::isdigit(formatstr[i])) { format = false; } else if (std::isalpha(formatstr[i])) { invalidScanfError(tok); format = false; } } } } //--------------------------------------------------------------------------- // if (!x==3) <- Probably meant to be "x!=3" //--------------------------------------------------------------------------- void CheckOther::checkComparisonOfBoolWithInt() { if (!_settings->isEnabled("style")) return; for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { if (Token::Match(tok, "( ! %var% ==|!= %num% )")) { const Token *numTok = tok->tokAt(4); if (numTok && numTok->str() != "0") { comparisonOfBoolWithIntError(numTok, tok->strAt(2)); } } else if (Token::Match(tok, "( %num% ==|!= ! %var% )")) { const Token *numTok = tok->tokAt(1); if (numTok && numTok->str() != "0") { comparisonOfBoolWithIntError(numTok, tok->strAt(4)); } } } } //--------------------------------------------------------------------------- // switch (x) // { // case 2: // y = a; // break; // break; // <- Redundant break // case 3: // y = b; // } //--------------------------------------------------------------------------- void CheckOther::checkDuplicateBreak() { if (!_settings->isEnabled("style")) return; const char breakPattern[] = "break|continue ; break|continue ;"; // Find consecutive break or continue statements. e.g.: // break; break; const Token *tok = Token::findmatch(_tokenizer->tokens(), breakPattern); while (tok) { duplicateBreakError(tok); tok = Token::findmatch(tok->next(), breakPattern); } } void CheckOther::sizeofForNumericParameterError(const Token *tok) { reportError(tok, Severity::error, "sizeofwithnumericparameter", "Using sizeof with a numeric constant as function " "argument might not be what you intended.\n" "It is unusual to use constant value with sizeof. For example, this code:\n" " int f() {\n" " return sizeof(10);\n" " }\n" " returns 4 (in 32-bit systems) or 8 (in 64-bit systems) instead of 10." ); } void CheckOther::sizeofForArrayParameterError(const Token *tok) { reportError(tok, Severity::error, "sizeofwithsilentarraypointer", "Using sizeof for array given as function argument " "returns the size of pointer.\n" "Giving array as function parameter and then using sizeof-operator for the array " "argument. In this case the sizeof-operator returns the size of pointer (in the " "system). It does not return the size of the whole array in bytes as might be " "expected. For example, this code:\n" " int f(char a[100]) {\n" " return sizeof(a);\n" " }\n" " returns 4 (in 32-bit systems) or 8 (in 64-bit systems) instead of 100 (the " "size of the array in bytes)." ); } void CheckOther::invalidScanfError(const Token *tok) { reportError(tok, Severity::warning, "invalidscanf", "scanf without field width limits can crash with huge input data\n" "scanf without field width limits can crash with huge input data. To fix this error " "message add a field width specifier:\n" " %s => %20s\n" " %i => %3i\n" "\n" "Sample program that can crash:\n" "\n" "#include \n" "int main()\n" "{\n" " int a;\n" " scanf(\"%i\", &a);\n" " return 0;\n" "}\n" "\n" "To make it crash:\n" "perl -e 'print \"5\"x2100000' | ./a.out"); } //--------------------------------------------------------------------------- // Check for unsigned divisions //--------------------------------------------------------------------------- void CheckOther::checkUnsignedDivision() { if (!_settings->isEnabled("style")) return; // Check for "ivar / uvar" and "uvar / ivar" std::map varsign; for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { if (Token::Match(tok, "[{};(,] %type% %var% [;=,)]")) { if (tok->tokAt(1)->isUnsigned()) varsign[tok->tokAt(2)->varId()] = 'u'; else varsign[tok->tokAt(2)->varId()] = 's'; } else if (!Token::Match(tok, "[).]") && Token::Match(tok->next(), "%var% / %num%")) { if (tok->strAt(3)[0] == '-') { char sign1 = varsign[tok->tokAt(1)->varId()]; if (sign1 == 'u') { udivError(tok->next()); } } } else if (Token::Match(tok, "(|[|=|%op% %num% / %var%")) { if (tok->strAt(1)[0] == '-') { char sign2 = varsign[tok->tokAt(3)->varId()]; if (sign2 == 'u') { udivError(tok->next()); } } } } } //--------------------------------------------------------------------------- // memset(p, y, 0 /* bytes to fill */) <- 2nd and 3rd arguments inverted //--------------------------------------------------------------------------- void CheckOther::checkMemsetZeroBytes() { const Token *tok = _tokenizer->tokens(); while (tok && ((tok = Token::findmatch(tok, "memset ( %var% , %num% , 0 )")) != NULL)) { memsetZeroBytesError(tok, tok->strAt(2)); tok = tok->tokAt(8); } } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // Usage of function variables //--------------------------------------------------------------------------- /** * @brief This class is used to capture the control flow within a function. */ class ScopeInfo { public: ScopeInfo() : _token(NULL), _parent(NULL) { } ScopeInfo(const Token *token, ScopeInfo *parent_) : _token(token), _parent(parent_) { } ~ScopeInfo(); ScopeInfo *parent() { return _parent; } ScopeInfo *addChild(const Token *token); void remove(ScopeInfo *scope); private: const Token *_token; ScopeInfo *_parent; std::list _children; }; ScopeInfo::~ScopeInfo() { while (!_children.empty()) { delete *_children.begin(); _children.pop_front(); } } ScopeInfo *ScopeInfo::addChild(const Token *token) { ScopeInfo *temp = new ScopeInfo(token, this); _children.push_back(temp); return temp; } void ScopeInfo::remove(ScopeInfo *scope) { std::list::iterator it; for (it = _children.begin(); it != _children.end(); ++it) { if (*it == scope) { delete *it; _children.erase(it); break; } } } /** * @brief This class is used create a list of variables within a function. */ class Variables { public: enum VariableType { standard, array, pointer, reference, pointerArray, referenceArray, pointerPointer }; /** Store information about variable usage */ class VariableUsage { public: VariableUsage(const Token *name = 0, VariableType type = standard, ScopeInfo *scope = NULL, bool read = false, bool write = false, bool modified = false, bool allocateMemory = false) : _name(name), _type(type), _scope(scope), _read(read), _write(write), _modified(modified), _allocateMemory(allocateMemory) { } /** variable is used.. set both read+write */ void use() { _read = true; _write = true; } /** is variable unused? */ bool unused() const { return (_read == false && _write == false); } const Token *_name; VariableType _type; ScopeInfo *_scope; bool _read; bool _write; bool _modified; // read/modify/write bool _allocateMemory; std::set _aliases; std::set _assignments; }; typedef std::map VariableMap; void clear() { _varUsage.clear(); } VariableMap &varUsage() { return _varUsage; } void addVar(const Token *name, VariableType type, ScopeInfo *scope, bool write_); void allocateMemory(unsigned int varid); void read(unsigned int varid); void readAliases(unsigned int varid); void readAll(unsigned int varid); void write(unsigned int varid); void writeAliases(unsigned int varid); void writeAll(unsigned int varid); void use(unsigned int varid); void modified(unsigned int varid); VariableUsage *find(unsigned int varid); void alias(unsigned int varid1, unsigned int varid2, bool replace); void erase(unsigned int varid) { _varUsage.erase(varid); } void eraseAliases(unsigned int varid); void eraseAll(unsigned int varid); void clearAliases(unsigned int varid); private: VariableMap _varUsage; }; /** * Alias the 2 given variables. Either replace the existing aliases if * they exist or merge them. You would replace an existing alias when this * assignment is in the same scope as the previous assignment. You might * merge the aliases when this assignment is in a different scope from the * previous assignment depending on the relationship of the 2 scopes. */ void Variables::alias(unsigned int varid1, unsigned int varid2, bool replace) { VariableUsage *var1 = find(varid1); VariableUsage *var2 = find(varid2); // alias to self if (varid1 == varid2) { if (var1) var1->use(); return; } std::set::iterator i; if (replace) { // remove var1 from all aliases for (i = var1->_aliases.begin(); i != var1->_aliases.end(); ++i) { VariableUsage *temp = find(*i); if (temp) temp->_aliases.erase(var1->_name->varId()); } // remove all aliases from var1 var1->_aliases.clear(); } // var1 gets all var2s aliases for (i = var2->_aliases.begin(); i != var2->_aliases.end(); ++i) { if (*i != varid1) var1->_aliases.insert(*i); } // var2 is an alias of var1 var2->_aliases.insert(varid1); var1->_aliases.insert(varid2); if (var2->_type == Variables::pointer) var2->_read = true; } void Variables::clearAliases(unsigned int varid) { VariableUsage *usage = find(varid); if (usage) { // remove usage from all aliases std::set::iterator i; for (i = usage->_aliases.begin(); i != usage->_aliases.end(); ++i) { VariableUsage *temp = find(*i); if (temp) temp->_aliases.erase(usage->_name->varId()); } // remove all aliases from usage usage->_aliases.clear(); } } void Variables::eraseAliases(unsigned int varid) { VariableUsage *usage = find(varid); if (usage) { std::set::iterator aliases; for (aliases = usage->_aliases.begin(); aliases != usage->_aliases.end(); ++aliases) erase(*aliases); } } void Variables::eraseAll(unsigned int varid) { eraseAliases(varid); erase(varid); } void Variables::addVar(const Token *name, VariableType type, ScopeInfo *scope, bool write_) { if (name->varId() > 0) _varUsage.insert(std::make_pair(name->varId(), VariableUsage(name, type, scope, false, write_, false))); } void Variables::allocateMemory(unsigned int varid) { VariableUsage *usage = find(varid); if (usage) usage->_allocateMemory = true; } void Variables::read(unsigned int varid) { VariableUsage *usage = find(varid); if (usage) usage->_read = true; } void Variables::readAliases(unsigned int varid) { VariableUsage *usage = find(varid); if (usage) { std::set::iterator aliases; for (aliases = usage->_aliases.begin(); aliases != usage->_aliases.end(); ++aliases) { VariableUsage *aliased = find(*aliases); if (aliased) aliased->_read = true; } } } void Variables::readAll(unsigned int varid) { VariableUsage *usage = find(varid); if (usage) { usage->_read = true; std::set::iterator aliases; for (aliases = usage->_aliases.begin(); aliases != usage->_aliases.end(); ++aliases) { VariableUsage *aliased = find(*aliases); if (aliased) aliased->_read = true; } } } void Variables::write(unsigned int varid) { VariableUsage *usage = find(varid); if (usage) usage->_write = true; } void Variables::writeAliases(unsigned int varid) { VariableUsage *usage = find(varid); if (usage) { std::set::iterator aliases; for (aliases = usage->_aliases.begin(); aliases != usage->_aliases.end(); ++aliases) { VariableUsage *aliased = find(*aliases); if (aliased) aliased->_write = true; } } } void Variables::writeAll(unsigned int varid) { VariableUsage *usage = find(varid); if (usage) { usage->_write = true; std::set::iterator aliases; for (aliases = usage->_aliases.begin(); aliases != usage->_aliases.end(); ++aliases) { VariableUsage *aliased = find(*aliases); if (aliased) aliased->_write = true; } } } void Variables::use(unsigned int varid) { VariableUsage *usage = find(varid); if (usage) { usage->use(); std::set::iterator aliases; for (aliases = usage->_aliases.begin(); aliases != usage->_aliases.end(); ++aliases) { VariableUsage *aliased = find(*aliases); if (aliased) aliased->use(); } } } void Variables::modified(unsigned int varid) { VariableUsage *usage = find(varid); if (usage) { usage->_modified = true; std::set::iterator aliases; for (aliases = usage->_aliases.begin(); aliases != usage->_aliases.end(); ++aliases) { VariableUsage *aliased = find(*aliases); if (aliased) aliased->_modified = true; } } } Variables::VariableUsage *Variables::find(unsigned int varid) { if (varid) { VariableMap::iterator i = _varUsage.find(varid); if (i != _varUsage.end()) return &i->second; } return 0; } static int doAssignment(Variables &variables, const Token *tok, bool dereference, ScopeInfo *scope) { int next = 0; // a = a + b; if (Token::Match(tok, "%var% = %var% !!;") && tok->str() == tok->strAt(2)) { return 2; } // check for aliased variable const unsigned int varid1 = tok->varId(); Variables::VariableUsage *var1 = variables.find(varid1); if (var1) { Variables::VariableUsage *var2 = 0; int start = 1; // search for '=' while (tok->tokAt(start)->str() != "=") start++; start++; if (Token::Match(tok->tokAt(start), "&| %var%") || Token::Match(tok->tokAt(start), "( const| struct|union| %type% *| ) &| %var%") || Token::Match(tok->tokAt(start), "( const| struct|union| %type% *| ) ( &| %var%") || Token::Match(tok->tokAt(start), "%any% < const| struct|union| %type% *| > ( &| %var%")) { unsigned char offset = 0; unsigned int varid2; bool addressOf = false; if (Token::Match(tok->tokAt(start), "%var% .")) variables.use(tok->tokAt(start)->varId()); // use = read + write // check for C style cast if (tok->tokAt(start)->str() == "(") { if (tok->tokAt(start + 1)->str() == "const") offset++; if (Token::Match(tok->tokAt(start + 1 + offset), "struct|union")) offset++; if (tok->tokAt(start + 2 + offset)->str() == "*") offset++; if (tok->tokAt(start + 3 + offset)->str() == "&") { addressOf = true; next = start + 4 + offset; } else if (tok->tokAt(start + 3 + offset)->str() == "(") { if (tok->tokAt(start + 4 + offset)->str() == "&") { addressOf = true; next = start + 5 + offset; } else next = start + 4 + offset; } else next = start + 3 + offset; } // check for C++ style cast else if (tok->tokAt(start)->str().find("cast") != std::string::npos && tok->tokAt(start + 1)->str() == "<") { if (tok->tokAt(start + 2)->str() == "const") offset++; if (Token::Match(tok->tokAt(start + 2 + offset), "struct|union")) offset++; if (tok->tokAt(start + 3 + offset)->str() == "*") offset++; if (tok->tokAt(start + 5 + offset)->str() == "&") { addressOf = true; next = start + 6 + offset; } else next = start + 5 + offset; } // check for var ? ... else if (Token::Match(tok->tokAt(start), "%var% ?")) { next = start; } // no cast else { if (tok->tokAt(start)->str() == "&") { addressOf = true; next = start + 1; } else if (tok->tokAt(start)->str() == "new") return 0; else next = start; } // check if variable is local varid2 = tok->tokAt(next)->varId(); var2 = variables.find(varid2); if (var2) { // local variable (alias or read it) if (var1->_type == Variables::pointer) { if (dereference) variables.read(varid2); else { if (addressOf || var2->_type == Variables::array || var2->_type == Variables::pointer) { bool replace = true; // check if variable declared in same scope if (scope == var1->_scope) replace = true; // not in same scope as declaration else { std::set::iterator assignment; // check for an assignment in this scope assignment = var1->_assignments.find(scope); // no other assignment in this scope if (assignment == var1->_assignments.end()) { // nothing to replace if (var1->_assignments.empty()) replace = false; // this variable has previous assignments else { /** * @todo determine if existing aliases should be replaced or merged */ replace = false; } } // assignment in this scope else { // replace when only one other assignment if (var1->_assignments.size() == 1) replace = true; // otherwise, merge them else replace = false; } } variables.alias(varid1, varid2, replace); } else if (tok->tokAt(next + 1)->str() == "?") { if (var2->_type == Variables::reference) variables.readAliases(varid2); else variables.read(varid2); } } } else if (var1->_type == Variables::reference) { variables.alias(varid1, varid2, true); } else { if (var2->_type == Variables::pointer && tok->tokAt(next + 1)->str() == "[") variables.readAliases(varid2); variables.read(varid2); } } else { // not a local variable (or an unsupported local variable) if (var1->_type == Variables::pointer && !dereference) { // check if variable declaration is in this scope if (var1->_scope == scope) variables.clearAliases(varid1); else { std::set::iterator assignment; // check for an assignment in this scope assignment = var1->_assignments.find(scope); // no other assignment in this scope if (assignment == var1->_assignments.end()) { /** * @todo determine if existing aliases should be discarded */ } // this assignment replaces the last assignment in this scope else { // aliased variables in a larger scope are not supported // remove all aliases variables.clearAliases(varid1); } } } } } var1->_assignments.insert(scope); } // check for alias to struct member // char c[10]; a.b = c; else if (Token::Match(tok->tokAt(-2), "%var% .")) { if (Token::Match(tok->tokAt(2), "%var%")) { unsigned int varid2 = tok->tokAt(2)->varId(); Variables::VariableUsage *var2 = variables.find(varid2); // struct member aliased to local variable if (var2 && (var2->_type == Variables::array || var2->_type == Variables::pointer)) { // erase aliased variable and all variables that alias it // to prevent false positives variables.eraseAll(varid2); } } } return next; } static bool nextIsStandardType(const Token *tok) { tok = tok->next(); if (tok->str() == "static") tok = tok->next(); return tok->isStandardType(); } static bool nextIsStandardTypeOrVoid(const Token *tok) { tok = tok->next(); if (tok->str() == "static") tok = tok->next(); if (tok->str() == "const") tok = tok->next(); return tok->isStandardType() || tok->str() == "void"; } bool CheckOther::isRecordTypeWithoutSideEffects(const Token *tok) { const Variable * var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(tok->varId()); // a type that has no side effects (no constructors and no members with constructors) /** @todo false negative: check base class for side effects */ /** @todo false negative: check constructors for side effects */ if (var && var->type() && var->type()->numConstructors == 0 && (var->type()->varlist.empty() || var->type()->needInitialization == Scope::True) && var->type()->derivedFrom.empty()) return true; return false; } void CheckOther::functionVariableUsage() { if (!_settings->isEnabled("style")) return; // Parse all executing scopes.. const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase(); std::list::const_iterator scope; for (scope = symbolDatabase->scopeList.begin(); scope != symbolDatabase->scopeList.end(); ++scope) { // only check functions if (scope->type != Scope::eFunction) continue; // First token for the current scope.. const Token *const tok1 = scope->classStart; // varId, usage {read, write, modified} Variables variables; // scopes ScopeInfo scopes; ScopeInfo *info = &scopes; unsigned int indentlevel = 0; for (const Token *tok = tok1; tok; tok = tok->next()) { if (tok->str() == "{") { // replace the head node when found if (indentlevel == 0) scopes = ScopeInfo(tok, NULL); // add the new scope else info = info->addChild(tok); ++indentlevel; } else if (tok->str() == "}") { --indentlevel; info = info->parent(); if (indentlevel == 0) break; } else if (Token::Match(tok, "struct|union|class {") || Token::Match(tok, "struct|union|class %type% {|:")) { while (tok->str() != "{") tok = tok->next(); tok = tok->link(); if (! tok) break; } if (Token::Match(tok, "[;{}] asm ( ) ;")) { variables.clear(); break; } // standard type declaration with possible initialization // int i; int j = 0; static int k; if (Token::Match(tok, "[;{}] static| %type% %var% ;|=") && !Token::Match(tok->next(), "return|throw")) { tok = tok->next(); const bool isStatic = tok->str() == "static"; if (isStatic) tok = tok->next(); if (tok->isStandardType() || isRecordTypeWithoutSideEffects(tok->next())) { variables.addVar(tok->next(), Variables::standard, info, tok->tokAt(2)->str() == "=" || isStatic); } tok = tok->next(); } // standard const type declaration // const int i = x; else if (Token::Match(tok, "[;{}] const %type% %var% =")) { tok = tok->next()->next(); if (tok->isStandardType() || isRecordTypeWithoutSideEffects(tok->next())) variables.addVar(tok->next(), Variables::standard, info, true); tok = tok->next(); } // std::string declaration with possible initialization // std::string s; std::string s = "string"; else if (Token::Match(tok, "[;{}] static| std :: string %var% ;|=")) { tok = tok->next(); const bool isStatic = tok->str() == "static"; if (isStatic) tok = tok->next(); tok = tok->tokAt(3); variables.addVar(tok, Variables::standard, info, tok->next()->str() == "=" || isStatic); } // standard struct type declaration with possible initialization // struct S s; struct S s = { 0 }; static struct S s; else if (Token::Match(tok, "[;{}] static| struct %type% %var% ;|=") && (isRecordTypeWithoutSideEffects(tok->strAt(1) == "static" ? tok->tokAt(4) : tok->tokAt(3)))) { tok = tok->next(); bool isStatic = tok->str() == "static"; if (isStatic) tok = tok->next(); tok = tok->next(); variables.addVar(tok->next(), Variables::standard, info, tok->tokAt(2)->str() == "=" || isStatic); tok = tok->next(); } // standard type declaration and initialization using constructor // int i(0); static int j(0); else if (Token::Match(tok, "[;{}] static| %type% %var% ( %any% ) ;") && nextIsStandardType(tok)) { tok = tok->next(); if (tok->str() == "static") tok = tok->next(); variables.addVar(tok->next(), Variables::standard, info, true); // check if a local variable is used to initialize this variable if (tok->tokAt(3)->varId() > 0) variables.readAll(tok->tokAt(3)->varId()); tok = tok->tokAt(4); } // standard type declaration of array of with possible initialization // int i[10]; int j[2] = { 0, 1 }; static int k[2] = { 2, 3 }; else if (Token::Match(tok, "[;{}] static| const| %type% *| %var% [ %any% ] ;|=") && nextIsStandardType(tok)) { tok = tok->next(); const bool isStatic = tok->str() == "static"; if (isStatic) tok = tok->next(); if (tok->str() == "const") tok = tok->next(); if (tok->str() != "return" && tok->str() != "throw") { bool isPointer = bool(tok->strAt(1) == "*"); const Token * const nametok = tok->tokAt(isPointer ? 2 : 1); variables.addVar(nametok, isPointer ? Variables::pointerArray : Variables::array, info, nametok->tokAt(4)->str() == "=" || isStatic); // check for reading array size from local variable if (nametok->tokAt(2)->varId() != 0) variables.read(nametok->tokAt(2)->varId()); // look at initializers if (Token::simpleMatch(nametok->tokAt(4), "= {")) { tok = nametok->tokAt(6); while (tok->str() != "}") { if (Token::Match(tok, "%var%")) variables.read(tok->varId()); tok = tok->next(); } } else tok = nametok->tokAt(3); } } // pointer or reference declaration with possible initialization // int * i; int * j = 0; static int * k = 0; else if (Token::Match(tok, "[;{}] static| const| %type% *|& %var% ;|=")) { tok = tok->next(); const bool isStatic = tok->str() == "static"; if (isStatic) tok = tok->next(); if (tok->str() == "const") tok = tok->next(); if (tok->strAt(1) == "::") tok = tok->tokAt(2); if (tok->str() != "return" && tok->str() != "throw") { Variables::VariableType type; if (tok->next()->str() == "*") type = Variables::pointer; else type = Variables::reference; bool written = tok->tokAt(3)->str() == "="; variables.addVar(tok->tokAt(2), type, info, written || isStatic); int offset = 0; // check for assignment if (written) offset = doAssignment(variables, tok->tokAt(2), false, info); tok = tok->tokAt(2 + offset); } } // pointer to pointer declaration with possible initialization // int ** i; int ** j = 0; static int ** k = 0; else if (Token::Match(tok, "[;{}] static| const| %type% * * %var% ;|=")) { tok = tok->next(); const bool isStatic = tok->str() == "static"; if (isStatic) tok = tok->next(); if (tok->str() == "const") tok = tok->next(); if (tok->str() != "return") { bool written = tok->tokAt(4)->str() == "="; variables.addVar(tok->tokAt(3), Variables::pointerPointer, info, written || isStatic); int offset = 0; // check for assignment if (written) offset = doAssignment(variables, tok->tokAt(3), false, info); tok = tok->tokAt(3 + offset); } } // pointer or reference of struct or union declaration with possible initialization // struct s * i; struct s * j = 0; static struct s * k = 0; else if (Token::Match(tok, "[;{}] static| const| struct|union %type% *|& %var% ;|=")) { Variables::VariableType type; tok = tok->next(); const bool isStatic = tok->str() == "static"; if (isStatic) tok = tok->next(); if (tok->str() == "const") tok = tok->next(); if (tok->strAt(2) == "*") type = Variables::pointer; else type = Variables::reference; const bool written = tok->strAt(4) == "="; variables.addVar(tok->tokAt(3), type, info, written || isStatic); int offset = 0; // check for assignment if (written) offset = doAssignment(variables, tok->tokAt(3), false, info); tok = tok->tokAt(3 + offset); } // pointer or reference declaration with initialization using constructor // int * i(j); int * k(i); static int * l(i); else if (Token::Match(tok, "[;{}] static| const| %type% &|* %var% ( %any% ) ;") && nextIsStandardTypeOrVoid(tok)) { Variables::VariableType type; tok = tok->next(); if (tok->str() == "static") tok = tok->next(); if (tok->str() == "const") tok = tok->next(); if (tok->next()->str() == "*") type = Variables::pointer; else type = Variables::reference; unsigned int varid = 0; // check for aliased variable if (Token::Match(tok->tokAt(4), "%var%")) varid = tok->tokAt(4)->varId(); variables.addVar(tok->tokAt(2), type, info, true); // check if a local variable is used to initialize this variable if (varid > 0) { Variables::VariableUsage *var = variables.find(varid); if (type == Variables::pointer) { variables.use(tok->tokAt(4)->varId()); if (var && (var->_type == Variables::array || var->_type == Variables::pointer)) var->_aliases.insert(tok->varId()); } else { variables.readAll(tok->tokAt(4)->varId()); if (var) var->_aliases.insert(tok->varId()); } } tok = tok->tokAt(5); } // array of pointer or reference declaration with possible initialization // int * p[10]; int * q[10] = { 0 }; static int * * r[10] = { 0 }; else if (Token::Match(tok, "[;{}] static| const| %type% *|& %var% [ %any% ] ;|=")) { tok = tok->next(); const bool isStatic = tok->str() == "static"; if (isStatic) tok = tok->next(); if (tok->str() == "const") tok = tok->next(); if (tok->str() != "return") { variables.addVar(tok->tokAt(2), tok->next()->str() == "*" ? Variables::pointerArray : Variables::referenceArray, info, tok->tokAt(6)->str() == "=" || isStatic); // check for reading array size from local variable if (tok->tokAt(4)->varId() != 0) variables.read(tok->tokAt(4)->varId()); tok = tok->tokAt(5); } } // array of pointer or reference of struct or union declaration with possible initialization // struct S * p[10]; struct T * q[10] = { 0 }; static struct S * r[10] = { 0 }; else if (Token::Match(tok, "[;{}] static| const| struct|union %type% *|& %var% [ %any% ] ;|=")) { tok = tok->next(); const bool isStatic = tok->str() == "static"; if (isStatic) tok = tok->next(); if (tok->str() == "const") tok = tok->next(); variables.addVar(tok->tokAt(3), tok->tokAt(2)->str() == "*" ? Variables::pointerArray : Variables::referenceArray, info, tok->tokAt(7)->str() == "=" || isStatic); // check for reading array size from local variable if (tok->tokAt(5)->varId() != 0) variables.read(tok->tokAt(5)->varId()); tok = tok->tokAt(6); } // Freeing memory (not considered "using" the pointer if it was also allocated in this function) else if (Token::Match(tok, "free|g_free|kfree|vfree ( %var% )") || Token::Match(tok, "delete %var% ;") || Token::Match(tok, "delete [ ] %var% ;")) { unsigned int varid = 0; if (tok->str() != "delete") { varid = tok->tokAt(2)->varId(); tok = tok->tokAt(3); } else if (tok->strAt(1) == "[") { varid = tok->tokAt(3)->varId(); tok = tok->tokAt(4); } else { varid = tok->next()->varId(); tok = tok->tokAt(2); } Variables::VariableUsage *var = variables.find(varid); if (var && !var->_allocateMemory) { variables.readAll(varid); } } else if (Token::Match(tok, "return|throw %var%")) variables.readAll(tok->next()->varId()); // assignment else if (Token::Match(tok, "*| (| ++|--| %var% ++|--| )| =") || Token::Match(tok, "*| ( const| %type% *| ) %var% =")) { bool dereference = false; bool pre = false; bool post = false; if (tok->str() == "*") { dereference = true; tok = tok->next(); } if (Token::Match(tok, "( const| %type% *| ) %var% =")) tok = tok->link()->next(); else if (tok->str() == "(") tok = tok->next(); if (Token::Match(tok, "++|--")) { pre = true; tok = tok->next(); } if (Token::Match(tok->next(), "++|--")) post = true; const unsigned int varid1 = tok->varId(); const Token *start = tok; tok = tok->tokAt(doAssignment(variables, tok, dereference, info)); if (pre || post) variables.use(varid1); if (dereference) { Variables::VariableUsage *var = variables.find(varid1); if (var && var->_type == Variables::array) variables.write(varid1); variables.writeAliases(varid1); variables.read(varid1); } else { Variables::VariableUsage *var = variables.find(varid1); if (var && var->_type == Variables::reference) { variables.writeAliases(varid1); variables.read(varid1); } // Consider allocating memory separately because allocating/freeing alone does not constitute using the variable else if (var && var->_type == Variables::pointer && Token::Match(start, "%var% = new|malloc|calloc|g_malloc|kmalloc|vmalloc")) { bool allocate = true; if (start->strAt(2) == "new") { // is it a user defined type? if (!start->tokAt(3)->isStandardType()) { if (!isRecordTypeWithoutSideEffects(start)) allocate = false; } } if (allocate) variables.allocateMemory(varid1); else variables.write(varid1); } else if (varid1 && Token::Match(tok, "%varid% .", varid1)) { variables.use(varid1); } else { variables.write(varid1); } Variables::VariableUsage *var2 = variables.find(tok->varId()); if (var2) { if (var2->_type == Variables::reference) { variables.writeAliases(tok->varId()); variables.read(tok->varId()); } else if (tok->varId() != varid1 && Token::Match(tok, "%var% .")) variables.read(tok->varId()); else if (tok->varId() != varid1 && var2->_type == Variables::standard && tok->strAt(-1) != "&") variables.use(tok->varId()); } } const Token *equal = tok->next(); if (Token::Match(tok->next(), "[ %any% ]")) equal = tok->tokAt(4); // checked for chained assignments if (tok != start && equal->str() == "=") { Variables::VariableUsage *var = variables.find(tok->varId()); if (var && var->_type != Variables::reference) var->_read = true; tok = tok->previous(); } } // assignment else if (Token::Match(tok, "%var% [") && Token::simpleMatch(tok->next()->link(), "] =")) { unsigned int varid = tok->varId(); const Variables::VariableUsage *var = variables.find(varid); if (var) { // Consider allocating memory separately because allocating/freeing alone does not constitute using the variable if (var->_type == Variables::pointer && Token::Match(tok->next()->link(), "] = new|malloc|calloc|g_malloc|kmalloc|vmalloc")) { variables.allocateMemory(varid); } else if (var->_type == Variables::pointer || var->_type == Variables::reference) { variables.read(varid); variables.writeAliases(varid); } else variables.writeAll(varid); } } else if (Token::Match(tok, ">>|& %var%")) variables.use(tok->next()->varId()); // use = read + write else if (Token::Match(tok, "[;{}] %var% >>")) variables.use(tok->next()->varId()); // use = read + write // function parameter else if (Token::Match(tok, "[(,] %var% [")) variables.use(tok->next()->varId()); // use = read + write else if (Token::Match(tok, "[(,] %var% [,)]") && tok->previous()->str() != "*") variables.use(tok->next()->varId()); // use = read + write else if (Token::Match(tok, "[(,] (") && Token::Match(tok->next()->link(), ") %var% [,)]")) variables.use(tok->next()->link()->next()->varId()); // use = read + write // function else if (Token::Match(tok, "%var% (")) { variables.read(tok->varId()); if (Token::Match(tok->tokAt(2), "%var% =")) variables.read(tok->tokAt(2)->varId()); } else if (Token::Match(tok, "[{,] %var% [,}]")) variables.read(tok->next()->varId()); else if (Token::Match(tok, "%var% .")) variables.use(tok->varId()); // use = read + write else if ((Token::Match(tok, "[(=&!]") || tok->isExtendedOp()) && (Token::Match(tok->next(), "%var%") && !Token::Match(tok->next(), "true|false|new"))) variables.readAll(tok->next()->varId()); else if (Token::Match(tok, "%var%") && (tok->next()->str() == ")" || tok->next()->isExtendedOp())) variables.readAll(tok->varId()); else if (Token::Match(tok, "; %var% ;")) variables.readAll(tok->next()->varId()); if (Token::Match(tok, "++|-- %var%")) { if (tok->strAt(-1) != ";") variables.use(tok->next()->varId()); else variables.modified(tok->next()->varId()); } else if (Token::Match(tok, "%var% ++|--")) { if (tok->strAt(-1) != ";") variables.use(tok->varId()); else variables.modified(tok->varId()); } else if (tok->isAssignmentOp()) { for (const Token *tok2 = tok->next(); tok2 && tok2->str() != ";"; tok2 = tok2->next()) { if (tok2->varId()) { variables.read(tok2->varId()); if (tok2->next()->isAssignmentOp()) variables.write(tok2->varId()); } } } } // Check usage of all variables in the current scope.. Variables::VariableMap::const_iterator it; for (it = variables.varUsage().begin(); it != variables.varUsage().end(); ++it) { const Variables::VariableUsage &usage = it->second; const std::string &varname = usage._name->str(); // variable has been marked as unused so ignore it if (usage._name->isUnused()) continue; // skip things that are only partially implemented to prevent false positives if (usage._type == Variables::pointerPointer || usage._type == Variables::pointerArray || usage._type == Variables::referenceArray) continue; // variable has had memory allocated for it, but hasn't done // anything with that memory other than, perhaps, freeing it if (usage.unused() && !usage._modified && usage._allocateMemory) allocatedButUnusedVariableError(usage._name, varname); // variable has not been written, read, or modified else if (usage.unused() && !usage._modified) unusedVariableError(usage._name, varname); // variable has not been written but has been modified else if (usage._modified & !usage._write) unassignedVariableError(usage._name, varname); // variable has been written but not read else if (!usage._read && !usage._modified) unreadVariableError(usage._name, varname); // variable has been read but not written else if (!usage._write && !usage._allocateMemory) unassignedVariableError(usage._name, varname); } } } void CheckOther::unusedVariableError(const Token *tok, const std::string &varname) { reportError(tok, Severity::style, "unusedVariable", "Unused variable: " + varname); } void CheckOther::allocatedButUnusedVariableError(const Token *tok, const std::string &varname) { reportError(tok, Severity::style, "unusedAllocatedMemory", "Variable '" + varname + "' is allocated memory that is never used"); } void CheckOther::unreadVariableError(const Token *tok, const std::string &varname) { reportError(tok, Severity::style, "unreadVariable", "Variable '" + varname + "' is assigned a value that is never used"); } void CheckOther::unassignedVariableError(const Token *tok, const std::string &varname) { reportError(tok, Severity::style, "unassignedVariable", "Variable '" + varname + "' is not assigned a value"); } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // Check scope of variables.. //--------------------------------------------------------------------------- void CheckOther::checkVariableScope() { if (!_settings->isEnabled("information")) return; const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase(); std::list::const_iterator scope; for (scope = symbolDatabase->scopeList.begin(); scope != symbolDatabase->scopeList.end(); ++scope) { // only check functions if (scope->type != Scope::eFunction) continue; // Walk through all tokens.. int indentlevel = 0; for (const Token *tok = scope->classStart; tok; tok = tok->next()) { // Skip function local class and struct declarations.. if ((tok->str() == "class") || (tok->str() == "struct") || (tok->str() == "union")) { for (const Token *tok2 = tok; tok2; tok2 = tok2->next()) { if (tok2->str() == "{") { tok = tok2->link(); break; } if (Token::Match(tok2, "[,);]")) { break; } } if (! tok) break; } else if (tok->str() == "{") { ++indentlevel; } else if (tok->str() == "}") { --indentlevel; if (indentlevel == 0) break; } if (indentlevel > 0 && Token::Match(tok, "[{};]")) { // First token of statement.. const Token *tok1 = tok->next(); if (! tok1) continue; if ((tok1->str() == "return") || (tok1->str() == "throw") || (tok1->str() == "delete") || (tok1->str() == "goto") || (tok1->str() == "else")) continue; // Variable declaration? if (Token::Match(tok1, "%type% %var% ; %var% = %num% ;")) { // Tokenizer modify "int i = 0;" to "int i; i = 0;", // so to handle this situation we just skip // initialization (see ticket #272). const unsigned int firstVarId = tok1->next()->varId(); const unsigned int secondVarId = tok1->tokAt(3)->varId(); if (firstVarId > 0 && firstVarId == secondVarId) { lookupVar(tok1->tokAt(6), tok1->strAt(1)); } } else if (tok1->isStandardType() && Token::Match(tok1, "%type% %var% [;=]")) { lookupVar(tok1, tok1->strAt(1)); } } } } } //--------------------------------------------------------------------------- void CheckOther::lookupVar(const Token *tok1, const std::string &varname) { const Token *tok = tok1; // Skip the variable declaration.. while (tok && tok->str() != ";") tok = tok->next(); // Check if the variable is used in this indentlevel.. bool used1 = false; // used in one sub-scope -> reducable bool used2 = false; // used in more sub-scopes -> not reducable int indentlevel = 0; int parlevel = 0; bool for_or_while = false; // is sub-scope a "for/while/etc". anything that is not "if" while (tok) { if (tok->str() == "{") { if (tok->strAt(-1) == "=") { if (Token::findmatch(tok, varname.c_str(), tok->link())) { return; } tok = tok->link(); } else ++indentlevel; } else if (tok->str() == "}") { if (indentlevel == 0) break; --indentlevel; if (indentlevel == 0) { if (for_or_while && used2) return; used2 |= used1; used1 = false; } } else if (tok->str() == "(") { ++parlevel; } else if (tok->str() == ")") { --parlevel; } // Bail out if references are used else if (Token::simpleMatch(tok, (std::string("& ") + varname).c_str())) { return; } else if (tok->str() == varname) { if (indentlevel == 0) return; used1 = true; if (for_or_while && !Token::simpleMatch(tok->next(), "=")) used2 = true; if (used1 && used2) return; } else if (indentlevel == 0) { // %unknown% ( %any% ) { // If %unknown% is anything except if, we assume // that it is a for or while loop or a macro hiding either one if (Token::simpleMatch(tok->next(), "(") && Token::simpleMatch(tok->next()->link(), ") {")) { if (tok->str() != "if") for_or_while = true; } else if (Token::simpleMatch(tok, "do {")) for_or_while = true; // possible unexpanded macro hiding for/while.. else if (tok->str() != "else" && Token::Match(tok->previous(), "[;{}] %type% {")) { for_or_while = true; } if (parlevel == 0 && (tok->str() == ";")) for_or_while = false; } tok = tok->next(); } // Warning if this variable: // * not used in this indentlevel // * used in lower indentlevel if (used1 || used2) variableScopeError(tok1, varname); } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // Check for constant function parameters //--------------------------------------------------------------------------- void CheckOther::checkConstantFunctionParameter() { if (!_settings->isEnabled("style")) return; const SymbolDatabase * const symbolDatabase = _tokenizer->getSymbolDatabase(); for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { // TODO: False negatives. This pattern only checks for string. // Investigate if there are other classes in the std // namespace and add them to the pattern. There are // streams for example (however it seems strange with // const stream parameter). if (Token::Match(tok, "[,(] const std :: string %var% [,)]")) { passedByValueError(tok, tok->strAt(5)); } else if (Token::Match(tok, "[,(] const std :: %type% < %type% > %var% [,)]")) { passedByValueError(tok, tok->strAt(8)); } else if (Token::Match(tok, "[,(] const std :: %type% < std :: %type% > %var% [,)]")) { passedByValueError(tok, tok->strAt(10)); } else if (Token::Match(tok, "[,(] const std :: %type% < std :: %type% , std :: %type% > %var% [,)]")) { passedByValueError(tok, tok->strAt(14)); } else if (Token::Match(tok, "[,(] const std :: %type% < %type% , std :: %type% > %var% [,)]")) { passedByValueError(tok, tok->strAt(12)); } else if (Token::Match(tok, "[,(] const std :: %type% < std :: %type% , %type% > %var% [,)]")) { passedByValueError(tok, tok->strAt(12)); } else if (Token::Match(tok, "[,(] const std :: %type% < %type% , %type% > %var% [,)]")) { passedByValueError(tok, tok->strAt(10)); } else if (Token::Match(tok, "[,(] const %type% %var% [,)]")) { // Check if type is a struct or class. if (symbolDatabase->isClassOrStruct(tok->strAt(2))) { passedByValueError(tok, tok->strAt(3)); } } } } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // Check that all struct members are used //--------------------------------------------------------------------------- void CheckOther::checkStructMemberUsage() { if (!_settings->isEnabled("style")) return; std::string structname; for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { if (tok->fileIndex() != 0) continue; if (Token::Match(tok, "struct|union %type% {")) { structname.clear(); if (Token::simpleMatch(tok->previous(), "extern")) continue; if ((!tok->previous() || Token::simpleMatch(tok->previous(), ";")) && Token::Match(tok->tokAt(2)->link(), ("} ; " + tok->strAt(1) + " %var% ;").c_str())) continue; structname = tok->strAt(1); // Bail out if struct/union contain any functions for (const Token *tok2 = tok->tokAt(2); tok2; tok2 = tok2->next()) { if (tok2->str() == "(") { structname.clear(); break; } if (tok2->str() == "}") break; } // bail out if struct is inherited if (!structname.empty() && Token::findmatch(tok, (",|private|protected|public " + structname).c_str())) structname.clear(); // Bail out if some data is casted to struct.. const std::string s("( struct| " + tok->next()->str() + " * ) & %var% ["); if (Token::findmatch(tok, s.c_str())) structname.clear(); // Try to prevent false positives when struct members are not used directly. if (Token::findmatch(tok, (structname + " *").c_str())) structname.clear(); else if (Token::findmatch(tok, (structname + " %type% *").c_str())) structname = ""; } if (tok->str() == "}") structname.clear(); if (!structname.empty() && Token::Match(tok, "[{;]")) { // Declaring struct variable.. std::string varname; // declaring a POD variable? if (!tok->next()->isStandardType()) continue; if (Token::Match(tok->next(), "%type% %var% [;[]")) varname = tok->strAt(2); else if (Token::Match(tok->next(), "%type% %type% %var% [;[]")) varname = tok->strAt(3); else if (Token::Match(tok->next(), "%type% * %var% [;[]")) varname = tok->strAt(3); else if (Token::Match(tok->next(), "%type% %type% * %var% [;[]")) varname = tok->strAt(4); else continue; // Check if the struct variable is used anywhere in the file const std::string usagePattern(". " + varname); bool used = false; for (const Token *tok2 = _tokenizer->tokens(); tok2; tok2 = tok2->next()) { if (Token::simpleMatch(tok2, usagePattern.c_str())) { used = true; break; } } if (! used) { unusedStructMemberError(tok->next(), structname, varname); } } } } //--------------------------------------------------------------------------- // Check usage of char variables.. //--------------------------------------------------------------------------- void CheckOther::checkCharVariable() { if (!_settings->isEnabled("style")) return; for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { // Declaring the variable.. if (Token::Match(tok, "[{};(,] const| char *| %var% [;=,)]") || Token::Match(tok, "[{};(,] const| char %var% [")) { // goto 'char' token tok = tok->next(); if (tok->str() == "const") tok = tok->next(); // Check for unsigned char if (tok->isUnsigned()) continue; // Set tok to point to the variable name tok = tok->next(); const bool isPointer(tok->str() == "*" || tok->strAt(1) == "["); if (tok->str() == "*") tok = tok->next(); // Check usage of char variable.. int indentlevel = 0; for (const Token *tok2 = tok->next(); tok2; tok2 = tok2->next()) { if (tok2->str() == "{") ++indentlevel; else if (tok2->str() == "}") { --indentlevel; if (indentlevel <= 0) break; } if (!isPointer) { std::string temp = "%var% [ " + tok->str() + " ]"; if ((tok2->str() != ".") && Token::Match(tok2->next(), temp.c_str())) { charArrayIndexError(tok2->next()); break; } } if (Token::Match(tok2, "[;{}] %var% = %any% [&|] %any% ;")) { // is the char variable used in the calculation? if (tok2->tokAt(3)->varId() != tok->varId() && tok2->tokAt(5)->varId() != tok->varId()) continue; // it's ok with a bitwise and where the other operand is 0xff or less.. if (tok2->strAt(4) == "&") { if (tok2->tokAt(3)->isNumber() && MathLib::isGreater("0x100", tok2->strAt(3))) continue; if (tok2->tokAt(5)->isNumber() && MathLib::isGreater("0x100", tok2->strAt(5))) continue; } // is the result stored in a short|int|long? if (!Token::findmatch(_tokenizer->tokens(), "short|int|long %varid%", tok2->next()->varId())) continue; // This is an error.. charBitOpError(tok2); break; } if (isPointer && Token::Match(tok2, "[;{}] %var% = %any% [&|] ( * %varid% ) ;", tok->varId())) { // it's ok with a bitwise and where the other operand is 0xff or less.. if (tok2->strAt(4) == "&" && tok2->tokAt(3)->isNumber() && MathLib::isGreater("0x100", tok2->strAt(3))) continue; // is the result stored in a short|int|long? if (!Token::findmatch(_tokenizer->tokens(), "short|int|long %varid%", tok2->next()->varId())) continue; // This is an error.. charBitOpError(tok2); break; } } } } } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // Incomplete statement.. //--------------------------------------------------------------------------- void CheckOther::checkIncompleteStatement() { if (!_settings->isEnabled("style")) return; for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { if (tok->str() == "(") { tok = tok->link(); if (Token::simpleMatch(tok, ") {") && Token::simpleMatch(tok->next()->link(), "} ;")) tok = tok->next()->link(); } else if (Token::simpleMatch(tok, "= {")) tok = tok->next()->link(); else if (tok->str() == "{" && Token::Match(tok->tokAt(-2), "%type% %var%")) tok = tok->link(); else if (Token::Match(tok, "[;{}] %str%") || Token::Match(tok, "[;{}] %num%")) { // bailout if there is a "? :" in this statement bool bailout = false; for (const Token *tok2 = tok->tokAt(2); tok2; tok2 = tok2->next()) { if (tok2->str() == "?") bailout = true; else if (tok2->str() == ";") break; } if (bailout) continue; constStatementError(tok->next(), tok->next()->isNumber() ? "numeric" : "string"); } } } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // str plus char //--------------------------------------------------------------------------- void CheckOther::strPlusChar() { // Don't use this check for Java and C# programs.. if (_tokenizer->isJavaOrCSharp()) { return; } bool charVars[10000] = {0}; for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { // Declaring char variable.. if (Token::Match(tok, "char|int|short %var% [;=]")) { unsigned int varid = tok->next()->varId(); if (varid > 0 && varid < 10000) charVars[varid] = true; } // else if (Token::Match(tok, "[=(] %str% + %any%")) { // char constant.. const std::string s = tok->strAt(3); if (s[0] == '\'') strPlusChar(tok->next()); // char variable.. unsigned int varid = tok->tokAt(3)->varId(); if (varid > 0 && varid < 10000 && charVars[varid]) strPlusChar(tok->next()); } } } void CheckOther::checkZeroDivision() { for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { if (Token::Match(tok, "/ %num%") && MathLib::isInt(tok->next()->str()) && MathLib::toLongNumber(tok->next()->str()) == 0L) { zerodivError(tok); } else if (Token::Match(tok, "div|ldiv|lldiv|imaxdiv ( %num% , %num% )") && MathLib::isInt(tok->tokAt(4)->str()) && MathLib::toLongNumber(tok->tokAt(4)->str()) == 0L) { zerodivError(tok); } } } void CheckOther::checkMathFunctions() { for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { // case log(-2) if (tok->varId() == 0 && Token::Match(tok, "log|log10 ( %num% )") && MathLib::isNegative(tok->tokAt(2)->str()) && MathLib::isInt(tok->tokAt(2)->str()) && MathLib::toLongNumber(tok->tokAt(2)->str()) <= 0) { mathfunctionCallError(tok); } // case log(-2.0) else if (tok->varId() == 0 && Token::Match(tok, "log|log10 ( %num% )") && MathLib::isNegative(tok->tokAt(2)->str()) && MathLib::isFloat(tok->tokAt(2)->str()) && MathLib::toDoubleNumber(tok->tokAt(2)->str()) <= 0.) { mathfunctionCallError(tok); } // case log(0.0) else if (tok->varId() == 0 && Token::Match(tok, "log|log10 ( %num% )") && !MathLib::isNegative(tok->tokAt(2)->str()) && MathLib::isFloat(tok->tokAt(2)->str()) && MathLib::toDoubleNumber(tok->tokAt(2)->str()) <= 0.) { mathfunctionCallError(tok); } // case log(0) else if (tok->varId() == 0 && Token::Match(tok, "log|log10 ( %num% )") && !MathLib::isNegative(tok->tokAt(2)->str()) && MathLib::isInt(tok->tokAt(2)->str()) && MathLib::toLongNumber(tok->tokAt(2)->str()) <= 0) { mathfunctionCallError(tok); } // acos( x ), asin( x ) where x is defined for interval [-1,+1], but not beyond else if (tok->varId() == 0 && Token::Match(tok, "acos|asin ( %num% )") && std::fabs(MathLib::toDoubleNumber(tok->tokAt(2)->str())) > 1.0) { mathfunctionCallError(tok); } // sqrt( x ): if x is negative the result is undefined else if (tok->varId() == 0 && Token::Match(tok, "sqrt|sqrtf|sqrtl ( %num% )") && MathLib::isNegative(tok->tokAt(2)->str())) { mathfunctionCallError(tok); } // atan2 ( x , y): x and y can not be zero, because this is mathematically not defined else if (tok->varId() == 0 && Token::Match(tok, "atan2 ( %num% , %num% )") && MathLib::isNullValue(tok->tokAt(2)->str()) && MathLib::isNullValue(tok->tokAt(4)->str())) { mathfunctionCallError(tok, 2); } // fmod ( x , y) If y is zero, then either a range error will occur or the function will return zero (implementation-defined). else if (tok->varId() == 0 && Token::Match(tok, "fmod ( %num% , %num% )") && MathLib::isNullValue(tok->tokAt(4)->str())) { mathfunctionCallError(tok, 2); } // pow ( x , y) If x is zero, and y is negative --> division by zero else if (tok->varId() == 0 && Token::Match(tok, "pow ( %num% , %num% )") && MathLib::isNullValue(tok->tokAt(2)->str()) && MathLib::isNegative(tok->tokAt(4)->str())) { mathfunctionCallError(tok, 2); } } } /** Is there a function with given name? */ static bool isFunction(const std::string &name, const Token *startToken) { const std::string pattern1(name + " ("); for (const Token *tok = startToken; tok; tok = tok->next()) { // skip executable scopes etc if (tok->str() == "(") { tok = tok->link(); if (Token::simpleMatch(tok, ") {")) tok = tok->next()->link(); else if (Token::simpleMatch(tok, ") const {")) tok = tok->tokAt(2)->link(); } // function declaration/implementation found if ((tok->str() == "*" || (tok->isName() && tok->str().find(":") ==std::string::npos)) && Token::simpleMatch(tok->next(), pattern1.c_str())) return true; } return false; } void CheckOther::checkMisusedScopedObject() { // Skip this check for .c files { const std::string fname = _tokenizer->getFiles()->at(0); size_t position = fname.rfind("."); if (position != std::string::npos) { const std::string ext = fname.substr(position); if (ext == ".c" || ext == ".C") return; } } const SymbolDatabase * const symbolDatabase = _tokenizer->getSymbolDatabase(); std::list::const_iterator scope; for (scope = symbolDatabase->scopeList.begin(); scope != symbolDatabase->scopeList.end(); ++scope) { // only check functions if (scope->type != Scope::eFunction) continue; unsigned int depth = 0; for (const Token *tok = scope->classStart; tok; tok = tok->next()) { if (tok->str() == "{") { ++depth; } else if (tok->str() == "}") { --depth; if (depth == 0) break; } if (Token::Match(tok, "[;{}] %var% (") && Token::simpleMatch(tok->tokAt(2)->link(), ") ;") && symbolDatabase->isClassOrStruct(tok->next()->str()) && !isFunction(tok->next()->str(), _tokenizer->tokens())) { tok = tok->next(); misusedScopeObjectError(tok, tok->str()); tok = tok->next(); } } } } void CheckOther::checkIncorrectStringCompare() { for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { if (Token::Match(tok, ". substr ( %any% , %num% ) ==|!= %str%")) { size_t clen = MathLib::toLongNumber(tok->tokAt(5)->str()); size_t slen = Token::getStrLength(tok->tokAt(8)); if (clen != slen) { incorrectStringCompareError(tok->next(), "substr", tok->tokAt(8)->str(), tok->tokAt(5)->str()); } } if (Token::Match(tok, "%str% ==|!= %var% . substr ( %any% , %num% )")) { size_t clen = MathLib::toLongNumber(tok->tokAt(8)->str()); size_t slen = Token::getStrLength(tok); if (clen != slen) { incorrectStringCompareError(tok->next(), "substr", tok->str(), tok->tokAt(8)->str()); } } } } //----------------------------------------------------------------------------- // check for duplicate expressions in if statements // if (a) { } else if (a) { } //----------------------------------------------------------------------------- static const std::string stringifyTokens(const Token *start, const Token *end) { const Token *tok = start; std::string stringified; if (tok->isUnsigned()) stringified.append("unsigned "); else if (tok->isSigned()) stringified.append("signed "); if (tok->isLong()) stringified.append("long "); stringified.append(tok->str()); while (tok && tok->next() && tok != end) { if (tok->isUnsigned()) stringified.append("unsigned "); else if (tok->isSigned()) stringified.append("signed "); if (tok->isLong()) stringified.append("long "); tok = tok->next(); stringified.append(" "); stringified.append(tok->str()); } return stringified; } static bool expressionHasSideEffects(const Token *first, const Token *last) { for (const Token *tok = first; tok != last->next(); tok = tok->next()) { // check for assignment if (tok->isAssignmentOp()) return true; // check for inc/dec else if (Token::Match(tok, "++|--")) return true; // check for function call else if (Token::Match(tok, "%var% (") && !(Token::Match(tok, "c_str|string") || tok->isStandardType())) return true; } return false; } void CheckOther::checkDuplicateIf() { if (!_settings->isEnabled("style")) return; const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase(); std::list::const_iterator scope; for (scope = symbolDatabase->scopeList.begin(); scope != symbolDatabase->scopeList.end(); ++scope) { // only check functions if (scope->type != Scope::eFunction) continue; // check all the code in the function for if (...) and else if (...) statements for (const Token *tok = scope->classStart; tok && tok != scope->classStart->link(); tok = tok->next()) { if (Token::simpleMatch(tok, "if (") && tok->strAt(-1) != "else" && Token::simpleMatch(tok->next()->link(), ") {")) { std::map expressionMap; // get the expression from the token stream std::string expression = stringifyTokens(tok->tokAt(2), tok->next()->link()->previous()); // save the expression and its location expressionMap.insert(std::make_pair(expression, tok)); // find the next else if (...) statement const Token *tok1 = tok->next()->link()->next()->link(); // check all the else if (...) statements while (Token::simpleMatch(tok1, "} else if (") && Token::simpleMatch(tok1->tokAt(3)->link(), ") {")) { // get the expression from the token stream expression = stringifyTokens(tok1->tokAt(4), tok1->tokAt(3)->link()->previous()); // try to look up the expression to check for duplicates std::map::iterator it = expressionMap.find(expression); // found a duplicate if (it != expressionMap.end()) { // check for expressions that have side effects and ignore them if (!expressionHasSideEffects(tok1->tokAt(4), tok1->tokAt(3)->link()->previous())) duplicateIfError(it->second, tok1->next()); } // not a duplicate expression so save it and its location else expressionMap.insert(std::make_pair(expression, tok1->next())); // find the next else if (...) statement tok1 = tok1->tokAt(3)->link()->next()->link(); } tok = tok->next()->link()->next(); } } } } void CheckOther::duplicateIfError(const Token *tok1, const Token *tok2) { std::list toks; toks.push_back(tok2); toks.push_back(tok1); reportError(toks, Severity::style, "duplicateIf", "Found duplicate if expressions.\n" "Finding the same expression more than once is suspicious and might indicate " "a cut and paste or logic error. Please examine this code carefully to determine " "if it is correct."); } //----------------------------------------------------------------------------- // check for duplicate code in if and else branches // if (a) { b = true; } else { b = true; } //----------------------------------------------------------------------------- void CheckOther::checkDuplicateBranch() { if (!_settings->isEnabled("style")) return; if (!_settings->inconclusive) return; const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase(); std::list::const_iterator scope; for (scope = symbolDatabase->scopeList.begin(); scope != symbolDatabase->scopeList.end(); ++scope) { // only check functions if (scope->type != Scope::eFunction) continue; // check all the code in the function for if (..) else for (const Token *tok = scope->classStart; tok && tok != scope->classStart->link(); tok = tok->next()) { if (Token::simpleMatch(tok, "if (") && tok->strAt(-1) != "else" && Token::simpleMatch(tok->next()->link(), ") {") && Token::simpleMatch(tok->next()->link()->next()->link(), "} else {")) { // save if branch code std::string branch1 = stringifyTokens(tok->next()->link()->tokAt(2), tok->next()->link()->next()->link()->previous()); // find else branch const Token *tok1 = tok->next()->link()->next()->link(); // save else branch code std::string branch2 = stringifyTokens(tok1->tokAt(3), tok1->tokAt(2)->link()->previous()); // check for duplicates if (branch1 == branch2) duplicateBranchError(tok, tok1->tokAt(2)); tok = tok->next()->link()->next(); } } } } void CheckOther::duplicateBranchError(const Token *tok1, const Token *tok2) { std::list toks; toks.push_back(tok2); toks.push_back(tok1); reportError(toks, Severity::style, "duplicateBranch", "Found duplicate branches for if and else.\n" "Finding the same code for an if branch and an else branch is suspicious and " "might indicate a cut and paste or logic error. Please examine this code " "carefully to determine if it is correct."); } //--------------------------------------------------------------------------- // check for the same expression on both sides of an operator // (x == x), (x && x), (x || x) // (x.y == x.y), (x.y && x.y), (x.y || x.y) //--------------------------------------------------------------------------- void CheckOther::checkDuplicateExpression() { if (!_settings->isEnabled("style")) return; // Parse all executing scopes.. const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase(); std::list::const_iterator scope; for (scope = symbolDatabase->scopeList.begin(); scope != symbolDatabase->scopeList.end(); ++scope) { // only check functions if (scope->type != Scope::eFunction) continue; for (const Token *tok = scope->classStart; tok && tok != scope->classStart->link(); tok = tok->next()) { if (Token::Match(tok, "(|&&|%oror% %var% &&|%oror%|==|!=|<=|>=|<|>|-|%or% %var% )|&&|%oror%") && tok->strAt(1) == tok->strAt(3)) { // float == float and float != float are valid NaN checks if (Token::Match(tok->tokAt(2), "==|!=") && tok->next()->varId()) { const Variable * var = symbolDatabase->getVariableFromVarId(tok->next()->varId()); if (var && var->typeStartToken() == var->typeEndToken()) { if (Token::Match(var->typeStartToken(), "float|double")) continue; } } duplicateExpressionError(tok->next(), tok->tokAt(3), tok->strAt(2)); } else if (Token::Match(tok, "(|&&|%oror% %var% . %var% &&|%oror%|==|!=|<=|>=|<|>|-|%or% %var% . %var% )|&&|%oror%") && tok->strAt(1) == tok->strAt(5) && tok->strAt(3) == tok->strAt(7)) { duplicateExpressionError(tok->next(), tok->tokAt(6), tok->strAt(4)); } } } } void CheckOther::duplicateExpressionError(const Token *tok1, const Token *tok2, const std::string &op) { std::list toks; toks.push_back(tok2); toks.push_back(tok1); reportError(toks, Severity::style, "duplicateExpression", "Same expression on both sides of \'" + op + "\'.\n" "Finding the same expression on both sides of an operator is suspicious and might " "indicate a cut and paste or logic error. Please examine this code carefully to " "determine if it is correct."); } //--------------------------------------------------------------------------- // Check for string comparison involving two static strings. // if(strcmp("00FF00","00FF00")==0) // <- statement is always true //--------------------------------------------------------------------------- void CheckOther::checkAlwaysTrueOrFalseStringCompare() { if (!_settings->isEnabled("style")) return; const char pattern1[] = "strcmp|stricmp|strcmpi|strcasecmp|wcscmp ( %str% , %str% )"; const char pattern2[] = "QString :: compare ( %str% , %str% )"; const Token *tok = _tokenizer->tokens(); while (tok && (tok = Token::findmatch(tok, pattern1)) != NULL) { alwaysTrueFalseStringCompare(tok, tok->strAt(2), tok->strAt(4)); tok = tok->tokAt(5); } tok = _tokenizer->tokens(); while (tok && (tok = Token::findmatch(tok, pattern2)) != NULL) { alwaysTrueFalseStringCompare(tok, tok->strAt(4), tok->strAt(6)); tok = tok->tokAt(7); } } void CheckOther::alwaysTrueFalseStringCompare(const Token *tok, const std::string& str1, const std::string& str2) { const size_t stringLen = 10; const std::string string1 = (str1.size() < stringLen) ? str1 : (str1.substr(0, stringLen-2) + ".."); const std::string string2 = (str2.size() < stringLen) ? str2 : (str2.substr(0, stringLen-2) + ".."); if (str1 == str2) { reportError(tok, Severity::warning, "staticStringCompare", "Comparison of always identical static strings.\n" "The compared strings, '" + string1 + "' and '" + string2 + "', are always identical. " "If the purpose is to compare these two strings, the comparison is unnecessary. " "If the strings are supposed to be different, then there is a bug somewhere."); } else { reportError(tok, Severity::performance, "staticStringCompare", "Unnecessary comparison of static strings.\n" "The compared strings, '" + string1 + "' and '" + string2 + "', are static and always different. " "If the purpose is to compare these two strings, the comparison is unnecessary."); } } //----------------------------------------------------------------------------- void CheckOther::cstyleCastError(const Token *tok) { reportError(tok, Severity::style, "cstyleCast", "C-style pointer casting"); } void CheckOther::dangerousUsageStrtolError(const Token *tok) { reportError(tok, Severity::error, "dangerousUsageStrtol", "Invalid radix in call to strtol or strtoul. Must be 0 or 2-36"); } void CheckOther::sprintfOverlappingDataError(const Token *tok, const std::string &varname) { reportError(tok, Severity::error, "sprintfOverlappingData", "Undefined behavior: variable is used as parameter and destination in s[n]printf().\n" "The variable '" + varname + "' is used both as a parameter and as a destination in " "s[n]printf(). The origin and destination buffers overlap. Quote from glibc (C-library) " "documentation (http://www.gnu.org/software/libc/manual/html_mono/libc.html#Formatted-Output-Functions): " "'If copying takes place between objects that overlap as a result of a call " "to sprintf() or snprintf(), the results are undefined.'"); } void CheckOther::udivError(const Token *tok) { reportError(tok, Severity::error, "udivError", "Unsigned division. The result will be wrong."); } void CheckOther::unusedStructMemberError(const Token *tok, const std::string &structname, const std::string &varname) { reportError(tok, Severity::style, "unusedStructMember", "struct or union member '" + structname + "::" + varname + "' is never used"); } void CheckOther::passedByValueError(const Token *tok, const std::string &parname) { reportError(tok, Severity::performance, "passedByValue", "Function parameter '" + parname + "' should be passed by reference.\n" "Parameter '" + parname + "' is passed as a value. It could be passed " "as a (const) reference which is usually faster and recommended in C++."); } void CheckOther::constStatementError(const Token *tok, const std::string &type) { reportError(tok, Severity::warning, "constStatement", "Redundant code: Found a statement that begins with " + type + " constant"); } void CheckOther::charArrayIndexError(const Token *tok) { reportError(tok, Severity::warning, "charArrayIndex", "Using char type as array index\n" "Using signed char type as array index. If the value " "can be greater than 127 there will be a buffer overflow " "(because of sign extension)."); } void CheckOther::charBitOpError(const Token *tok) { reportError(tok, Severity::warning, "charBitOp", "When using char variables in bit operations, sign extension can generate unexpected results.\n" "When using char variables in bit operations, sign extension can generate unexpected results. For example:\n" " char c = 0x80;\n" " int i = 0 | c;\n" " if (i & 0x8000)\n" " printf(\"not expected\");\n" "The 'not expected' will be printed on the screen."); } void CheckOther::variableScopeError(const Token *tok, const std::string &varname) { reportError(tok, Severity::information, "variableScope", "The scope of the variable '" + varname + "' can be reduced\n" "The scope of the variable '" + varname + "' can be reduced. Warning: It can be unsafe " "to fix this message. Be careful. Especially when there are inner loops. Here is an " "example where cppcheck will write that the scope for 'i' can be reduced:\n" "void f(int x)\n" "{\n" " int i = 0;\n" " if (x) {\n" " // it's safe to move 'int i = 0' here\n" " for (int n = 0; n < 10; ++n) {\n" " // it is possible but not safe to move 'int i = 0' here\n" " do_something(&i);\n" " }\n" " }\n" "}\n" "When you see this message it is always safe to reduce the variable scope 1 level."); } void CheckOther::conditionAlwaysTrueFalse(const Token *tok, const std::string &truefalse) { reportError(tok, Severity::style, "conditionAlwaysTrueFalse", "Condition is always " + truefalse); } void CheckOther::strPlusChar(const Token *tok) { reportError(tok, Severity::error, "strPlusChar", "Unusual pointer arithmetic"); } void CheckOther::zerodivError(const Token *tok) { reportError(tok, Severity::error, "zerodiv", "Division by zero"); } void CheckOther::mathfunctionCallError(const Token *tok, const unsigned int numParam) { if (tok) { if (numParam == 1) reportError(tok, Severity::error, "wrongmathcall", "Passing value " + tok->tokAt(2)->str() + " to " + tok->str() + "() leads to undefined result"); else if (numParam == 2) reportError(tok, Severity::error, "wrongmathcall", "Passing value " + tok->tokAt(2)->str() + " and " + tok->tokAt(4)->str() + " to " + tok->str() + "() leads to undefined result"); } else reportError(tok, Severity::error, "wrongmathcall", "Passing value " " to " "() leads to undefined result"); } void CheckOther::fflushOnInputStreamError(const Token *tok, const std::string &varname) { reportError(tok, Severity::error, "fflushOnInputStream", "fflush() called on input stream \"" + varname + "\" may result in undefined behaviour"); } void CheckOther::sizeofsizeof() { if (!_settings->isEnabled("style")) return; for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { if (Token::Match(tok, "sizeof (| sizeof")) { sizeofsizeofError(tok); tok = tok->next(); } } } void CheckOther::sizeofsizeofError(const Token *tok) { reportError(tok, Severity::warning, "sizeofsizeof", "Calling sizeof for 'sizeof'.\n" "Calling sizeof for 'sizeof looks like a suspicious code and " "most likely there should be just one 'sizeof'. The current " "code is equivalent to 'sizeof(size_t)'"); } void CheckOther::sizeofCalculation() { if (!_settings->isEnabled("style")) return; for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { if (Token::simpleMatch(tok, "sizeof (")) { unsigned int parlevel = 0; for (const Token *tok2 = tok->tokAt(2); tok2; tok2 = tok2->next()) { if (tok2->str() == "(") ++parlevel; else if (tok2->str() == ")") { if (parlevel <= 1) break; --parlevel; } else if (Token::Match(tok2, "+|/")) { sizeofCalculationError(tok2); break; } } } } } void CheckOther::sizeofCalculationError(const Token *tok) { reportError(tok, Severity::warning, "sizeofCalculation", "Found calculation inside sizeof()"); } void CheckOther::redundantAssignmentInSwitchError(const Token *tok, const std::string &varname) { reportError(tok, Severity::warning, "redundantAssignInSwitch", "Redundant assignment of \"" + varname + "\" in switch"); } void CheckOther::switchCaseFallThrough(const Token *tok) { reportError(tok, Severity::style, "switchCaseFallThrough", "Switch falls through case without comment"); } void CheckOther::selfAssignmentError(const Token *tok, const std::string &varname) { reportError(tok, Severity::warning, "selfAssignment", "Redundant assignment of \"" + varname + "\" to itself"); } void CheckOther::assignmentInAssertError(const Token *tok, const std::string &varname) { reportError(tok, Severity::warning, "assignmentInAssert", "Assert statement modifies '" + varname + "'.\n" "Variable '" + varname + "' is modified insert assert statement. " "Assert statements are removed from release builds so the code inside " "assert statement is not run. If the code is needed also in release " "builds this is a bug."); } void CheckOther::incorrectLogicOperatorError(const Token *tok, bool always) { if (always) reportError(tok, Severity::warning, "incorrectLogicOperator", "Mutual exclusion over || always evaluates to true. Did you intend to use && instead?"); else reportError(tok, Severity::warning, "incorrectLogicOperator", "Expression always evaluates to false. Did you intend to use || instead?"); } void CheckOther::misusedScopeObjectError(const Token *tok, const std::string& varname) { reportError(tok, Severity::error, "unusedScopedObject", "instance of \"" + varname + "\" object destroyed immediately"); } void CheckOther::catchExceptionByValueError(const Token *tok) { reportError(tok, Severity::style, "catchExceptionByValue", "Exception should be caught by reference.\n" "The exception is caught as a value. It could be caught " "as a (const) reference which is usually recommended in C++."); } void CheckOther::memsetZeroBytesError(const Token *tok, const std::string &varname) { const std::string summary("memset() called to fill 0 bytes of \'" + varname + "\'"); const std::string verbose(summary + ". Second and third arguments might be inverted."); reportError(tok, Severity::warning, "memsetZeroBytes", summary + "\n" + verbose); } void CheckOther::incorrectStringCompareError(const Token *tok, const std::string& func, const std::string &string, const std::string &len) { reportError(tok, Severity::warning, "incorrectStringCompare", "String literal " + string + " doesn't match length argument for " + func + "(" + len + ")."); } void CheckOther::comparisonOfBoolWithIntError(const Token *tok, const std::string &varname) { reportError(tok, Severity::warning, "comparisonOfBoolWithInt", "Comparison of a boolean with a non-zero integer\n" "The expression \"!" + varname + "\" is of type 'bool' but is compared against a non-zero 'int'."); } void CheckOther::duplicateBreakError(const Token *tok) { reportError(tok, Severity::style, "duplicateBreak", "Consecutive break or continue statements are unnecessary\n" "The second of the two statements can never be executed, and so should be removed\n"); } void CheckOther::checkAssignBoolToPointer() { for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { if (Token::Match(tok, "[;{}] %var% = %bool% ;")) { const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase(); const Variable *var1(symbolDatabase->getVariableFromVarId(tok->next()->varId())); // Is variable a pointer? if (var1 && var1->nameToken()->strAt(-1) == "*") assignBoolToPointerError(tok->next()); } } } void CheckOther::assignBoolToPointerError(const Token *tok) { reportError(tok, Severity::error, "assignBoolToPointer", "Assigning bool value to pointer (converting bool value to address)"); } //--------------------------------------------------------------------------- // Check testing sign of unsigned variables. //--------------------------------------------------------------------------- void CheckOther::checkSignOfUnsignedVariable() { if (!_settings->isEnabled("style")) return; const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase(); std::list::const_iterator scope; for (scope = symbolDatabase->scopeList.begin(); scope != symbolDatabase->scopeList.end(); ++scope) { // only check functions if (scope->type != Scope::eFunction) continue; // check all the code in the function for (const Token *tok = scope->classStart; tok && tok != scope->classStart->link(); tok = tok->next()) { if (Token::Match(tok, "( %var% <|<= 0 )") && tok->next()->varId()) { const Variable * var = symbolDatabase->getVariableFromVarId(tok->next()->varId()); if (var && var->typeEndToken()->isUnsigned()) unsignedLessThanZero(tok->next(), tok->next()->str()); } else if (Token::Match(tok, "( 0 > %var% )") && tok->tokAt(3)->varId()) { const Variable * var = symbolDatabase->getVariableFromVarId(tok->tokAt(3)->varId()); if (var && var->typeEndToken()->isUnsigned()) unsignedLessThanZero(tok->tokAt(3), tok->strAt(3)); } else if (Token::Match(tok, "( 0 <= %var% )") && tok->tokAt(3)->varId()) { const Variable * var = symbolDatabase->getVariableFromVarId(tok->tokAt(3)->varId()); if (var && var->typeEndToken()->isUnsigned()) unsignedPositive(tok->tokAt(3), tok->strAt(3)); } } } } void CheckOther::unsignedLessThanZero(const Token *tok, const std::string &varname) { reportError(tok, Severity::style, "unsignedLessThanZero", "Checking if unsigned variable '" + varname + "' is less than zero.\n" "An unsigned variable will never be negative so it is either pointless or " "an error to check if it is."); } void CheckOther::unsignedPositive(const Token *tok, const std::string &varname) { reportError(tok, Severity::style, "unsignedPositive", "Checking if unsigned variable '" + varname + "' is positive is always true.\n" "An unsigned variable can't be negative so it is either pointless or " "an error to check if it is."); } cppcheck-1.61/gui/test/data/files/000077500000000000000000000000001217722632100170025ustar00rootroot00000000000000cppcheck-1.61/gui/test/data/files/bar1000066400000000000000000000000211217722632100175430ustar00rootroot00000000000000Dummy test file. cppcheck-1.61/gui/test/data/files/bar1.foo000066400000000000000000000000211217722632100203250ustar00rootroot00000000000000Dummy test file. cppcheck-1.61/gui/test/data/files/dir1/000077500000000000000000000000001217722632100176415ustar00rootroot00000000000000cppcheck-1.61/gui/test/data/files/dir1/dir11/000077500000000000000000000000001217722632100205615ustar00rootroot00000000000000cppcheck-1.61/gui/test/data/files/dir1/dir11/foo11.cpp000066400000000000000000000000211217722632100222030ustar00rootroot00000000000000Dummy test file. cppcheck-1.61/gui/test/data/files/dir1/foo1.cpp000066400000000000000000000000211217722632100212020ustar00rootroot00000000000000Dummy test file. cppcheck-1.61/gui/test/data/files/dir2/000077500000000000000000000000001217722632100176425ustar00rootroot00000000000000cppcheck-1.61/gui/test/data/files/dir2/foo1.cpp000066400000000000000000000000211217722632100212030ustar00rootroot00000000000000Dummy test file. cppcheck-1.61/gui/test/data/files/foo1.cpp000066400000000000000000000000211217722632100203430ustar00rootroot00000000000000Dummy test file. cppcheck-1.61/gui/test/data/files/foo2.cxx000066400000000000000000000000211217722632100203640ustar00rootroot00000000000000Dummy test file. cppcheck-1.61/gui/test/data/files/foo3.cc000066400000000000000000000000211217722632100201500ustar00rootroot00000000000000Dummy test file. cppcheck-1.61/gui/test/data/files/foo4.c000066400000000000000000000000211217722632100200060ustar00rootroot00000000000000Dummy test file. cppcheck-1.61/gui/test/data/files/foo5.c++000066400000000000000000000000211217722632100201350ustar00rootroot00000000000000Dummy test file. cppcheck-1.61/gui/test/data/files/foo6.txx000066400000000000000000000000211217722632100204110ustar00rootroot00000000000000Dummy test file. cppcheck-1.61/gui/test/data/files/foo7.tpp000066400000000000000000000000211217722632100203720ustar00rootroot00000000000000Dummy test file. cppcheck-1.61/gui/test/data/projectfiles/000077500000000000000000000000001217722632100203715ustar00rootroot00000000000000cppcheck-1.61/gui/test/data/projectfiles/simple.cppcheck000066400000000000000000000006031217722632100233630ustar00rootroot00000000000000 cppcheck-1.61/gui/test/data/projectfiles/simple_ignore.cppcheck000066400000000000000000000006011217722632100247240ustar00rootroot00000000000000 cppcheck-1.61/gui/test/data/projectfiles/simple_noroot.cppcheck000066400000000000000000000005501217722632100247640ustar00rootroot00000000000000 cppcheck-1.61/gui/test/data/xmlfiles/000077500000000000000000000000001217722632100175235ustar00rootroot00000000000000cppcheck-1.61/gui/test/data/xmlfiles/xmlreport_v1.xml000066400000000000000000000023231217722632100227070ustar00rootroot00000000000000 cppcheck-1.61/gui/test/data/xmlfiles/xmlreport_v2.xml000066400000000000000000000040061217722632100227100ustar00rootroot00000000000000 cppcheck-1.61/gui/test/filelist/000077500000000000000000000000001217722632100166025ustar00rootroot00000000000000cppcheck-1.61/gui/test/filelist/filelist.pro000066400000000000000000000003521217722632100211370ustar00rootroot00000000000000TEMPLATE = app TARGET = test-filelist DEPENDPATH += . INCLUDEPATH += . OBJECTS_DIR = ../build MOC_DIR = ../build include(../common.pri) DEFINES += SRCDIR=\\\"$$PWD\\\" # tests SOURCES += testfilelist.cpp HEADERS += testfilelist.h cppcheck-1.61/gui/test/filelist/testfilelist.cpp000066400000000000000000000142671217722632100220330ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include #include #include #include "testfilelist.h" #include "filelist.h" void TestFileList::addFile() { // Accepted extensions: *.cpp, *.cxx, *.cc, *.c, *.c++, *.txx, *.tpp" FileList list; list.AddFile(QString(SRCDIR) + "/../data/files/foo1.cpp"); list.AddFile(QString(SRCDIR) + "/../data/files/foo2.cxx"); list.AddFile(QString(SRCDIR) + "/../data/files/foo3.cc"); list.AddFile(QString(SRCDIR) + "/../data/files/foo4.c"); list.AddFile(QString(SRCDIR) + "/../data/files/foo5.c++"); list.AddFile(QString(SRCDIR) + "/../data/files/foo6.txx"); list.AddFile(QString(SRCDIR) + "/../data/files/foo7.tpp"); QStringList files = list.GetFileList(); QCOMPARE(files.size(), 7); } void TestFileList::addPathList() { // Accepted extensions: *.cpp, *.cxx, *.cc, *.c, *.c++, *.txx, *.tpp" QStringList paths; paths << QString(SRCDIR) + "/../data/files/foo1.cpp"; paths << QString(SRCDIR) + "/../data/files/foo2.cxx"; paths << QString(SRCDIR) + "/../data/files/foo3.cc"; paths << QString(SRCDIR) + "/../data/files/foo4.c"; paths << QString(SRCDIR) + "/../data/files/foo5.c++"; paths << QString(SRCDIR) + "/../data/files/foo6.txx"; paths << QString(SRCDIR) + "/../data/files/foo7.tpp"; FileList list; list.AddPathList(paths); QStringList files = list.GetFileList(); QCOMPARE(files.size(), 7); } void TestFileList::addFile_notexist() { FileList list; list.AddFile(QString(SRCDIR) + "/../data/files/bar1.cpp"); QStringList files = list.GetFileList(); QCOMPARE(files.size(), 0); } void TestFileList::addFile_unknown() { FileList list; list.AddFile(QString(SRCDIR) + "/../data/files/bar1"); list.AddFile(QString(SRCDIR) + "/../data/files/bar1.foo"); QStringList files = list.GetFileList(); QCOMPARE(files.size(), 0); } void TestFileList::addDirectory() { FileList list; list.AddDirectory(QString(SRCDIR) + "/../data/files"); QStringList files = list.GetFileList(); QCOMPARE(files.size(), 7); } void TestFileList::addDirectory_recursive() { FileList list; list.AddDirectory(QString(SRCDIR) + "/../data/files", true); QStringList files = list.GetFileList(); QCOMPARE(files.size(), 10); QDir dir(QString(SRCDIR) + "/../data/files"); QString base = dir.canonicalPath(); QVERIFY(files.contains(base + "/dir1/foo1.cpp")); QVERIFY(files.contains(base + "/dir1/dir11/foo11.cpp")); QVERIFY(files.contains(base + "/dir2/foo1.cpp")); } void TestFileList::filterFiles() { FileList list; QStringList filters; filters << "foo1.cpp" << "foo3.cc"; list.AddExcludeList(filters); list.AddFile(QString(SRCDIR) + "/../data/files/foo1.cpp"); list.AddFile(QString(SRCDIR) + "/../data/files/foo2.cxx"); list.AddFile(QString(SRCDIR) + "/../data/files/foo3.cc"); list.AddFile(QString(SRCDIR) + "/../data/files/foo4.c"); list.AddFile(QString(SRCDIR) + "/../data/files/foo5.c++"); list.AddFile(QString(SRCDIR) + "/../data/files/foo6.txx"); list.AddFile(QString(SRCDIR) + "/../data/files/foo7.tpp"); QStringList files = list.GetFileList(); QCOMPARE(files.size(), 5); QDir dir(QString(SRCDIR) + "/../data/files"); QString base = dir.canonicalPath(); QVERIFY(! files.contains(base + "/foo1.cpp")); QVERIFY(! files.contains(base + "/foo3.cpp")); } void TestFileList::filterFiles2() { FileList list; QStringList filters; filters << "foo1.cpp" << "foo3.cc"; list.AddExcludeList(filters); list.AddDirectory(QString(SRCDIR) + "/../data/files"); QStringList files = list.GetFileList(); QCOMPARE(files.size(), 5); QDir dir(QString(SRCDIR) + "/../data/files"); QString base = dir.canonicalPath(); QVERIFY(! files.contains(base + "/foo1.cpp")); QVERIFY(! files.contains(base + "/foo3.cpp")); } void TestFileList::filterFiles3() { FileList list; QStringList filters; filters << "foo1.cpp" << "foo3.cc"; list.AddExcludeList(filters); list.AddDirectory(QString(SRCDIR) + "/../data/files", true); QStringList files = list.GetFileList(); QCOMPARE(files.size(), 6); QDir dir(QString(SRCDIR) + "/../data/files"); QString base = dir.canonicalPath(); QVERIFY(! files.contains(base + "/foo1.cpp")); QVERIFY(! files.contains(base + "/foo3.cpp")); QVERIFY(! files.contains(base + "/dir1/foo1.cpp")); QVERIFY(! files.contains(base + "/dir2/foo1.cpp")); } void TestFileList::filterFiles4() { FileList list; QStringList filters; filters << "dir1/"; list.AddExcludeList(filters); list.AddDirectory(QString(SRCDIR) + "/../data/files", true); QStringList files = list.GetFileList(); QCOMPARE(files.size(), 8); QDir dir(QString(SRCDIR) + "/../data/files"); QString base = dir.canonicalPath(); QVERIFY(! files.contains(base + "/dir1/foo1.cpp")); QVERIFY(! files.contains(base + "/dir1/dir11/foo11.cpp")); } /* void TestFileList::filterFiles5() { FileList list; QStringList filters; filters << QDir(QString(SRCDIR) + "/../data/files/dir1/").absolutePath() + "/"; list.AddExcludeList(filters); list.AddDirectory(QString(SRCDIR) + "/../data/files", true); QStringList files = list.GetFileList(); QCOMPARE(files.size(), 8); QDir dir(QString(SRCDIR) + "/../data/files"); QString base = dir.canonicalPath(); QVERIFY(! files.contains(base + "/dir1/foo1.cpp")); QVERIFY(! files.contains(base + "/dir1/dir11/foo11.cpp")); } */ QTEST_MAIN(TestFileList) cppcheck-1.61/gui/test/filelist/testfilelist.h000066400000000000000000000021641217722632100214710ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include class TestFileList: public QObject { Q_OBJECT private slots: void addFile(); void addPathList(); void addFile_notexist(); void addFile_unknown(); void addDirectory(); void addDirectory_recursive(); void filterFiles(); void filterFiles2(); void filterFiles3(); void filterFiles4(); }; cppcheck-1.61/gui/test/projectfile/000077500000000000000000000000001217722632100172755ustar00rootroot00000000000000cppcheck-1.61/gui/test/projectfile/projectfile.pro000066400000000000000000000003631217722632100223270ustar00rootroot00000000000000TEMPLATE = app TARGET = test-projectfile DEPENDPATH += . INCLUDEPATH += . OBJECTS_DIR = ../build MOC_DIR = ../build include(../common.pri) DEFINES += SRCDIR=\\\"$$PWD\\\" # tests SOURCES += testprojectfile.cpp HEADERS += testprojectfile.h cppcheck-1.61/gui/test/projectfile/testprojectfile.cpp000066400000000000000000000071171217722632100232150ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include #include "testprojectfile.h" #include "projectfile.h" void TestProjectFile::loadInexisting() { const QString filepath(QString(SRCDIR) + "/../data/projectfiles/foo.cppcheck"); ProjectFile pfile(filepath); QCOMPARE(pfile.Read(), false); } void TestProjectFile::loadSimple() { const QString filepath(QString(SRCDIR) + "/../data/projectfiles/simple.cppcheck"); ProjectFile pfile(filepath); QVERIFY(pfile.Read()); QCOMPARE(pfile.GetRootPath(), QString("../..")); QStringList includes = pfile.GetIncludeDirs(); QCOMPARE(includes.size(), 2); QCOMPARE(includes[0], QString("lib/")); QCOMPARE(includes[1], QString("cli/")); QStringList paths = pfile.GetCheckPaths(); QCOMPARE(paths.size(), 2); QCOMPARE(paths[0], QString("gui/")); QCOMPARE(paths[1], QString("test/")); QStringList excludes = pfile.GetExcludedPaths(); QCOMPARE(excludes.size(), 1); QCOMPARE(excludes[0], QString("gui/temp/")); QStringList defines = pfile.GetDefines(); QCOMPARE(defines.size(), 1); QCOMPARE(defines[0], QString("FOO")); } // Test that project file with old 'ignore' element works void TestProjectFile::loadSimpleWithIgnore() { const QString filepath(QString(SRCDIR) + "/../data/projectfiles/simple_ignore.cppcheck"); ProjectFile pfile(filepath); QVERIFY(pfile.Read()); QCOMPARE(pfile.GetRootPath(), QString("../..")); QStringList includes = pfile.GetIncludeDirs(); QCOMPARE(includes.size(), 2); QCOMPARE(includes[0], QString("lib/")); QCOMPARE(includes[1], QString("cli/")); QStringList paths = pfile.GetCheckPaths(); QCOMPARE(paths.size(), 2); QCOMPARE(paths[0], QString("gui/")); QCOMPARE(paths[1], QString("test/")); QStringList excludes = pfile.GetExcludedPaths(); QCOMPARE(excludes.size(), 1); QCOMPARE(excludes[0], QString("gui/temp/")); QStringList defines = pfile.GetDefines(); QCOMPARE(defines.size(), 1); QCOMPARE(defines[0], QString("FOO")); } void TestProjectFile::loadSimpleNoroot() { const QString filepath(QString(SRCDIR) + "/../data/projectfiles/simple_noroot.cppcheck"); ProjectFile pfile(filepath); QVERIFY(pfile.Read()); QCOMPARE(pfile.GetRootPath(), QString()); QStringList includes = pfile.GetIncludeDirs(); QCOMPARE(includes.size(), 2); QCOMPARE(includes[0], QString("lib/")); QCOMPARE(includes[1], QString("cli/")); QStringList paths = pfile.GetCheckPaths(); QCOMPARE(paths.size(), 2); QCOMPARE(paths[0], QString("gui/")); QCOMPARE(paths[1], QString("test/")); QStringList excludes = pfile.GetExcludedPaths(); QCOMPARE(excludes.size(), 1); QCOMPARE(excludes[0], QString("gui/temp/")); QStringList defines = pfile.GetDefines(); QCOMPARE(defines.size(), 1); QCOMPARE(defines[0], QString("FOO")); } QTEST_MAIN(TestProjectFile) cppcheck-1.61/gui/test/projectfile/testprojectfile.h000066400000000000000000000017431217722632100226610ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include class TestProjectFile: public QObject { Q_OBJECT private slots: void loadInexisting(); void loadSimple(); void loadSimpleWithIgnore(); void loadSimpleNoroot(); }; cppcheck-1.61/gui/test/readme.txt000066400000000000000000000013071217722632100167660ustar00rootroot00000000000000GUI tests + benchmark tests =========================== As the GUI uses Qt framework, the GUI tests also use Qt's Testlib. This is totally different test framework than lib/cli is using. By principle each testcase is compiled as an own runnable binary. Compiling --------- To compile all the tests run in root directory of tests: - qmake ; make You can also (re)compile single test by CD:ing to the directory where test (source) resides and running: - qmake ; make Running ------- As each test is compiled as single executable binary you can run the test just by running the executable. You can get from http://bitbucket.org/kimmov/testrun a script which runs all the tests and collects the results. cppcheck-1.61/gui/test/test.pro000066400000000000000000000002511217722632100164660ustar00rootroot00000000000000CONFIG += ordered TEMPLATE = subdirs SUBDIRS = benchmark \ filelist \ projectfile \ translationhandler \ xmlreport \ xmlreportv1 \ xmlreportv2 cppcheck-1.61/gui/test/translationhandler/000077500000000000000000000000001217722632100206635ustar00rootroot00000000000000cppcheck-1.61/gui/test/translationhandler/testtranslationhandler.cpp000066400000000000000000000021461217722632100261660ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include #include "testtranslationhandler.h" #include "translationhandler.h" void TestTranslationHandler::construct() { TranslationHandler handler; QCOMPARE(handler.GetNames().size(), 13); // 12 translations + english QCOMPARE(handler.GetCurrentLanguage(), QString("en")); } QTEST_MAIN(TestTranslationHandler) cppcheck-1.61/gui/test/translationhandler/testtranslationhandler.h000066400000000000000000000016201217722632100256270ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include class TestTranslationHandler: public QObject { Q_OBJECT private slots: void construct(); }; cppcheck-1.61/gui/test/translationhandler/translationhandler.pro000066400000000000000000000003471217722632100253050ustar00rootroot00000000000000TEMPLATE = app TARGET = test-translationhandler DEPENDPATH += . INCLUDEPATH += . OBJECTS_DIR = ../build MOC_DIR = ../build include(../common.pri) # tests SOURCES += testtranslationhandler.cpp HEADERS += testtranslationhandler.h cppcheck-1.61/gui/test/xmlreport/000077500000000000000000000000001217722632100170235ustar00rootroot00000000000000cppcheck-1.61/gui/test/xmlreport/testxmlreport.cpp000066400000000000000000000032351217722632100224660ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include #include "testxmlreport.h" #include "xmlreport.h" void TestXmlReport::testQuoteMessage() { const QString toQuote("abcdefgh&\"'<>12345"); const QString quoted("abcdefgh&"'<>12345"); QCOMPARE(XmlReport::quoteMessage(toQuote), quoted); } void TestXmlReport::testUnquoteMessage() { const QString toQuote("abcdefgh&\"'<>12345"); const QString quoted("abcdefgh&"'<>12345"); QCOMPARE(XmlReport::unquoteMessage(quoted), toQuote); } void TestXmlReport::testGetVersion1() { const QString filepath(QString(SRCDIR) + "/../data/xmlfiles/xmlreport_v1.xml"); QCOMPARE(XmlReport::determineVersion(filepath), 1); } void TestXmlReport::testGetVersion2() { const QString filepath(QString(SRCDIR) + "/../data/xmlfiles/xmlreport_v2.xml"); QCOMPARE(XmlReport::determineVersion(filepath), 2); } QTEST_MAIN(TestXmlReport) cppcheck-1.61/gui/test/xmlreport/testxmlreport.h000066400000000000000000000017451217722632100221370ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include class TestXmlReport: public QObject { Q_OBJECT private slots: void testQuoteMessage(); void testUnquoteMessage(); void testGetVersion1(); void testGetVersion2(); }; cppcheck-1.61/gui/test/xmlreport/xmlreport.pro000066400000000000000000000003551217722632100216040ustar00rootroot00000000000000TEMPLATE = app TARGET = test-xmlreport DEPENDPATH += . INCLUDEPATH += . OBJECTS_DIR = ../build MOC_DIR = ../build include(../common.pri) DEFINES += SRCDIR=\\\"$$PWD\\\" # tests SOURCES += testxmlreport.cpp HEADERS += testxmlreport.h cppcheck-1.61/gui/test/xmlreportv1/000077500000000000000000000000001217722632100172725ustar00rootroot00000000000000cppcheck-1.61/gui/test/xmlreportv1/testxmlreportv1.cpp000066400000000000000000000031441217722632100232030ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include #include "testxmlreportv1.h" #include "xmlreportv1.h" #include "erroritem.h" #include "errorlogger.h" void TestXmlReportV1::readXml() { const QString filepath(QString(SRCDIR) + "/../data/xmlfiles/xmlreport_v1.xml"); XmlReportV1 report(filepath); QVERIFY(report.Open()); QList errors = report.Read(); QCOMPARE(errors.size(), 6); ErrorItem item = errors[0]; QCOMPARE(item.file, QString("test.cxx")); QCOMPARE(item.lines[0], (unsigned int)11); QCOMPARE(item.errorId, QString("unreadVariable")); QCOMPARE(GuiSeverity::toString(item.severity), QString("style")); QCOMPARE(item.summary, QString("Variable 'a' is assigned a value that is never used")); QCOMPARE(item.message, QString("Variable 'a' is assigned a value that is never used")); } QTEST_MAIN(TestXmlReportV1) cppcheck-1.61/gui/test/xmlreportv1/testxmlreportv1.h000066400000000000000000000016071217722632100226520ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include class TestXmlReportV1: public QObject { Q_OBJECT private slots: void readXml(); }; cppcheck-1.61/gui/test/xmlreportv1/xmlreportv1.pro000066400000000000000000000003631217722632100223210ustar00rootroot00000000000000TEMPLATE = app TARGET = test-xmlreportv1 DEPENDPATH += . INCLUDEPATH += . OBJECTS_DIR = ../build MOC_DIR = ../build include(../common.pri) DEFINES += SRCDIR=\\\"$$PWD\\\" # tests SOURCES += testxmlreportv1.cpp HEADERS += testxmlreportv1.h cppcheck-1.61/gui/test/xmlreportv2/000077500000000000000000000000001217722632100172735ustar00rootroot00000000000000cppcheck-1.61/gui/test/xmlreportv2/testxmlreportv2.cpp000066400000000000000000000045541217722632100232130ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include #include "testxmlreportv2.h" #include "xmlreportv2.h" #include "erroritem.h" #include "errorlogger.h" void TestXmlReportV2::readXml() { const QString filepath(QString(SRCDIR) + "/../data/xmlfiles/xmlreport_v2.xml"); XmlReportV2 report(filepath); QVERIFY(report.Open()); QList errors = report.Read(); QCOMPARE(errors.size(), 6); ErrorItem item = errors[0]; QCOMPARE(item.file, QString("test.cxx")); QCOMPARE(item.files.size(), 1); QCOMPARE(item.lines.size(), 1); QCOMPARE(item.files[0], QString("test.cxx")); QCOMPARE(item.lines[0], (unsigned int)11); QCOMPARE(item.errorId, QString("unreadVariable")); QCOMPARE(GuiSeverity::toString(item.severity), QString("style")); QCOMPARE(item.summary, QString("Variable 'a' is assigned a value that is never used")); QCOMPARE(item.message, QString("Variable 'a' is assigned a value that is never used")); ErrorItem item2 = errors[3]; QCOMPARE(item2.file, QString("test.cxx")); QCOMPARE(item2.files.size(), 2); QCOMPARE(item2.lines.size(), 2); QCOMPARE(item2.files[0], QString("test.cxx")); QCOMPARE(item2.lines[0], (unsigned int)32); QCOMPARE(item2.files[1], QString("test.cxx")); QCOMPARE(item2.lines[1], (unsigned int)16); QCOMPARE(item2.errorId, QString("mismatchAllocDealloc")); QCOMPARE(GuiSeverity::toString(item2.severity), QString("error")); QCOMPARE(item2.summary, QString("Mismatching allocation and deallocation: k")); QCOMPARE(item2.message, QString("Mismatching allocation and deallocation: k")); } QTEST_MAIN(TestXmlReportV2) cppcheck-1.61/gui/test/xmlreportv2/testxmlreportv2.h000066400000000000000000000016071217722632100226540ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include class TestXmlReportV2: public QObject { Q_OBJECT private slots: void readXml(); }; cppcheck-1.61/gui/test/xmlreportv2/xmlreportv2.pro000066400000000000000000000003631217722632100223230ustar00rootroot00000000000000TEMPLATE = app TARGET = test-xmlreportv2 DEPENDPATH += . INCLUDEPATH += . OBJECTS_DIR = ../build MOC_DIR = ../build include(../common.pri) DEFINES += SRCDIR=\\\"$$PWD\\\" # tests SOURCES += testxmlreportv2.cpp HEADERS += testxmlreportv2.h cppcheck-1.61/gui/threadhandler.cpp000066400000000000000000000143341217722632100173260ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include #include #include #include "common.h" #include "settings.h" #include "checkthread.h" #include "threadhandler.h" #include "resultsview.h" ThreadHandler::ThreadHandler(QObject *parent) : QObject(parent), mScanDuration(0), mRunningThreadCount(0) { SetThreadCount(1); } ThreadHandler::~ThreadHandler() { RemoveThreads(); } void ThreadHandler::ClearFiles() { mLastFiles.clear(); mResults.ClearFiles(); } void ThreadHandler::SetFiles(const QStringList &files) { mResults.SetFiles(files); mLastFiles = files; } void ThreadHandler::Check(const Settings &settings, bool recheck) { if (recheck && mRunningThreadCount == 0) { // only recheck changed files mResults.SetFiles(GetReCheckFiles()); } if (mResults.GetFileCount() == 0 || mRunningThreadCount > 0 || settings._jobs == 0) { qDebug() << "Can't start checking if there's no files to check or if check is in progress."; emit Done(); return; } SetThreadCount(settings._jobs); mRunningThreadCount = mThreads.size(); if (mResults.GetFileCount() < mRunningThreadCount) { mRunningThreadCount = mResults.GetFileCount(); } for (int i = 0; i < mRunningThreadCount; i++) { mThreads[i]->Check(settings); } // Date and time when checking starts.. mCheckStartTime = QDateTime::currentDateTime(); mTime.start(); } bool ThreadHandler::IsChecking() const { return mRunningThreadCount > 0; } void ThreadHandler::SetThreadCount(const int count) { if (mRunningThreadCount > 0 || count == mThreads.size() || count <= 0) { return; } //Remove unused old threads RemoveThreads(); //Create new threads for (int i = mThreads.size(); i < count; i++) { mThreads << new CheckThread(mResults); connect(mThreads.last(), SIGNAL(Done()), this, SLOT(ThreadDone())); connect(mThreads.last(), SIGNAL(FileChecked(const QString &)), &mResults, SLOT(FileChecked(const QString &))); } } void ThreadHandler::RemoveThreads() { for (int i = 0; i < mThreads.size(); i++) { mThreads[i]->terminate(); disconnect(mThreads.last(), SIGNAL(Done()), this, SLOT(ThreadDone())); disconnect(mThreads.last(), SIGNAL(FileChecked(const QString &)), &mResults, SLOT(FileChecked(const QString &))); delete mThreads[i]; } mThreads.clear(); } void ThreadHandler::ThreadDone() { mRunningThreadCount--; if (mRunningThreadCount == 0) { emit Done(); mScanDuration = mTime.elapsed(); // Set date/time used by the recheck if (!mCheckStartTime.isNull()) { mLastCheckTime = mCheckStartTime; mCheckStartTime = QDateTime(); } } } void ThreadHandler::Stop() { mCheckStartTime = QDateTime(); for (int i = 0; i < mThreads.size(); i++) { mThreads[i]->stop(); } } void ThreadHandler::Initialize(ResultsView *view) { connect(&mResults, SIGNAL(Progress(int, const QString&)), view, SLOT(Progress(int, const QString&))); connect(&mResults, SIGNAL(Error(const ErrorItem &)), view, SLOT(Error(const ErrorItem &))); connect(&mResults, SIGNAL(Log(const QString &)), parent(), SLOT(Log(const QString &))); connect(&mResults, SIGNAL(DebugError(const ErrorItem &)), parent(), SLOT(DebugError(const ErrorItem &))); } void ThreadHandler::LoadSettings(QSettings &settings) { SetThreadCount(settings.value(SETTINGS_CHECK_THREADS, 1).toInt()); } void ThreadHandler::SaveSettings(QSettings &settings) const { settings.setValue(SETTINGS_CHECK_THREADS, mThreads.size()); } bool ThreadHandler::HasPreviousFiles() const { return !mLastFiles.isEmpty(); } int ThreadHandler::GetPreviousFilesCount() const { return mLastFiles.size(); } int ThreadHandler::GetPreviousScanDuration() const { return mScanDuration; } QStringList ThreadHandler::GetReCheckFiles() const { if (mLastCheckTime.isNull()) return mLastFiles; std::set modified; std::set unmodified; QStringList files; for (int i = 0; i < mLastFiles.size(); ++i) { if (NeedsReCheck(mLastFiles[i], modified, unmodified)) files.push_back(mLastFiles[i]); } return files; } bool ThreadHandler::NeedsReCheck(const QString &filename, std::set &modified, std::set &unmodified) const { if (modified.find(filename) != modified.end()) return true; if (unmodified.find(filename) != unmodified.end()) return false; if (QFileInfo(filename).lastModified() > mLastCheckTime) { return true; } // Parse included files recursively QFile f(filename); if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) return false; // prevent recursion.. unmodified.insert(filename); QTextStream in(&f); while (!in.atEnd()) { QString line = in.readLine(); if (line.startsWith("#include \"")) { line.remove(0,10); int i = line.indexOf("\""); if (i > 0) { line.remove(i,line.length()); line = QFileInfo(filename).absolutePath() + "/" + line; if (NeedsReCheck(line, modified, unmodified)) { modified.insert(line); return true; } } } } return false; } cppcheck-1.61/gui/threadhandler.h000066400000000000000000000111001217722632100167570ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #ifndef THREADHANDLER_H #define THREADHANDLER_H #include #include #include #include #include "threadresult.h" class ResultsView; class CheckThread; class QSettings; class Settings; /// @addtogroup GUI /// @{ /** * @brief This class handles creating threadresult and starting threads * */ class ThreadHandler : public QObject { Q_OBJECT public: ThreadHandler(QObject *parent = 0); virtual ~ThreadHandler(); /** * @brief Set the number of threads to use * @param count The number of threads to use */ void SetThreadCount(const int count); /** * @brief Initialize the threads (connect all signals to resultsview's slots) * * @param view View to show error results */ void Initialize(ResultsView *view); /** * @brief Load settings * @param settings QSettings to load settings from */ void LoadSettings(QSettings &settings); /** * @brief Save settings * @param settings QSettings to save settings to */ void SaveSettings(QSettings &settings) const; /** * @brief Clear all files from cppcheck * */ void ClearFiles(); /** * @brief Set files to check * * @param files files to check */ void SetFiles(const QStringList &files); /** * @brief Start the threads to check the files * * @param settings Settings for checking * @param recheck Should we reuse the files we checked earlier */ void Check(const Settings &settings, bool recheck); /** * @brief Is checking running? * * @return true if check is running, false otherwise. */ bool IsChecking() const; /** * @brief Have we checked files already? * * @return true check has been previously run and recheck can be done */ bool HasPreviousFiles() const; /** * @brief Return count of files we checked last time. * * @return count of files that were checked last time. */ int GetPreviousFilesCount() const; /** * @brief Return the time elapsed while scanning the previous time. * * @return the time elapsed in milliseconds. */ int GetPreviousScanDuration() const; /** * @brief Get files that should be rechecked because they have been * changed. */ QStringList GetReCheckFiles() const; signals: /** * @brief Signal that all threads are done * */ void Done(); public slots: /** * @brief Slot to stop all threads * */ void Stop(); protected slots: /** * @brief Slot that a single thread is done * */ void ThreadDone(); protected: /** * @brief List of files checked last time (used when rechecking) * */ QStringList mLastFiles; /** @brief date and time when current checking started */ QDateTime mCheckStartTime; /** * @brief when was the files checked the last time (used when rechecking) */ QDateTime mLastCheckTime; /** * @brief Timer used for measuring scan duration * */ QTime mTime; /** * @brief The previous scan duration in milliseconds. * */ int mScanDuration; /** * @brief Function to delete all threads * */ void RemoveThreads(); /** * @brief Thread results are stored here * */ ThreadResult mResults; /** * @brief List of threads currently in use * */ QList mThreads; /** * @brief The amount of threads currently running * */ int mRunningThreadCount; private: /** * @brief Check if a file needs to be rechecked. Recursively checks * included headers. Used by GetReCheckFiles() */ bool NeedsReCheck(const QString &filename, std::set &modified, std::set &unmodified) const; }; /// @} #endif // THREADHANDLER_H cppcheck-1.61/gui/threadresult.cpp000066400000000000000000000066521217722632100172330ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include #include #include #include #include #include "common.h" #include "erroritem.h" #include "errorlogger.h" #include "threadresult.h" ThreadResult::ThreadResult() : mMaxProgress(0), mProgress(0), mFilesChecked(0), mTotalFiles(0) { //ctor } ThreadResult::~ThreadResult() { //dtor } void ThreadResult::reportOut(const std::string &outmsg) { emit Log(QString::fromStdString(outmsg)); } void ThreadResult::FileChecked(const QString &file) { QMutexLocker locker(&mutex); mProgress += QFile(file).size(); mFilesChecked ++; if (mMaxProgress > 0) { const int value = static_cast(PROGRESS_MAX * mProgress / mMaxProgress); const QString description = tr("%1 of %2 files checked").arg(mFilesChecked).arg(mTotalFiles); emit Progress(value, description); } } void ThreadResult::reportErr(const ErrorLogger::ErrorMessage &msg) { QMutexLocker locker(&mutex); QList lines; QStringList files; for (std::list::const_iterator tok = msg._callStack.begin(); tok != msg._callStack.end(); ++tok) { files << QString((*tok).getfile(false).c_str()); lines << (*tok).line; } ErrorItem item; item.file = QString::fromStdString(callStackToString(msg._callStack)); item.files = files; item.errorId = QString::fromStdString(msg._id); item.lines = lines; item.summary = QString::fromStdString(msg.shortMessage()); item.message = QString::fromStdString(msg.verboseMessage()); item.severity = msg._severity; item.inconclusive = msg._inconclusive; item.file0 = QString::fromStdString(msg.file0); if (msg._severity != Severity::debug) emit Error(item); else emit DebugError(item); } QString ThreadResult::GetNextFile() { QMutexLocker locker(&mutex); if (mFiles.isEmpty()) { return ""; } return mFiles.takeFirst(); } void ThreadResult::SetFiles(const QStringList &files) { QMutexLocker locker(&mutex); mFiles = files; mProgress = 0; mFilesChecked = 0; mTotalFiles = files.size(); // Determine the total size of all of the files to check, so that we can // show an accurate progress estimate quint64 sizeOfFiles = 0; foreach(const QString& file, files) { sizeOfFiles += QFile(file).size(); } mMaxProgress = sizeOfFiles; } void ThreadResult::ClearFiles() { QMutexLocker locker(&mutex); mFiles.clear(); mFilesChecked = 0; mTotalFiles = 0; } int ThreadResult::GetFileCount() const { QMutexLocker locker(&mutex); return mFiles.size(); } cppcheck-1.61/gui/threadresult.h000066400000000000000000000057771217722632100167070ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #ifndef THREADRESULT_H #define THREADRESULT_H #include #include #include #include "errorlogger.h" class ErrorItem; /// @addtogroup GUI /// @{ /** * @brief Threads use this class to obtain new files to process and to publish results * */ class ThreadResult : public QObject, public ErrorLogger { Q_OBJECT public: ThreadResult(); virtual ~ThreadResult(); /** * @brief Get next unprocessed file * @return File path */ QString GetNextFile(); /** * @brief Set list of files to check * @param files List of files to check */ void SetFiles(const QStringList &files); /** * @brief Clear files to check * */ void ClearFiles(); /** * @brief Get the number of files to check * */ int GetFileCount() const; /** * ErrorLogger methods */ void reportOut(const std::string &outmsg); void reportErr(const ErrorLogger::ErrorMessage &msg); public slots: /** * @brief Slot threads use to signal this class that a specific file is checked * @param file File that is checked */ void FileChecked(const QString &file); signals: /** * @brief Progress signal * @param value Current progress * @param description Description of the current stage */ void Progress(int value, const QString& description); /** * @brief Signal of a new error * * @param item Error data */ void Error(const ErrorItem &item); /** * @brief Signal of a new log message * * @param logline Log line */ void Log(const QString &logline); /** * @brief Signal of a debug error * * @param item Error data */ void DebugError(const ErrorItem &item); protected: /** * @brief Mutex * */ mutable QMutex mutex; /** * @brief List of files to check * */ QStringList mFiles; /** * @brief Max progress * */ quint64 mMaxProgress; /** * @brief Current progress * */ quint64 mProgress; /** * @brief Current number of files checked * */ unsigned long mFilesChecked; /** * @brief Total number of files * */ unsigned long mTotalFiles; }; /// @} #endif // THREADRESULT_H cppcheck-1.61/gui/translationhandler.cpp000066400000000000000000000137241217722632100204170ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include #include #include #include #include "translationhandler.h" // Provide own translations for standard buttons. This (garbage) code is needed to enforce them to appear in .ts files even after "lupdate gui.pro" static void unused() { QT_TRANSLATE_NOOP("QDialogButtonBox", "OK"); QT_TRANSLATE_NOOP("QDialogButtonBox", "Cancel"); QT_TRANSLATE_NOOP("QDialogButtonBox", "Close"); QT_TRANSLATE_NOOP("QDialogButtonBox", "Save"); } TranslationHandler::TranslationHandler(QObject *parent) : QObject(parent), mCurrentLanguage("en"), mTranslator(NULL) { // Add our available languages // Keep this list sorted AddTranslation(QT_TRANSLATE_NOOP("MainWindow", "Chinese (Simplified)"), "cppcheck_zh_CN"); AddTranslation(QT_TRANSLATE_NOOP("MainWindow", "Dutch"), "cppcheck_nl"); AddTranslation(QT_TRANSLATE_NOOP("MainWindow", "English"), "cppcheck_en"); AddTranslation(QT_TRANSLATE_NOOP("MainWindow", "Finnish"), "cppcheck_fi"); AddTranslation(QT_TRANSLATE_NOOP("MainWindow", "French"), "cppcheck_fr"); AddTranslation(QT_TRANSLATE_NOOP("MainWindow", "German"), "cppcheck_de"); AddTranslation(QT_TRANSLATE_NOOP("MainWindow", "Italian"), "cppcheck_it"); AddTranslation(QT_TRANSLATE_NOOP("MainWindow", "Japanese"), "cppcheck_ja"); AddTranslation(QT_TRANSLATE_NOOP("MainWindow", "Korean"), "cppcheck_ko"); AddTranslation(QT_TRANSLATE_NOOP("MainWindow", "Russian"), "cppcheck_ru"); AddTranslation(QT_TRANSLATE_NOOP("MainWindow", "Serbian"), "cppcheck_sr"); AddTranslation(QT_TRANSLATE_NOOP("MainWindow", "Spanish"), "cppcheck_es"); AddTranslation(QT_TRANSLATE_NOOP("MainWindow", "Swedish"), "cppcheck_sv"); } TranslationHandler::~TranslationHandler() { } const QStringList TranslationHandler::GetNames() const { QStringList names; foreach(TranslationInfo translation, mTranslations) { names.append(translation.mName); } return names; } bool TranslationHandler::SetLanguage(const QString &code) { bool failure = false; QString error; //If English is the language if (code == "en") { //Just remove all extra translators if (mTranslator) { qApp->removeTranslator(mTranslator); delete mTranslator; mTranslator = NULL; } mCurrentLanguage = code; return true; } //Make sure the translator is otherwise valid int index = GetLanguageIndexByCode(code); if (index == -1) { error = QObject::tr("Unknown language specified!"); failure = true; } // Make sure there is a translator if (!mTranslator && !failure) mTranslator = new QTranslator(this); //Load the new language if (!mTranslator->load(mTranslations[index].mFilename) && !failure) { //If it failed, lets check if the default file exists if (!QFile::exists(mTranslations[index].mFilename + ".qm")) { error = QObject::tr("Language file %1 not found!"); error = error.arg(mTranslations[index].mFilename + ".qm"); failure = true; } //If file exists, there's something wrong with it error = QObject::tr("Failed to load translation for language %1 from file %2"); error = error.arg(mTranslations[index].mName); error = error.arg(mTranslations[index].mFilename + ".qm"); } if (failure) { const QString msg(tr("Failed to change the user interface language:" "\n\n%1\n\n" "The user interface language has been reset to English. Open " "the Preferences-dialog to select any of the available " "languages.").arg(error)); QMessageBox msgBox(QMessageBox::Warning, tr("Cppcheck"), msg, QMessageBox::Ok); msgBox.exec(); return false; } qApp->installTranslator(mTranslator); mCurrentLanguage = code; return true; } QString TranslationHandler::GetCurrentLanguage() const { return mCurrentLanguage; } QString TranslationHandler::SuggestLanguage() const { /* Get language from system locale's name QLocale::languageToString would return the languages full name and we only want two-letter ISO 639 language code so we'll get it from locale's name. */ QString language = QLocale::system().name().left(2); //qDebug()<<"Your language is"<. */ #ifndef TRANSLATIONHANDLER_H #define TRANSLATIONHANDLER_H #include #include #include #include /// @addtogroup GUI /// @{ /** * @brief Information for one translation. * */ struct TranslationInfo { /** * @brief Readable name for the translation (e.g. "English"). * */ QString mName; /** * @brief Filename for the translation. * */ QString mFilename; /** * @brief ISO 639 language code for the translation (e.g. "en"). * */ QString mCode; }; /** * @brief A class handling the available translations. * * This class contains a list of available translations. The class also keeps * track which translation is the currently active translation. * */ class TranslationHandler : QObject { Q_OBJECT public: TranslationHandler(QObject *parent = 0); virtual ~TranslationHandler(); /** * @brief Get a list of available translation names. * @return List of available translation names. * */ const QStringList GetNames() const; /** * @brief Get a list of available translations. * @return List of available translations. * */ QList GetTranslations() const { return mTranslations; } /** * @brief Set active translation. * @param code ISO 639 language code for new selected translation. * @return true if succeeds, false otherwise. * */ bool SetLanguage(const QString &code); /** * @brief Get currently selected translation. * @return ISO 639 language code for current translation. * */ QString GetCurrentLanguage() const; /** * @brief Get translation suggestion for the system. * This function checks the current system locale and determines which of * the available translations is best as current translation. If none of * the available translations is good then it returns English ("en"). * @return Suggested translation ISO 639 language code. * */ QString SuggestLanguage() const; protected: /** * @brief Add new translation to list of available translations. * @param name Name of the translation ("English"). * @param filename Filename of the translation. * */ void AddTranslation(const char *name, const char *filename); /** * @brief Find language in the list and return its index. * @param code ISO 639 language code. * @return Index at list, or -1 if not found. * */ int GetLanguageIndexByCode(const QString &code) const; private: /** * @brief ISO 639 language code of the currently selected translation. * */ QString mCurrentLanguage; /** * @brief List of available translations. * */ QList mTranslations; /** * @brief Translator class instance. * */ QTranslator *mTranslator; }; /// @} #endif // TRANSLATIONHANDLER_H cppcheck-1.61/gui/txtreport.cpp000066400000000000000000000040311217722632100165650ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include "txtreport.h" TxtReport::TxtReport(const QString &filename) : Report(filename) { } TxtReport::~TxtReport() { } bool TxtReport::Create() { if (Report::Create()) { mTxtWriter.setDevice(Report::GetFile()); return true; } return false; } void TxtReport::WriteHeader() { // No header for txt report } void TxtReport::WriteFooter() { // No footer for txt report } void TxtReport::WriteError(const ErrorItem &error) { /* Error example from the core program in text [gui/test.cpp:23] -> [gui/test.cpp:14]: (error) Mismatching allocation and deallocation: k */ QString line; for (int i = 0; i < error.lines.size(); i++) { const QString file = QDir::toNativeSeparators(error.files[i]); line += QString("[%1:%2]").arg(file).arg(error.lines[i]); if (i < error.lines.size() - 1 && !error.lines.isEmpty()) { line += " -> "; } if (i == error.lines.size() - 1) { line += ": "; } } QString temp = "(%1"; if (error.inconclusive) { temp += ", "; temp += tr("inconclusive"); } temp += ") "; line += temp.arg(GuiSeverity::toString(error.severity)); line += error.summary; mTxtWriter << line << endl; } cppcheck-1.61/gui/txtreport.h000066400000000000000000000033071217722632100162370ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #ifndef TXT_REPORT_H #define TXT_REPORT_H #include #include #include "report.h" /// @addtogroup GUI /// @{ /** * @brief Text file report. * This report mimics the output of the command line cppcheck. */ class TxtReport : public Report { Q_OBJECT public: TxtReport(const QString &filename); virtual ~TxtReport(); /** * @brief Create the report (file). * @return true if succeeded, false if file could not be created. */ virtual bool Create(); /** * @brief Write report header. */ virtual void WriteHeader(); /** * @brief Write report footer. */ virtual void WriteFooter(); /** * @brief Write error to report. * @param error Error data. */ virtual void WriteError(const ErrorItem &error); private: /** * @brief Text stream writer for writing the report in text format. */ QTextStream mTxtWriter; }; /// @} #endif // TXT_REPORT_H cppcheck-1.61/gui/xmlreport.cpp000066400000000000000000000056771217722632100165670ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include #include #include #include "report.h" #include "xmlreport.h" static const char ResultElementName[] = "results"; static const char VersionAttribute[] = "version"; XmlReport::XmlReport(const QString &filename) : Report(filename) { } QString XmlReport::quoteMessage(const QString &message) { QString quotedMessage(message); quotedMessage.replace("&", "&"); quotedMessage.replace("\"", """); quotedMessage.replace("'", "'"); quotedMessage.replace("<", "<"); quotedMessage.replace(">", ">"); return quotedMessage; } QString XmlReport::unquoteMessage(const QString &message) { QString quotedMessage(message); quotedMessage.replace("&", "&"); quotedMessage.replace(""", "\""); quotedMessage.replace("'", "'"); quotedMessage.replace("<", "<"); quotedMessage.replace(">", ">"); return quotedMessage; } int XmlReport::determineVersion(const QString &filename) { QFile file; file.setFileName(filename); bool succeed = file.open(QIODevice::ReadOnly | QIODevice::Text); if (!succeed) return 0; QXmlStreamReader reader(&file); while (!reader.atEnd()) { switch (reader.readNext()) { case QXmlStreamReader::StartElement: if (reader.name() == ResultElementName) { QXmlStreamAttributes attribs = reader.attributes(); if (attribs.hasAttribute(QString(VersionAttribute))) { int ver = attribs.value("", VersionAttribute).toString().toInt(); return ver; } else return 1; } break; // Not handled case QXmlStreamReader::EndElement: case QXmlStreamReader::NoToken: case QXmlStreamReader::Invalid: case QXmlStreamReader::StartDocument: case QXmlStreamReader::EndDocument: case QXmlStreamReader::Characters: case QXmlStreamReader::Comment: case QXmlStreamReader::DTD: case QXmlStreamReader::EntityReference: case QXmlStreamReader::ProcessingInstruction: break; } } return 0; } cppcheck-1.61/gui/xmlreport.h000066400000000000000000000034451217722632100162230ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #ifndef XML_REPORT_H #define XML_REPORT_H #include #include #include "report.h" #include "erroritem.h" class QObject; /// @addtogroup GUI /// @{ /** * @brief Base class for XML report classes. */ class XmlReport : public Report { public: XmlReport(const QString &filename); /** * @brief Read contents of the report file. */ virtual QList Read() = 0; /** * @brief Quote the message. * @param message Message to quote. * @return quoted message. */ static QString quoteMessage(const QString &message); /** * @brief Unquote the message. * @param message Message to quote. * @return quoted message. */ static QString unquoteMessage(const QString &message); /** * @brief Get the XML report format version from the file. * @param filename Filename of the report file. * @return XML report format version or 0 if error happened. */ static int determineVersion(const QString &filename); }; /// @} #endif // XML_REPORT_H cppcheck-1.61/gui/xmlreportv1.cpp000066400000000000000000000135251217722632100170250ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include #include #include #include #include #include "report.h" #include "erroritem.h" #include "xmlreport.h" #include "xmlreportv1.h" static const char ResultElementName[] = "results"; static const char ErrorElementName[] = "error"; static const char FilenameAttribute[] = "file"; static const char LineAttribute[] = "line"; static const char IdAttribute[] = "id"; static const char SeverityAttribute[] = "severity"; static const char MsgAttribute[] = "msg"; XmlReportV1::XmlReportV1(const QString &filename) : XmlReport(filename), mXmlReader(NULL), mXmlWriter(NULL) { } XmlReportV1::~XmlReportV1() { delete mXmlReader; delete mXmlWriter; } bool XmlReportV1::Create() { if (Report::Create()) { mXmlWriter = new QXmlStreamWriter(Report::GetFile()); return true; } return false; } bool XmlReportV1::Open() { if (Report::Open()) { mXmlReader = new QXmlStreamReader(Report::GetFile()); return true; } return false; } void XmlReportV1::WriteHeader() { mXmlWriter->setAutoFormatting(true); mXmlWriter->writeStartDocument(); mXmlWriter->writeStartElement(ResultElementName); } void XmlReportV1::WriteFooter() { mXmlWriter->writeEndElement(); mXmlWriter->writeEndDocument(); } void XmlReportV1::WriteError(const ErrorItem &error) { /* Error example from the core program in xml The callstack seems to be ignored here as well, instead last item of the stack is used */ // Don't write inconclusive errors to XML V1 if (error.inconclusive) return; mXmlWriter->writeStartElement(ErrorElementName); QString file = QDir::toNativeSeparators(error.files[error.files.size() - 1]); file = XmlReport::quoteMessage(file); mXmlWriter->writeAttribute(FilenameAttribute, file); const QString line = QString::number(error.lines[error.lines.size() - 1]); mXmlWriter->writeAttribute(LineAttribute, line); mXmlWriter->writeAttribute(IdAttribute, error.errorId); // Don't localize severity so we can read these files mXmlWriter->writeAttribute(SeverityAttribute, GuiSeverity::toString(error.severity)); const QString message = XmlReport::quoteMessage(error.message); mXmlWriter->writeAttribute(MsgAttribute, message); mXmlWriter->writeEndElement(); } QList XmlReportV1::Read() { QList errors; bool insideResults = false; if (!mXmlReader) { qDebug() << "You must Open() the file before reading it!"; return errors; } while (!mXmlReader->atEnd()) { switch (mXmlReader->readNext()) { case QXmlStreamReader::StartElement: if (mXmlReader->name() == ResultElementName) insideResults = true; // Read error element from inside result element if (insideResults && mXmlReader->name() == ErrorElementName) { ErrorItem item = ReadError(mXmlReader); errors.append(item); } break; case QXmlStreamReader::EndElement: if (mXmlReader->name() == ResultElementName) insideResults = false; break; // Not handled case QXmlStreamReader::NoToken: case QXmlStreamReader::Invalid: case QXmlStreamReader::StartDocument: case QXmlStreamReader::EndDocument: case QXmlStreamReader::Characters: case QXmlStreamReader::Comment: case QXmlStreamReader::DTD: case QXmlStreamReader::EntityReference: case QXmlStreamReader::ProcessingInstruction: break; } } return errors; } ErrorItem XmlReportV1::ReadError(QXmlStreamReader *reader) { ErrorItem item; if (reader->name().toString() == ErrorElementName) { QXmlStreamAttributes attribs = reader->attributes(); QString file = attribs.value("", FilenameAttribute).toString(); file = XmlReport::unquoteMessage(file); item.file = file; item.files.push_back(file); const int line = attribs.value("", LineAttribute).toString().toUInt(); item.lines.push_back(line); item.errorId = attribs.value("", IdAttribute).toString(); item.severity = GuiSeverity::fromString(attribs.value("", SeverityAttribute).toString()); // NOTE: This duplicates the message to Summary-field. But since // old XML format doesn't have separate summary and verbose messages // we must add same message to both data so it shows up in GUI. // Check if there is full stop and cut the summary to it. QString summary = attribs.value("", MsgAttribute).toString(); const int ind = summary.indexOf('.'); if (ind != -1) summary = summary.left(ind + 1); item.summary = XmlReport::unquoteMessage(summary); QString message = attribs.value("", MsgAttribute).toString(); item.message = XmlReport::unquoteMessage(message); } return item; } cppcheck-1.61/gui/xmlreportv1.h000066400000000000000000000044101217722632100164630ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #ifndef XML_REPORTV1_H #define XML_REPORTV1_H #include #include #include #include "xmlreport.h" /// @addtogroup GUI /// @{ /** * @brief XML file report version 1. * This report outputs XML-formatted report, version 1. The XML format must match command * line version's XML output. */ class XmlReportV1 : public XmlReport { public: XmlReportV1(const QString &filename); virtual ~XmlReportV1(); /** * @brief Create the report (file). * @return true if succeeded, false if file could not be created. */ virtual bool Create(); /** * @brief Open existing report file. */ bool Open(); /** * @brief Write report header. */ virtual void WriteHeader(); /** * @brief Write report footer. */ virtual void WriteFooter(); /** * @brief Write error to report. * @param error Error data. */ virtual void WriteError(const ErrorItem &error); /** * @brief Read contents of the report file. */ virtual QList Read(); protected: /** * @brief Read and parse error item from XML stream. * @param reader XML stream reader to use. */ ErrorItem ReadError(QXmlStreamReader *reader); private: /** * @brief XML stream reader for reading the report in XML format. */ QXmlStreamReader *mXmlReader; /** * @brief XML stream writer for writing the report in XML format. */ QXmlStreamWriter *mXmlWriter; }; /// @} #endif // XML_REPORTV1_H cppcheck-1.61/gui/xmlreportv2.cpp000066400000000000000000000176151217722632100170320ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #include #include #include #include #include #include #include "report.h" #include "erroritem.h" #include "xmlreport.h" #include "xmlreportv2.h" #include "cppcheck.h" static const char ResultElementName[] = "results"; static const char CppcheckElementName[] = "cppcheck"; static const char ErrorElementName[] = "error"; static const char ErrorsElementName[] = "errors"; static const char LocationElementName[] = "location"; static const char FilenameAttribute[] = "file"; static const char LineAttribute[] = "line"; static const char IdAttribute[] = "id"; static const char SeverityAttribute[] = "severity"; static const char MsgAttribute[] = "msg"; static const char VersionAttribute[] = "version"; static const char VerboseAttribute[] = "verbose"; XmlReportV2::XmlReportV2(const QString &filename) : XmlReport(filename), mXmlReader(NULL), mXmlWriter(NULL) { } XmlReportV2::~XmlReportV2() { delete mXmlReader; delete mXmlWriter; } bool XmlReportV2::Create() { if (Report::Create()) { mXmlWriter = new QXmlStreamWriter(Report::GetFile()); return true; } return false; } bool XmlReportV2::Open() { if (Report::Open()) { mXmlReader = new QXmlStreamReader(Report::GetFile()); return true; } return false; } void XmlReportV2::WriteHeader() { mXmlWriter->setAutoFormatting(true); mXmlWriter->writeStartDocument(); mXmlWriter->writeStartElement(ResultElementName); mXmlWriter->writeAttribute(VersionAttribute, QString::number(2)); mXmlWriter->writeStartElement(CppcheckElementName); mXmlWriter->writeAttribute(VersionAttribute, QString(CppCheck::version())); mXmlWriter->writeEndElement(); mXmlWriter->writeStartElement(ErrorsElementName); } void XmlReportV2::WriteFooter() { mXmlWriter->writeEndElement(); // errors mXmlWriter->writeEndElement(); // results mXmlWriter->writeEndDocument(); } void XmlReportV2::WriteError(const ErrorItem &error) { /* Error example from the core program in xml */ // Don't write inconclusive errors to XML V2 until we decide the format if (error.inconclusive) return; mXmlWriter->writeStartElement(ErrorElementName); mXmlWriter->writeAttribute(IdAttribute, error.errorId); // Don't localize severity so we can read these files mXmlWriter->writeAttribute(SeverityAttribute, GuiSeverity::toString(error.severity)); const QString summary = XmlReport::quoteMessage(error.summary); mXmlWriter->writeAttribute(MsgAttribute, summary); const QString message = XmlReport::quoteMessage(error.message); mXmlWriter->writeAttribute(VerboseAttribute, message); for (int i = 0; i < error.files.count(); i++) { mXmlWriter->writeStartElement(LocationElementName); QString file = QDir::toNativeSeparators(error.files[i]); file = XmlReport::quoteMessage(file); mXmlWriter->writeAttribute(FilenameAttribute, file); const QString line = QString::number(error.lines[i]); mXmlWriter->writeAttribute(LineAttribute, line); mXmlWriter->writeEndElement(); } mXmlWriter->writeEndElement(); } QList XmlReportV2::Read() { QList errors; bool insideResults = false; if (!mXmlReader) { qDebug() << "You must Open() the file before reading it!"; return errors; } while (!mXmlReader->atEnd()) { switch (mXmlReader->readNext()) { case QXmlStreamReader::StartElement: if (mXmlReader->name() == ResultElementName) insideResults = true; // Read error element from inside result element if (insideResults && mXmlReader->name() == ErrorElementName) { ErrorItem item = ReadError(mXmlReader); errors.append(item); } break; case QXmlStreamReader::EndElement: if (mXmlReader->name() == ResultElementName) insideResults = false; break; // Not handled case QXmlStreamReader::NoToken: case QXmlStreamReader::Invalid: case QXmlStreamReader::StartDocument: case QXmlStreamReader::EndDocument: case QXmlStreamReader::Characters: case QXmlStreamReader::Comment: case QXmlStreamReader::DTD: case QXmlStreamReader::EntityReference: case QXmlStreamReader::ProcessingInstruction: break; } } return errors; } ErrorItem XmlReportV2::ReadError(QXmlStreamReader *reader) { /* Error example from the core program in xml */ ErrorItem item; // Read error element from inside errors element if (mXmlReader->name() == ErrorElementName) { QXmlStreamAttributes attribs = reader->attributes(); item.errorId = attribs.value("", IdAttribute).toString(); item.severity = GuiSeverity::fromString(attribs.value("", SeverityAttribute).toString()); const QString summary = attribs.value("", MsgAttribute).toString(); item.summary = XmlReport::unquoteMessage(summary); const QString message = attribs.value("", VerboseAttribute).toString(); item.message = XmlReport::unquoteMessage(message); } bool errorRead = false; while (!errorRead && !mXmlReader->atEnd()) { switch (mXmlReader->readNext()) { case QXmlStreamReader::StartElement: // Read location element from inside error element if (mXmlReader->name() == LocationElementName) { QXmlStreamAttributes attribs = mXmlReader->attributes(); QString file = attribs.value("", FilenameAttribute).toString(); file = XmlReport::unquoteMessage(file); if (item.file.isEmpty()) item.file = file; item.files.push_back(file); const int line = attribs.value("", LineAttribute).toString().toUInt(); item.lines.push_back(line); } break; case QXmlStreamReader::EndElement: if (mXmlReader->name() == ErrorElementName) errorRead = true; break; // Not handled case QXmlStreamReader::NoToken: case QXmlStreamReader::Invalid: case QXmlStreamReader::StartDocument: case QXmlStreamReader::EndDocument: case QXmlStreamReader::Characters: case QXmlStreamReader::Comment: case QXmlStreamReader::DTD: case QXmlStreamReader::EntityReference: case QXmlStreamReader::ProcessingInstruction: break; } } return item; } cppcheck-1.61/gui/xmlreportv2.h000066400000000000000000000044201217722632100164650ustar00rootroot00000000000000/* * Cppcheck - A tool for static C/C++ code analysis * Copyright (C) 2007-2013 Daniel Marjamäki and Cppcheck team. * * 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 . */ #ifndef XML_REPORTV2_H #define XML_REPORTV2_H #include #include #include #include #include "xmlreport.h" /// @addtogroup GUI /// @{ /** * @brief XML file report version 2. * This report outputs XML-formatted report. The XML format must match command * line version's XML output. */ class XmlReportV2 : public XmlReport { public: XmlReportV2(const QString &filename); virtual ~XmlReportV2(); /** * @brief Create the report (file). * @return true if succeeded, false if file could not be created. */ virtual bool Create(); /** * @brief Open existing report file. */ bool Open(); /** * @brief Write report header. */ virtual void WriteHeader(); /** * @brief Write report footer. */ virtual void WriteFooter(); /** * @brief Write error to report. * @param error Error data. */ virtual void WriteError(const ErrorItem &error); /** * @brief Read contents of the report file. */ virtual QList Read(); protected: /** * @brief Read and parse error item from XML stream. * @param reader XML stream reader to use. */ ErrorItem ReadError(QXmlStreamReader *reader); private: /** * @brief XML stream reader for reading the report in XML format. */ QXmlStreamReader *mXmlReader; /** * @brief XML stream writer for writing the report in XML format. */ QXmlStreamWriter *mXmlWriter; }; /// @} #endif // XML_REPORTV2_H cppcheck-1.61/htdocs/000077500000000000000000000000001217722632100145105ustar00rootroot00000000000000cppcheck-1.61/htdocs/.htaccess000066400000000000000000000613031217722632100163110ustar00rootroot00000000000000# Apache Configuration File # https://github.com/h5bp/server-configs-apache # (!) Using `.htaccess` files slows down Apache, therefore, if you have access # to the main server config file (usually called `httpd.conf`), you should add # this logic there: http://httpd.apache.org/docs/current/howto/htaccess.html. # ############################################################################## # # CROSS-ORIGIN RESOURCE SHARING (CORS) # # ############################################################################## # ------------------------------------------------------------------------------ # | Cross-domain AJAX requests | # ------------------------------------------------------------------------------ # Enable cross-origin AJAX requests. # http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity # http://enable-cors.org/ # # Header set Access-Control-Allow-Origin "*" # # ------------------------------------------------------------------------------ # | CORS-enabled images | # ------------------------------------------------------------------------------ # Send the CORS header for images when browsers request it. # https://developer.mozilla.org/en/CORS_Enabled_Image # http://blog.chromium.org/2011/07/using-cross-domain-images-in-webgl-and.html # http://hacks.mozilla.org/2011/11/using-cors-to-load-webgl-textures-from-cross-domain-images/ SetEnvIf Origin ":" IS_CORS Header set Access-Control-Allow-Origin "*" env=IS_CORS # ------------------------------------------------------------------------------ # | Web fonts access | # ------------------------------------------------------------------------------ # Allow access from all domains for web fonts Header set Access-Control-Allow-Origin "*" # ############################################################################## # # ERRORS # # ############################################################################## # ------------------------------------------------------------------------------ # | 404 error prevention for non-existing redirected folders | # ------------------------------------------------------------------------------ # Prevent Apache from returning a 404 error for a rewrite if a directory # with the same name does not exist. # http://httpd.apache.org/docs/current/content-negotiation.html#multiviews # http://www.webmasterworld.com/apache/3808792.htm Options -MultiViews # ------------------------------------------------------------------------------ # | Custom error messages / pages | # ------------------------------------------------------------------------------ # You can customize what Apache returns to the client in case of an error (see # http://httpd.apache.org/docs/current/mod/core.html#errordocument), e.g.: ErrorDocument 404 /404.html # ############################################################################## # # INTERNET EXPLORER # # ############################################################################## # ------------------------------------------------------------------------------ # | Better website experience | # ------------------------------------------------------------------------------ # Force IE to render pages in the highest available mode in the various # cases when it may not: http://hsivonen.iki.fi/doctype/ie-mode.pdf. Header set X-UA-Compatible "IE=edge" # `mod_headers` can't match based on the content-type, however, we only # want to send this header for HTML pages and not for the other resources Header unset X-UA-Compatible # ------------------------------------------------------------------------------ # | Cookie setting from iframes | # ------------------------------------------------------------------------------ # Allow cookies to be set from iframes in IE. # # Header set P3P "policyref=\"/w3c/p3p.xml\", CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"" # # ------------------------------------------------------------------------------ # | Screen flicker | # ------------------------------------------------------------------------------ # Stop screen flicker in IE on CSS rollovers (this only works in # combination with the `ExpiresByType` directives for images from below). # BrowserMatch "MSIE" brokenvary=1 # BrowserMatch "Mozilla/4.[0-9]{2}" brokenvary=1 # BrowserMatch "Opera" !brokenvary # SetEnvIf brokenvary 1 force-no-vary # ############################################################################## # # MIME TYPES AND ENCODING # # ############################################################################## # ------------------------------------------------------------------------------ # | Proper MIME types for all files | # ------------------------------------------------------------------------------ # Audio AddType audio/mp4 m4a f4a f4b AddType audio/ogg oga ogg # JavaScript # Normalize to standard type (it's sniffed in IE anyways): # http://tools.ietf.org/html/rfc4329#section-7.2 AddType application/javascript js AddType application/json json # Video AddType video/mp4 mp4 m4v f4v f4p AddType video/ogg ogv AddType video/webm webm AddType video/x-flv flv # Web fonts AddType application/font-woff woff AddType application/vnd.ms-fontobject eot # Browsers usually ignore the font MIME types and sniff the content, # however, Chrome shows a warning if other MIME types are used for the # following fonts. AddType application/x-font-ttf ttc ttf AddType font/opentype otf # Make SVGZ fonts work on iPad: # https://twitter.com/FontSquirrel/status/14855840545 AddType image/svg+xml svg svgz AddEncoding gzip svgz # Other AddType application/octet-stream safariextz AddType application/x-chrome-extension crx AddType application/x-opera-extension oex AddType application/x-shockwave-flash swf AddType application/x-web-app-manifest+json webapp AddType application/x-xpinstall xpi AddType application/xml atom rdf rss xml AddType image/webp webp AddType image/x-icon ico AddType text/cache-manifest appcache manifest AddType text/vtt vtt AddType text/x-component htc AddType text/x-vcard vcf # ------------------------------------------------------------------------------ # | UTF-8 encoding | # ------------------------------------------------------------------------------ # Use UTF-8 encoding for anything served as `text/html` or `text/plain`. AddDefaultCharset utf-8 # Force UTF-8 for certain file formats. AddCharset utf-8 .atom .css .js .json .rss .vtt .webapp .xml # ############################################################################## # # URL REWRITES # # ############################################################################## # ------------------------------------------------------------------------------ # | Rewrite engine | # ------------------------------------------------------------------------------ # Turning on the rewrite engine and enabling the `FollowSymLinks` option is # necessary for the following directives to work. # If your web host doesn't allow the `FollowSymlinks` option, you may need to # comment it out and use `Options +SymLinksIfOwnerMatch` but, be aware of the # performance impact: http://httpd.apache.org/docs/current/misc/perf-tuning.html#symlinks # Also, some cloud hosting services require `RewriteBase` to be set: # http://www.rackspace.com/knowledge_center/frequently-asked-question/why-is-mod-rewrite-not-working-on-my-site Options +FollowSymlinks # Options +SymLinksIfOwnerMatch RewriteEngine On # RewriteBase / # Redirect "democlient.html" to the new place... Redirect permanent /democlient.html http://cppcheck.sourceforge.net/demo/ # Redirect "devinfo.html" to the new place... Redirect permanent /devinfo.html http://cppcheck.sourceforge.net/devinfo/ # Redirect doxyoutput, coverage- and cpd report to the new place... Redirect permanent /doxyoutput/ http://cppcheck.sourceforge.net/devinfo/doxyoutput/ Redirect permanent /doxygen-errors.txt http://cppcheck.sourceforge.net/devinfo/doxygen-errors.txt Redirect permanent /coverage_report/ http://cppcheck.sourceforge.net/devinfo/coverage_report/ Redirect permanent /cpd.txt http://cppcheck.sourceforge.net/devinfo/cpd.txt # ------------------------------------------------------------------------------ # | Suppressing / Forcing the "www." at the beginning of URLs | # ------------------------------------------------------------------------------ # The same content should never be available under two different URLs especially # not with and without "www." at the beginning. This can cause SEO problems # (duplicate content), therefore, you should choose one of the alternatives and # redirect the other one. # By default option 1 (no "www.") is activated: # http://no-www.org/faq.php?q=class_b # If you'd prefer to use option 2, just comment out all the lines from option 1 # and uncomment the ones from option 2. # IMPORTANT: NEVER USE BOTH RULES AT THE SAME TIME! # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Option 1: rewrite www.example.com → example.com RewriteCond %{HTTPS} !=on RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC] RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L] # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Option 2: rewrite example.com → www.example.com # Be aware that the following might not be a good idea if you use "real" # subdomains for certain parts of your website. # # RewriteCond %{HTTPS} !=on # RewriteCond %{HTTP_HOST} !^www\..+$ [NC] # RewriteCond %{HTTP_HOST} !=localhost [NC] # RewriteCond %{HTTP_HOST} !=127.0.0.1 # RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L] # # ############################################################################## # # SECURITY # # ############################################################################## # ------------------------------------------------------------------------------ # | Content Security Policy (CSP) | # ------------------------------------------------------------------------------ # You can mitigate the risk of cross-site scripting and other content-injection # attacks by setting a Content Security Policy which whitelists trusted sources # of content for your site. # The example header below allows ONLY scripts that are loaded from the current # site's origin (no inline scripts, no CDN, etc). This almost certainly won't # work as-is for your site! # To get all the details you'll need to craft a reasonable policy for your site, # read: http://html5rocks.com/en/tutorials/security/content-security-policy (or # see the specification: http://w3.org/TR/CSP). # # Header set Content-Security-Policy "script-src 'self'; object-src 'self'" # # Header unset Content-Security-Policy # # # ------------------------------------------------------------------------------ # | File access | # ------------------------------------------------------------------------------ # Block access to directories without a default document. # Usually you should leave this uncommented because you shouldn't allow anyone # to surf through every directory on your server (which may includes rather # private places like the CMS's directories). Options -Indexes # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Block access to hidden files and directories. # This includes directories used by version control systems such as Git and SVN. RewriteCond %{SCRIPT_FILENAME} -d [OR] RewriteCond %{SCRIPT_FILENAME} -f RewriteRule "(^|/)\." - [F] # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Block access to backup and source files. # These files may be left by some text editors and can pose a great security # danger when anyone has access to them. Order allow,deny Deny from all Satisfy All # ------------------------------------------------------------------------------ # | Secure Sockets Layer (SSL) | # ------------------------------------------------------------------------------ # Rewrite secure requests properly to prevent SSL certificate warnings, e.g.: # prevent `https://www.example.com` when your certificate only allows # `https://secure.example.com`. # # RewriteCond %{SERVER_PORT} !^443 # RewriteRule ^ https://example-domain-please-change-me.com%{REQUEST_URI} [R=301,L] # # ------------------------------------------------------------------------------ # | HTTP Strict Transport Security (HSTS) | # ------------------------------------------------------------------------------ # Force client-side SSL redirection. # If a user types "example.com" in his browser, the above rule will redirect # him to the secure version of the site. That still leaves a window of oppor- # tunity (the initial HTTP connection) for an attacker to downgrade or redirect # the request. The following header ensures that browser will ONLY connect to # your server via HTTPS, regardless of what the users type in the address bar. # http://tools.ietf.org/html/draft-ietf-websec-strict-transport-sec-14#section-6.1 # http://www.html5rocks.com/en/tutorials/security/transport-layer-security/ # (!) Remove the `includeSubDomains` optional directive if the subdomains are # not using HTTPS. # # Header set Strict-Transport-Security "max-age=16070400; includeSubDomains" # # ------------------------------------------------------------------------------ # | Server software information | # ------------------------------------------------------------------------------ # Avoid displaying the exact Apache version number, the description of the # generic OS-type and the information about Apache's compiled-in modules. # ADD THIS DIRECTIVE IN THE `httpd.conf` AS IT WILL NOT WORK IN THE `.htaccess`! # ServerTokens Prod # ############################################################################## # # WEB PERFORMANCE # # ############################################################################## # ------------------------------------------------------------------------------ # | Compression | # ------------------------------------------------------------------------------ # Force compression for mangled headers. # http://developer.yahoo.com/blogs/ydn/posts/2010/12/pushing-beyond-gzipping SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding # Compress all output labeled with one of the following MIME-types # (for Apache versions below 2.3.7, you don't need to enable `mod_filter` # and can remove the `` and `` lines # as `AddOutputFilterByType` is still in the core directives). # AddOutputFilterByType DEFLATE application/atom+xml \ application/javascript \ application/json \ application/rss+xml \ application/vnd.ms-fontobject \ application/x-font-ttf \ application/x-web-app-manifest+json \ application/xhtml+xml \ application/xml \ font/opentype \ image/svg+xml \ image/x-icon \ text/css \ text/html \ text/plain \ text/x-component \ text/xml # # ------------------------------------------------------------------------------ # | Content transformations | # ------------------------------------------------------------------------------ # Prevent some of the mobile network providers from modifying the content of # your site: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.5. # # Header set Cache-Control "no-transform" # # ------------------------------------------------------------------------------ # | ETag removal | # ------------------------------------------------------------------------------ # Since we're sending far-future expires headers (see below), ETags can # be removed: http://developer.yahoo.com/performance/rules.html#etags. # `FileETag None` is not enough for every server. Header unset ETag FileETag None # ------------------------------------------------------------------------------ # | Expires headers (for better cache control) | # ------------------------------------------------------------------------------ # The following expires headers are set pretty far in the future. If you don't # control versioning with filename-based cache busting, consider lowering the # cache time for resources like CSS and JS to something like 1 week. ExpiresActive on ExpiresDefault "access plus 1 month" # CSS ExpiresByType text/css "access plus 1 week" # Data interchange ExpiresByType application/json "access plus 0 seconds" ExpiresByType application/xml "access plus 0 seconds" ExpiresByType text/xml "access plus 0 seconds" # Favicon (cannot be renamed!) ExpiresByType image/x-icon "access plus 1 week" # HTML components (HTCs) ExpiresByType text/x-component "access plus 1 month" # HTML ExpiresByType text/html "access plus 0 seconds" # JavaScript ExpiresByType application/javascript "access plus 1 week" # Manifest files ExpiresByType application/x-web-app-manifest+json "access plus 0 seconds" ExpiresByType text/cache-manifest "access plus 0 seconds" # Media ExpiresByType audio/ogg "access plus 1 month" ExpiresByType image/gif "access plus 1 month" ExpiresByType image/jpeg "access plus 1 month" ExpiresByType image/png "access plus 1 month" ExpiresByType video/mp4 "access plus 1 month" ExpiresByType video/ogg "access plus 1 month" ExpiresByType video/webm "access plus 1 month" # Web feeds ExpiresByType application/atom+xml "access plus 1 hour" ExpiresByType application/rss+xml "access plus 1 hour" # Web fonts ExpiresByType application/font-woff "access plus 1 month" ExpiresByType application/vnd.ms-fontobject "access plus 1 month" ExpiresByType application/x-font-ttf "access plus 1 month" ExpiresByType font/opentype "access plus 1 month" ExpiresByType image/svg+xml "access plus 1 month" # ------------------------------------------------------------------------------ # | Filename-based cache busting | # ------------------------------------------------------------------------------ # If you're not using a build process to manage your filename version revving, # you might want to consider enabling the following directives to route all # requests such as `/css/style.12345.css` to `/css/style.css`. # To understand why this is important and a better idea than `*.css?v231`, read: # http://stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring # # RewriteCond %{REQUEST_FILENAME} !-f # RewriteRule ^(.+)\.(\d+)\.(js|css|png|jpg|gif)$ $1.$3 [L] # # ------------------------------------------------------------------------------ # | File concatenation | # ------------------------------------------------------------------------------ # Allow concatenation from within specific CSS and JS files, e.g.: # Inside of `script.combined.js` you could have # # # and they would be included into this single file. # # # Options +Includes # AddOutputFilterByType INCLUDES application/javascript application/json # SetOutputFilter INCLUDES # # # Options +Includes # AddOutputFilterByType INCLUDES text/css # SetOutputFilter INCLUDES # # # ------------------------------------------------------------------------------ # | Persistent connections | # ------------------------------------------------------------------------------ # Allow multiple requests to be sent over the same TCP connection: # http://httpd.apache.org/docs/current/en/mod/core.html#keepalive. # Enable if you serve a lot of static content but, be aware of the # possible disadvantages! # # Header set Connection Keep-Alive # cppcheck-1.61/htdocs/404.html000066400000000000000000000105661217722632100157150ustar00rootroot00000000000000 Cppcheck - Page Not Found :(

Not found :(

Sorry, but the page you were trying to view does not exist.

It looks like this was the result of either:

  • a mistyped address
  • an out-of-date link
cppcheck-1.61/htdocs/archive/000077500000000000000000000000001217722632100161315ustar00rootroot00000000000000cppcheck-1.61/htdocs/archive/addfile.c000066400000000000000000000041271217722632100176710ustar00rootroot00000000000000#include #include #include #include #include "webarchive.h" const char *validate(const char *data) { int i; if (strncmp(data,"name=",5) != 0) return "invalid query string: must start with 'name='"; i = 5; while (isalnum(data[i])) i++; if (i == 5) return "invalid query string: no name"; if (i > 35) return "invalid query string: max name size is 32"; if (data[i] == '\0') return NULL; if (data[i] != '&') return "invalid query string: only alphanumeric characters are allowed in the name"; if (strncmp(data+i,"&data=",6)!=0) return "invalid query string"; i += 6; // TODO: check XML data.. return NULL; } int main() { const char *query_string = getenv("QUERY_STRING"); if (query_string == NULL) { generatepage("Internal error: empty/invalid data"); } else if (strlen(query_string) > MAX_LINE_LEN) { char errmsg[100] = {0}; sprintf(errmsg, "Internal error: data size limit exceeded (%i)", MAX_LINE_LEN); generatepage(errmsg); } else if (NULL != validate(query_string)) { generatepage(validate(query_string)); } else { char data[MAX_LINE_LEN] = {0}; unencode(query_string, data); if (NULL != validate(data)) { generatepage(validate(data)); } else { char *olddata[MAX_RECORDS] = {0}; olddata[0] = data; if (!readdata(&olddata[1], MAX_RECORDS-1)) { generatepage("Failed to add file (access denied). Try again."); return EXIT_SUCCESS; } sortdata(olddata, MAX_RECORDS); FILE *f = fopen("data.txt", "wt"); if (f == NULL) { generatepage("Failed to add file (access denied). Try again."); return EXIT_SUCCESS; } for (int i = 0; i < MAX_RECORDS && olddata[i]; i++) fprintf(f, "%s\n", olddata[i]); fclose(f); generatepage("saved."); } } return EXIT_SUCCESS; } cppcheck-1.61/htdocs/archive/createzip.c000066400000000000000000000041601217722632100202640ustar00rootroot00000000000000#include #include #include "webarchive.h" #include "miniz.c" #define ALL_ZIP "all.zip" int main() { mz_zip_archive zip_archive = {0}; FILE *f = fopen("data.txt", "rt"); if (f == NULL) { generatepage("failed to load data"); return EXIT_FAILURE; } int first = 1; char line[MAX_LINE_LEN] = {0}; while (fgets(line,sizeof(line)-2,f)) { char data[MAX_LINE_LEN] = {0}; unencode(line,data); const char *xmldata = strstr(data, "&data="); xmldata = xmldata ? (xmldata + 6) : ""; char name[MAX_NAME_LEN+20]; if (strstr(xmldata, "")) sprintf(name, "archive/%s.rule", getname(line)); else sprintf(name, "archive/%s.cfg", getname(line)); if (first == 1) { first = 0; if (!mz_zip_writer_init_file(&zip_archive, ALL_ZIP, 0)) { generatepage("internal error: init_file failed"); return EXIT_FAILURE; } if (!mz_zip_writer_add_mem_ex(&zip_archive, name, xmldata, strlen(xmldata), NULL, 0U, MZ_BEST_COMPRESSION, 0, 0)) { generatepage("internal error: add_mem_ex failed"); return EXIT_FAILURE; } if (!mz_zip_writer_finalize_archive(&zip_archive)) { generatepage("internal error: finalize_archive failed"); return EXIT_FAILURE; } if (!mz_zip_writer_end(&zip_archive)) { generatepage("internal error: writer_end failed"); return EXIT_FAILURE; } } else if (!mz_zip_add_mem_to_archive_file_in_place(ALL_ZIP, name, xmldata, strlen(xmldata), NULL, 0U, MZ_BEST_COMPRESSION)) { generatepage("failed to add data"); return EXIT_FAILURE; } } fclose(f); f = fopen("all.zip","rb"); if (!f) { generatepage("internal error: failed to load zip"); return EXIT_FAILURE; } puts("Content-type: application/zip\r\n\r"); int c; while ((c = fgetc(f)) != EOF) putc(c,stdout); return EXIT_SUCCESS; } cppcheck-1.61/htdocs/archive/deletefile.c000066400000000000000000000026731217722632100204070ustar00rootroot00000000000000#include #include #include #include #include "webarchive.h" int main() { const char *query_string = getenv("QUERY_STRING"); if (query_string == NULL) { generatepage("Internal error: invalid request"); return EXIT_SUCCESS; } if (NULL != validate_name_version(query_string)) { generatepage(validate_name_version(query_string)); return EXIT_SUCCESS; } char *data[MAX_RECORDS] = {0}; if (!readdata(data, MAX_RECORDS)) { generatepage("Failed to delete file, try again"); return EXIT_SUCCESS; } sortdata(data, MAX_RECORDS); char name[MAX_NAME_LEN] = {0}; strcpy(name, getname(query_string)); int index = -1; for (int i = 0; i < MAX_RECORDS && data[i]; i++) { if (strcmp(name, getname(data[i])) == 0) { index = i; break; } } if (index == -1) { generatepage("File not found"); return EXIT_SUCCESS; } FILE *f = fopen("data.txt", "wt"); if (f == NULL) { generatepage("Failed to delete file (access denied)"); return EXIT_SUCCESS; } int deleted = 0; for (int i = 0; i < MAX_RECORDS && data[i]; i++) { if (i != index) fprintf(f, "%s\n", data[i]); else deleted = 1; } fclose(f); generatepage(deleted ? "File deleted" : "Failed to delete file"); return EXIT_SUCCESS; } cppcheck-1.61/htdocs/archive/edit.c000066400000000000000000000036051217722632100172260ustar00rootroot00000000000000#include #include #include #include #include "webarchive.h" int main() { const char *query_string = getenv("QUERY_STRING"); if (query_string == NULL) { generatepage("Internal error: invalid request"); return EXIT_SUCCESS; } if (NULL != validate_name_version(query_string)) { generatepage(validate_name_version(query_string)); return EXIT_SUCCESS; } char *data[MAX_RECORDS] = {0}; if (!readdata(data, MAX_RECORDS)) { generatepage("Failed to read file data"); return EXIT_SUCCESS; } char name[MAX_NAME_LEN] = {0}; strcpy(name, getname(query_string)); int index = -1; for (int i = 0; i < MAX_RECORDS && data[i]; i++) { if (strcmp(name, getname(data[i])) == 0) { index = i; break; } } if (index == -1) { generatepage("File not found"); return EXIT_SUCCESS; } int version = getversion(data[index]); if (version < 1) version = 1; const char *olddata = strstr(data[index], "&data="); if (olddata) { char *temp = malloc(strlen(olddata+6)); unencode(olddata+6, temp); olddata = temp; } else olddata = ""; puts("Content-type: text/html\r\n\r\n"); puts(""); puts(""); puts("
"); printf(" \n",name); printf("
\n",1+version); printf("
\n",olddata); puts(" "); puts("
"); puts(""); puts(""); return EXIT_SUCCESS; } cppcheck-1.61/htdocs/archive/index.php000066400000000000000000000052641217722632100177600ustar00rootroot00000000000000 Cppcheck - Archive

Cppcheck - Archive

This archive is for useful Cppcheck rules and library configuration files.

If you have a rule or library configuration that you want to share, use this archive. Feel free to add any library or rule here.

Download all

cppcheck-1.61/htdocs/archive/miniz.c000066400000000000000000007432141217722632100174360ustar00rootroot00000000000000/* miniz.c v1.14 - public domain deflate/inflate, zlib-subset, ZIP reading/writing/appending, PNG writing See "unlicense" statement at the end of this file. Rich Geldreich , last updated May 20, 2012 Implements RFC 1950: http://www.ietf.org/rfc/rfc1950.txt and RFC 1951: http://www.ietf.org/rfc/rfc1951.txt Most API's defined in miniz.c are optional. For example, to disable the archive related functions just define MINIZ_NO_ARCHIVE_APIS, or to get rid of all stdio usage define MINIZ_NO_STDIO (see the list below for more macros). * Change History 5/20/12 v1.14 - MinGW32/64 GCC 4.6.1 compiler fixes: added MZ_FORCEINLINE, #include (thanks fermtect). 5/19/12 v1.13 - From jason@cornsyrup.org and kelwert@mtu.edu - Fix mz_crc32() so it doesn't compute the wrong CRC-32's when mz_ulong is 64-bit. Temporarily/locally slammed in "typedef unsigned long mz_ulong" and re-ran a randomized regression test on ~500k files. Eliminated a bunch of warnings when compiling with GCC 32-bit/64. Ran all examples, miniz.c, and tinfl.c through MSVC 2008's /analyze (static analysis) option and fixed all warnings (except for the silly "Use of the comma-operator in a tested expression.." analysis warning, which I purposely use to work around a MSVC compiler warning). Created 32-bit and 64-bit Codeblocks projects/workspace. Built and tested Linux executables. The codeblocks workspace is compatible with Linux+Win32/x64. Added miniz_tester solution/project, which is a useful little app derived from LZHAM's tester app that I use as part of the regression test. Ran miniz.c and tinfl.c through another series of regression testing on ~500,000 files and archives. Modified example5.c so it purposely disables a bunch of high-level functionality (MINIZ_NO_STDIO, etc.). (Thanks to corysama for the MINIZ_NO_STDIO bug report.) Fix ftell() usage in examples so they exit with an error on files which are too large (a limitation of the examples, not miniz itself). 4/12/12 v1.12 - More comments, added low-level example5.c, fixed a couple minor level_and_flags issues in the archive API's. level_and_flags can now be set to MZ_DEFAULT_COMPRESSION. Thanks to Bruce Dawson for the feedback/bug report. 5/28/11 v1.11 - Added statement from unlicense.org 5/27/11 v1.10 - Substantial compressor optimizations: Level 1 is now ~4x faster than before. The L1 compressor's throughput now varies between 70-110MB/sec. on a Core i7 (actual throughput varies depending on the type of data, and x64 vs. x86). Improved baseline L2-L9 compression perf. Also, greatly improved compression perf. issues on some file types. Refactored the compression code for better readability and maintainability. Added level 10 compression level (L10 has slightly better ratio than level 9, but could have a potentially large drop in throughput on some files). 5/15/11 v1.09 - Initial stable release. * Low-level Deflate/Inflate implementation notes: Compression: Use the "tdefl" API's. The compressor supports raw, static, and dynamic blocks, lazy or greedy parsing, match length filtering, RLE-only, and Huffman-only streams. It performs and compresses approximately as well as zlib. Decompression: Use the "tinfl" API's. The entire decompressor is implemented as a single function coroutine: see tinfl_decompress(). It supports decompression into a 32KB (or larger power of 2) wrapping buffer, or into a memory block large enough to hold the entire file. The low-level tdefl/tinfl API's do not make any use of dynamic memory allocation. * zlib-style API notes: miniz.c implements a fairly large subset of zlib. There's enough functionality present for it to be a drop-in zlib replacement in many apps: The z_stream struct, optional memory allocation callbacks deflateInit/deflateInit2/deflate/deflateReset/deflateEnd/deflateBound inflateInit/inflateInit2/inflate/inflateEnd compress, compress2, compressBound, uncompress CRC-32, Adler-32 - Using modern, minimal code size, CPU cache friendly routines. Supports raw deflate streams or standard zlib streams with adler-32 checking. Limitations: The callback API's are not implemented yet. No support for gzip headers or zlib static dictionaries. I've tried to closely emulate zlib's various flavors of stream flushing and return status codes, but there are no guarantees that miniz.c pulls this off perfectly. * PNG writing: See the tdefl_write_image_to_png_file_in_memory() function, originally written by Alex Evans. Supports 1-4 bytes/pixel images. * ZIP archive API notes: The ZIP archive API's where designed with simplicity and efficiency in mind, with just enough abstraction to get the job done with minimal fuss. There are simple API's to retrieve file information, read files from existing archives, create new archives, append new files to existing archives, or clone archive data from one archive to another. It supports archives located in memory or the heap, on disk (using stdio.h), or you can specify custom file read/write callbacks. - Archive reading: Just call this function to read a single file from a disk archive: void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint zip_flags); For more complex cases, use the "mz_zip_reader" functions. Upon opening an archive, the entire central directory is located and read as-is into memory, and subsequent file access only occurs when reading individual files. - Archives file scanning: The simple way is to use this function to scan a loaded archive for a specific file: int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags); The locate operation can optionally check file comments too, which (as one example) can be used to identify multiple versions of the same file in an archive. This function uses a simple linear search through the central directory, so it's not very fast. Alternately, you can iterate through all the files in an archive (using mz_zip_reader_get_num_files()) and retrieve detailed info on each file by calling mz_zip_reader_file_stat(). - Archive creation: Use the "mz_zip_writer" functions. The ZIP writer immediately writes compressed file data to disk and builds an exact image of the central directory in memory. The central directory image is written all at once at the end of the archive file when the archive is finalized. The archive writer can optionally align each file's local header and file data to any power of 2 alignment, which can be useful when the archive will be read from optical media. Also, the writer supports placing arbitrary data blobs at the very beginning of ZIP archives. Archives written using either feature are still readable by any ZIP tool. - Archive appending: The simple way to add a single file to an archive is to call this function: mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags); The archive will be created if it doesn't already exist, otherwise it'll be appended to. Note the appending is done in-place and is not an atomic operation, so if something goes wrong during the operation it's possible the archive could be left without a central directory (although the local file headers and file data will be fine, so the archive will be recoverable). For more complex archive modification scenarios: 1. The safest way is to use a mz_zip_reader to read the existing archive, cloning only those bits you want to preserve into a new archive using using the mz_zip_writer_add_from_zip_reader() function (which compiles the compressed file data as-is). When you're done, delete the old archive and rename the newly written archive, and you're done. This is safe but requires a bunch of temporary disk space or heap memory. 2. Or, you can convert an mz_zip_reader in-place to an mz_zip_writer using mz_zip_writer_init_from_reader(), append new files as needed, then finalize the archive which will write an updated central directory to the original archive. (This is basically what mz_zip_add_mem_to_archive_file_in_place() does.) There's a possibility that the archive's central directory could be lost with this method if anything goes wrong, though. - ZIP archive support limitations: No zip64 or spanning support. Extraction functions can only handle unencrypted, stored or deflated files. Requires streams capable of seeking. * This is a header file library, like stb_image.c. To get only a header file, either cut and paste the below header, or create miniz.h, #define MINIZ_HEADER_FILE_ONLY, and then include miniz.c from it. * Important: For best perf. be sure to customize the below macros for your target platform: #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1 #define MINIZ_LITTLE_ENDIAN 1 #define MINIZ_HAS_64BIT_REGISTERS 1 */ #ifndef MINIZ_HEADER_INCLUDED #define MINIZ_HEADER_INCLUDED #include #if !defined(MINIZ_NO_TIME) && !defined(MINIZ_NO_ARCHIVE_APIS) #include #endif // Defines to completely disable specific portions of miniz.c: // If all macros here are defined the only functionality remaining will be CRC-32, adler-32, tinfl, and tdefl. // Define MINIZ_NO_STDIO to disable all usage and any functions which rely on stdio for file I/O. //#define MINIZ_NO_STDIO // If MINIZ_NO_TIME is specified then the ZIP archive functions will not be able to get the current time, or // get/set file times. //#define MINIZ_NO_TIME // Define MINIZ_NO_ARCHIVE_APIS to disable all ZIP archive API's. //#define MINIZ_NO_ARCHIVE_APIS // Define MINIZ_NO_ARCHIVE_APIS to disable all writing related ZIP archive API's. //#define MINIZ_NO_ARCHIVE_WRITING_APIS // Define MINIZ_NO_ZLIB_APIS to remove all ZLIB-style compression/decompression API's. //#define MINIZ_NO_ZLIB_APIS // Define MINIZ_NO_ZLIB_COMPATIBLE_NAME to disable zlib names, to prevent conflicts against stock zlib. //#define MINIZ_NO_ZLIB_COMPATIBLE_NAMES // Define MINIZ_NO_MALLOC to disable all calls to malloc, free, and realloc. // Note if MINIZ_NO_MALLOC is defined then the user must always provide custom user alloc/free/realloc // callbacks to the zlib and archive API's, and a few stand-alone helper API's which don't provide custom user // functions (such as tdefl_compress_mem_to_heap() and tinfl_decompress_mem_to_heap()) won't work. //#define MINIZ_NO_MALLOC #if defined(_M_IX86) || defined(_M_X64) || defined(__i386__) || defined(__i386) || defined(__i486__) || defined(__i486) || defined(i386) || defined(__ia64__) || defined(__x86_64__) // MINIZ_X86_OR_X64_CPU is only used to help set the below macros. #define MINIZ_X86_OR_X64_CPU 1 #endif #if (__BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__) || MINIZ_X86_OR_X64_CPU // Set MINIZ_LITTLE_ENDIAN to 1 if the processor is little endian. #define MINIZ_LITTLE_ENDIAN 1 #endif #if MINIZ_X86_OR_X64_CPU // Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient integer loads and stores from unaligned addresses. #define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1 #endif #if defined(_M_X64) || defined(_WIN64) || defined(__MINGW64__) || defined(_LP64) || defined(__LP64__) || defined(__ia64__) || defined(__x86_64__) // Set MINIZ_HAS_64BIT_REGISTERS to 1 if operations on 64-bit integers are reasonably fast (and don't involve compiler generated calls to helper functions). #define MINIZ_HAS_64BIT_REGISTERS 1 #endif #ifdef __cplusplus extern "C" { #endif // ------------------- zlib-style API Definitions. // For more compatibility with zlib, miniz.c uses unsigned long for some parameters/struct members. Beware: mz_ulong can be either 32 or 64-bits! typedef unsigned long mz_ulong; // mz_free() internally uses the MZ_FREE() macro (which by default calls free() unless you've modified the MZ_MALLOC macro) to release a block allocated from the heap. void mz_free(void *p); #define MZ_ADLER32_INIT (1) // mz_adler32() returns the initial adler-32 value to use when called with ptr==NULL. mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len); #define MZ_CRC32_INIT (0) // mz_crc32() returns the initial CRC-32 value to use when called with ptr==NULL. mz_ulong mz_crc32(mz_ulong crc, const unsigned char *ptr, size_t buf_len); // Compression strategies. enum { MZ_DEFAULT_STRATEGY = 0, MZ_FILTERED = 1, MZ_HUFFMAN_ONLY = 2, MZ_RLE = 3, MZ_FIXED = 4 }; // Method #define MZ_DEFLATED 8 #ifndef MINIZ_NO_ZLIB_APIS // Heap allocation callbacks. // Note that mz_alloc_func parameter types purpsosely differ from zlib's: items/size is size_t, not unsigned long. typedef void *(*mz_alloc_func)(void *opaque, size_t items, size_t size); typedef void (*mz_free_func)(void *opaque, void *address); typedef void *(*mz_realloc_func)(void *opaque, void *address, size_t items, size_t size); #define MZ_VERSION "9.1.14" #define MZ_VERNUM 0x91E0 #define MZ_VER_MAJOR 9 #define MZ_VER_MINOR 1 #define MZ_VER_REVISION 14 #define MZ_VER_SUBREVISION 0 // Flush values. For typical usage you only need MZ_NO_FLUSH and MZ_FINISH. The other values are for advanced use (refer to the zlib docs). enum { MZ_NO_FLUSH = 0, MZ_PARTIAL_FLUSH = 1, MZ_SYNC_FLUSH = 2, MZ_FULL_FLUSH = 3, MZ_FINISH = 4, MZ_BLOCK = 5 }; // Return status codes. MZ_PARAM_ERROR is non-standard. enum { MZ_OK = 0, MZ_STREAM_END = 1, MZ_NEED_DICT = 2, MZ_ERRNO = -1, MZ_STREAM_ERROR = -2, MZ_DATA_ERROR = -3, MZ_MEM_ERROR = -4, MZ_BUF_ERROR = -5, MZ_VERSION_ERROR = -6, MZ_PARAM_ERROR = -10000 }; // Compression levels: 0-9 are the standard zlib-style levels, 10 is best possible compression (not zlib compatible, and may be very slow), MZ_DEFAULT_COMPRESSION=MZ_DEFAULT_LEVEL. enum { MZ_NO_COMPRESSION = 0, MZ_BEST_SPEED = 1, MZ_BEST_COMPRESSION = 9, MZ_UBER_COMPRESSION = 10, MZ_DEFAULT_LEVEL = 6, MZ_DEFAULT_COMPRESSION = -1 }; // Window bits #define MZ_DEFAULT_WINDOW_BITS 15 struct mz_internal_state; // Compression/decompression stream struct. typedef struct mz_stream_s { const unsigned char *next_in; // pointer to next byte to read unsigned int avail_in; // number of bytes available at next_in mz_ulong total_in; // total number of bytes consumed so far unsigned char *next_out; // pointer to next byte to write unsigned int avail_out; // number of bytes that can be written to next_out mz_ulong total_out; // total number of bytes produced so far char *msg; // error msg (unused) struct mz_internal_state *state; // internal state, allocated by zalloc/zfree mz_alloc_func zalloc; // optional heap allocation function (defaults to malloc) mz_free_func zfree; // optional heap free function (defaults to free) void *opaque; // heap alloc function user pointer int data_type; // data_type (unused) mz_ulong adler; // adler32 of the source or uncompressed data mz_ulong reserved; // not used } mz_stream; typedef mz_stream *mz_streamp; // Returns the version string of miniz.c. const char *mz_version(void); // mz_deflateInit() initializes a compressor with default options: // Parameters: // pStream must point to an initialized mz_stream struct. // level must be between [MZ_NO_COMPRESSION, MZ_BEST_COMPRESSION]. // level 1 enables a specially optimized compression function that's been optimized purely for performance, not ratio. // (This special func. is currently only enabled when MINIZ_USE_UNALIGNED_LOADS_AND_STORES and MINIZ_LITTLE_ENDIAN are defined.) // Return values: // MZ_OK on success. // MZ_STREAM_ERROR if the stream is bogus. // MZ_PARAM_ERROR if the input parameters are bogus. // MZ_MEM_ERROR on out of memory. int mz_deflateInit(mz_streamp pStream, int level); // mz_deflateInit2() is like mz_deflate(), except with more control: // Additional parameters: // method must be MZ_DEFLATED // window_bits must be MZ_DEFAULT_WINDOW_BITS (to wrap the deflate stream with zlib header/adler-32 footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate/no header or footer) // mem_level must be between [1, 9] (it's checked but ignored by miniz.c) int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy); // Quickly resets a compressor without having to reallocate anything. Same as calling mz_deflateEnd() followed by mz_deflateInit()/mz_deflateInit2(). int mz_deflateReset(mz_streamp pStream); // mz_deflate() compresses the input to output, consuming as much of the input and producing as much output as possible. // Parameters: // pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members. // flush may be MZ_NO_FLUSH, MZ_PARTIAL_FLUSH/MZ_SYNC_FLUSH, MZ_FULL_FLUSH, or MZ_FINISH. // Return values: // MZ_OK on success (when flushing, or if more input is needed but not available, and/or there's more output to be written but the output buffer is full). // MZ_STREAM_END if all input has been consumed and all output bytes have been written. Don't call mz_deflate() on the stream anymore. // MZ_STREAM_ERROR if the stream is bogus. // MZ_PARAM_ERROR if one of the parameters is invalid. // MZ_BUF_ERROR if no forward progress is possible because the input and/or output buffers are empty. (Fill up the input buffer or free up some output space and try again.) int mz_deflate(mz_streamp pStream, int flush); // mz_deflateEnd() deinitializes a compressor: // Return values: // MZ_OK on success. // MZ_STREAM_ERROR if the stream is bogus. int mz_deflateEnd(mz_streamp pStream); // mz_deflateBound() returns a (very) conservative upper bound on the amount of data that could be generated by deflate(), assuming flush is set to only MZ_NO_FLUSH or MZ_FINISH. mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len); // Single-call compression functions mz_compress() and mz_compress2(): // Returns MZ_OK on success, or one of the error codes from mz_deflate() on failure. int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len); int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level); // mz_compressBound() returns a (very) conservative upper bound on the amount of data that could be generated by calling mz_compress(). mz_ulong mz_compressBound(mz_ulong source_len); // Initializes a decompressor. int mz_inflateInit(mz_streamp pStream); // mz_inflateInit2() is like mz_inflateInit() with an additional option that controls the window size and whether or not the stream has been wrapped with a zlib header/footer: // window_bits must be MZ_DEFAULT_WINDOW_BITS (to parse zlib header/footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate). int mz_inflateInit2(mz_streamp pStream, int window_bits); // Decompresses the input stream to the output, consuming only as much of the input as needed, and writing as much to the output as possible. // Parameters: // pStream is the stream to read from and write to. You must initialize/update the next_in, avail_in, next_out, and avail_out members. // flush may be MZ_NO_FLUSH, MZ_SYNC_FLUSH, or MZ_FINISH. // On the first call, if flush is MZ_FINISH it's assumed the input and output buffers are both sized large enough to decompress the entire stream in a single call (this is slightly faster). // MZ_FINISH implies that there are no more source bytes available beside what's already in the input buffer, and that the output buffer is large enough to hold the rest of the decompressed data. // Return values: // MZ_OK on success. Either more input is needed but not available, and/or there's more output to be written but the output buffer is full. // MZ_STREAM_END if all needed input has been consumed and all output bytes have been written. For zlib streams, the adler-32 of the decompressed data has also been verified. // MZ_STREAM_ERROR if the stream is bogus. // MZ_DATA_ERROR if the deflate stream is invalid. // MZ_PARAM_ERROR if one of the parameters is invalid. // MZ_BUF_ERROR if no forward progress is possible because the input buffer is empty but the inflater needs more input to continue, or if the output buffer is not large enough. Call mz_inflate() again // with more input data, or with more room in the output buffer (except when using single call decompression, described above). int mz_inflate(mz_streamp pStream, int flush); // Deinitializes a decompressor. int mz_inflateEnd(mz_streamp pStream); // Single-call decompression. // Returns MZ_OK on success, or one of the error codes from mz_inflate() on failure. int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len); // Returns a string description of the specified error code, or NULL if the error code is invalid. const char *mz_error(int err); // Redefine zlib-compatible names to miniz equivalents, so miniz.c can be used as a drop-in replacement for the subset of zlib that miniz.c supports. // Define MINIZ_NO_ZLIB_COMPATIBLE_NAMES to disable zlib-compatibility if you use zlib in the same project. #ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES typedef unsigned char Byte; typedef unsigned int uInt; typedef mz_ulong uLong; typedef Byte Bytef; typedef uInt uIntf; typedef char charf; typedef int intf; typedef void *voidpf; typedef uLong uLongf; typedef void *voidp; typedef void *const voidpc; #define Z_NULL 0 #define Z_NO_FLUSH MZ_NO_FLUSH #define Z_PARTIAL_FLUSH MZ_PARTIAL_FLUSH #define Z_SYNC_FLUSH MZ_SYNC_FLUSH #define Z_FULL_FLUSH MZ_FULL_FLUSH #define Z_FINISH MZ_FINISH #define Z_BLOCK MZ_BLOCK #define Z_OK MZ_OK #define Z_STREAM_END MZ_STREAM_END #define Z_NEED_DICT MZ_NEED_DICT #define Z_ERRNO MZ_ERRNO #define Z_STREAM_ERROR MZ_STREAM_ERROR #define Z_DATA_ERROR MZ_DATA_ERROR #define Z_MEM_ERROR MZ_MEM_ERROR #define Z_BUF_ERROR MZ_BUF_ERROR #define Z_VERSION_ERROR MZ_VERSION_ERROR #define Z_PARAM_ERROR MZ_PARAM_ERROR #define Z_NO_COMPRESSION MZ_NO_COMPRESSION #define Z_BEST_SPEED MZ_BEST_SPEED #define Z_BEST_COMPRESSION MZ_BEST_COMPRESSION #define Z_DEFAULT_COMPRESSION MZ_DEFAULT_COMPRESSION #define Z_DEFAULT_STRATEGY MZ_DEFAULT_STRATEGY #define Z_FILTERED MZ_FILTERED #define Z_HUFFMAN_ONLY MZ_HUFFMAN_ONLY #define Z_RLE MZ_RLE #define Z_FIXED MZ_FIXED #define Z_DEFLATED MZ_DEFLATED #define Z_DEFAULT_WINDOW_BITS MZ_DEFAULT_WINDOW_BITS #define alloc_func mz_alloc_func #define free_func mz_free_func #define internal_state mz_internal_state #define z_stream mz_stream #define deflateInit mz_deflateInit #define deflateInit2 mz_deflateInit2 #define deflateReset mz_deflateReset #define deflate mz_deflate #define deflateEnd mz_deflateEnd #define deflateBound mz_deflateBound #define compress mz_compress #define compress2 mz_compress2 #define compressBound mz_compressBound #define inflateInit mz_inflateInit #define inflateInit2 mz_inflateInit2 #define inflate mz_inflate #define inflateEnd mz_inflateEnd #define uncompress mz_uncompress #define crc32 mz_crc32 #define adler32 mz_adler32 #define MAX_WBITS 15 #define MAX_MEM_LEVEL 9 #define zError mz_error #define ZLIB_VERSION MZ_VERSION #define ZLIB_VERNUM MZ_VERNUM #define ZLIB_VER_MAJOR MZ_VER_MAJOR #define ZLIB_VER_MINOR MZ_VER_MINOR #define ZLIB_VER_REVISION MZ_VER_REVISION #define ZLIB_VER_SUBREVISION MZ_VER_SUBREVISION #define zlibVersion mz_version #define zlib_version mz_version() #endif // #ifndef MINIZ_NO_ZLIB_COMPATIBLE_NAMES #endif // MINIZ_NO_ZLIB_APIS // ------------------- Types and macros typedef unsigned char mz_uint8; typedef signed short mz_int16; typedef unsigned short mz_uint16; typedef unsigned int mz_uint32; typedef unsigned int mz_uint; typedef long long mz_int64; typedef unsigned long long mz_uint64; typedef int mz_bool; #define MZ_FALSE (0) #define MZ_TRUE (1) // Works around MSVC's spammy "warning C4127: conditional expression is constant" message. #ifdef _MSC_VER #define MZ_MACRO_END while (0, 0) #else #define MZ_MACRO_END while (0) #endif // ------------------- ZIP archive reading/writing #ifndef MINIZ_NO_ARCHIVE_APIS enum { MZ_ZIP_MAX_IO_BUF_SIZE = 64*1024, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE = 260, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE = 256 }; typedef struct { mz_uint32 m_file_index; mz_uint32 m_central_dir_ofs; mz_uint16 m_version_made_by; mz_uint16 m_version_needed; mz_uint16 m_bit_flag; mz_uint16 m_method; #ifndef MINIZ_NO_TIME time_t m_time; #endif mz_uint32 m_crc32; mz_uint64 m_comp_size; mz_uint64 m_uncomp_size; mz_uint16 m_internal_attr; mz_uint32 m_external_attr; mz_uint64 m_local_header_ofs; mz_uint32 m_comment_size; char m_filename[MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE]; char m_comment[MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE]; } mz_zip_archive_file_stat; typedef size_t (*mz_file_read_func)(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n); typedef size_t (*mz_file_write_func)(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n); struct mz_zip_internal_state_tag; typedef struct mz_zip_internal_state_tag mz_zip_internal_state; typedef enum { MZ_ZIP_MODE_INVALID = 0, MZ_ZIP_MODE_READING = 1, MZ_ZIP_MODE_WRITING = 2, MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED = 3 } mz_zip_mode; typedef struct { mz_uint64 m_archive_size; mz_uint64 m_central_directory_file_ofs; mz_uint m_total_files; mz_zip_mode m_zip_mode; mz_uint m_file_offset_alignment; mz_alloc_func m_pAlloc; mz_free_func m_pFree; mz_realloc_func m_pRealloc; void *m_pAlloc_opaque; mz_file_read_func m_pRead; mz_file_write_func m_pWrite; void *m_pIO_opaque; mz_zip_internal_state *m_pState; } mz_zip_archive; typedef enum { MZ_ZIP_FLAG_CASE_SENSITIVE = 0x0100, MZ_ZIP_FLAG_IGNORE_PATH = 0x0200, MZ_ZIP_FLAG_COMPRESSED_DATA = 0x0400, MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY = 0x0800 } mz_zip_flags; // ZIP archive reading // Inits a ZIP archive reader. // These functions read and validate the archive's central directory. mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint32 flags); mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint32 flags); #ifndef MINIZ_NO_STDIO mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags); #endif // Returns the total number of files in the archive. mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip); // Returns detailed information about an archive file entry. mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat); // Determines if an archive file entry is a directory entry. mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index); mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index); // Retrieves the filename of an archive file entry. // Returns the number of bytes written to pFilename, or if filename_buf_size is 0 this function returns the number of bytes needed to fully store the filename. mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size); // Attempts to locates a file in the archive's central directory. // Valid flags: MZ_ZIP_FLAG_CASE_SENSITIVE, MZ_ZIP_FLAG_IGNORE_PATH // Returns -1 if the file cannot be found. int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags); // Extracts a archive file to a memory buffer using no memory allocation. mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size); mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size); // Extracts a archive file to a memory buffer. mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags); mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags); // Extracts a archive file to a dynamically allocated heap buffer. void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags); void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags); // Extracts a archive file using a callback function to output the file's data. mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags); mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags); #ifndef MINIZ_NO_STDIO // Extracts a archive file to a disk file and sets its last accessed and modified times. // This function only extracts files, not archive directory records. mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags); mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags); #endif // Ends archive reading, freeing all allocations, and closing the input archive file if mz_zip_reader_init_file() was used. mz_bool mz_zip_reader_end(mz_zip_archive *pZip); // ZIP archive writing #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS // Inits a ZIP archive writer. mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size); mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size); #ifndef MINIZ_NO_STDIO mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning); #endif // Converts a ZIP archive reader object into a writer object, to allow efficient in-place file appends to occur on an existing archive. // For archives opened using mz_zip_reader_init_file, pFilename must be the archive's filename so it can be reopened for writing. If the file can't be reopened, mz_zip_reader_end() will be called. // For archives opened using mz_zip_reader_init_mem, the memory block must be growable using the realloc callback (which defaults to realloc unless you've overridden it). // Finally, for archives opened using mz_zip_reader_init, the mz_zip_archive's user provided m_pWrite function cannot be NULL. // Note: In-place archive modification is not recommended unless you know what you're doing, because if execution stops or something goes wrong before // the archive is finalized the file's central directory will be hosed. mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename); // Adds the contents of a memory buffer to an archive. These functions record the current local time into the archive. // To add a directory entry, call this method with an archive name ending in a forwardslash with empty buffer. // level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags); mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32); #ifndef MINIZ_NO_STDIO // Adds the contents of a disk file to an archive. This function also records the disk file's modified time into the archive. // level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags); #endif // Adds a file to an archive by fully cloning the data from another archive. // This function fully clones the source file's compressed data (no recompression), along with its full filename, extra data, and comment fields. mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint file_index); // Finalizes the archive by writing the central directory records followed by the end of central directory record. // After an archive is finalized, the only valid call on the mz_zip_archive struct is mz_zip_writer_end(). // An archive must be manually finalized by calling this function for it to be valid. mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip); mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf, size_t *pSize); // Ends archive writing, freeing all allocations, and closing the output file if mz_zip_writer_init_file() was used. // Note for the archive to be valid, it must have been finalized before ending. mz_bool mz_zip_writer_end(mz_zip_archive *pZip); // Misc. high-level helper functions: // mz_zip_add_mem_to_archive_file_in_place() efficiently (but not atomically) appends a memory blob to a ZIP archive. // level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags); // Reads a single file from an archive into a heap block. // Returns NULL on failure. void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint zip_flags); #endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS #endif // #ifndef MINIZ_NO_ARCHIVE_APIS // ------------------- Low-level Decompression API Definitions // Decompression flags used by tinfl_decompress(). // TINFL_FLAG_PARSE_ZLIB_HEADER: If set, the input has a valid zlib header and ends with an adler32 checksum (it's a valid zlib stream). Otherwise, the input is a raw deflate stream. // TINFL_FLAG_HAS_MORE_INPUT: If set, there are more input bytes available beyond the end of the supplied input buffer. If clear, the input buffer contains all remaining input. // TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF: If set, the output buffer is large enough to hold the entire decompressed stream. If clear, the output buffer is at least the size of the dictionary (typically 32KB). // TINFL_FLAG_COMPUTE_ADLER32: Force adler-32 checksum computation of the decompressed bytes. enum { TINFL_FLAG_PARSE_ZLIB_HEADER = 1, TINFL_FLAG_HAS_MORE_INPUT = 2, TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF = 4, TINFL_FLAG_COMPUTE_ADLER32 = 8 }; // High level decompression functions: // tinfl_decompress_mem_to_heap() decompresses a block in memory to a heap block allocated via malloc(). // On entry: // pSrc_buf, src_buf_len: Pointer and size of the Deflate or zlib source data to decompress. // On return: // Function returns a pointer to the decompressed data, or NULL on failure. // *pOut_len will be set to the decompressed data's size, which could be larger than src_buf_len on uncompressible data. // The caller must call mz_free() on the returned block when it's no longer needed. void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags); // tinfl_decompress_mem_to_mem() decompresses a block in memory to another block in memory. // Returns TINFL_DECOMPRESS_MEM_TO_MEM_FAILED on failure, or the number of bytes written on success. #define TINFL_DECOMPRESS_MEM_TO_MEM_FAILED ((size_t)(-1)) size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags); // tinfl_decompress_mem_to_callback() decompresses a block in memory to an internal 32KB buffer, and a user provided callback function will be called to flush the buffer. // Returns 1 on success or 0 on failure. typedef int (*tinfl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser); int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags); struct tinfl_decompressor_tag; typedef struct tinfl_decompressor_tag tinfl_decompressor; // Max size of LZ dictionary. #define TINFL_LZ_DICT_SIZE 32768 // Return status. typedef enum { TINFL_STATUS_BAD_PARAM = -3, TINFL_STATUS_ADLER32_MISMATCH = -2, TINFL_STATUS_FAILED = -1, TINFL_STATUS_DONE = 0, TINFL_STATUS_NEEDS_MORE_INPUT = 1, TINFL_STATUS_HAS_MORE_OUTPUT = 2 } tinfl_status; // Initializes the decompressor to its initial state. #define tinfl_init(r) do { (r)->m_state = 0; } MZ_MACRO_END #define tinfl_get_adler32(r) (r)->m_check_adler32 // Main low-level decompressor coroutine function. This is the only function actually needed for decompression. All the other functions are just high-level helpers for improved usability. // This is a universal API, i.e. it can be used as a building block to build any desired higher level decompression API. In the limit case, it can be called once per every byte input or output. tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags); // Internal/private bits follow. enum { TINFL_MAX_HUFF_TABLES = 3, TINFL_MAX_HUFF_SYMBOLS_0 = 288, TINFL_MAX_HUFF_SYMBOLS_1 = 32, TINFL_MAX_HUFF_SYMBOLS_2 = 19, TINFL_FAST_LOOKUP_BITS = 10, TINFL_FAST_LOOKUP_SIZE = 1 << TINFL_FAST_LOOKUP_BITS }; typedef struct { mz_uint8 m_code_size[TINFL_MAX_HUFF_SYMBOLS_0]; mz_int16 m_look_up[TINFL_FAST_LOOKUP_SIZE], m_tree[TINFL_MAX_HUFF_SYMBOLS_0 * 2]; } tinfl_huff_table; #if MINIZ_HAS_64BIT_REGISTERS #define TINFL_USE_64BIT_BITBUF 1 #endif #if TINFL_USE_64BIT_BITBUF typedef mz_uint64 tinfl_bit_buf_t; #define TINFL_BITBUF_SIZE (64) #else typedef mz_uint32 tinfl_bit_buf_t; #define TINFL_BITBUF_SIZE (32) #endif struct tinfl_decompressor_tag { mz_uint32 m_state, m_num_bits, m_zhdr0, m_zhdr1, m_z_adler32, m_final, m_type, m_check_adler32, m_dist, m_counter, m_num_extra, m_table_sizes[TINFL_MAX_HUFF_TABLES]; tinfl_bit_buf_t m_bit_buf; size_t m_dist_from_out_buf_start; tinfl_huff_table m_tables[TINFL_MAX_HUFF_TABLES]; mz_uint8 m_raw_header[4], m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + TINFL_MAX_HUFF_SYMBOLS_1 + 137]; }; // ------------------- Low-level Compression API Definitions // Set TDEFL_LESS_MEMORY to 1 to use less memory (compression will be slightly slower, and raw/dynamic blocks will be output more frequently). #define TDEFL_LESS_MEMORY 0 // tdefl_init() compression flags logically OR'd together (low 12 bits contain the max. number of probes per dictionary search): // TDEFL_DEFAULT_MAX_PROBES: The compressor defaults to 128 dictionary probes per dictionary search. 0=Huffman only, 1=Huffman+LZ (fastest/crap compression), 4095=Huffman+LZ (slowest/best compression). enum { TDEFL_HUFFMAN_ONLY = 0, TDEFL_DEFAULT_MAX_PROBES = 128, TDEFL_MAX_PROBES_MASK = 0xFFF }; // TDEFL_WRITE_ZLIB_HEADER: If set, the compressor outputs a zlib header before the deflate data, and the Adler-32 of the source data at the end. Otherwise, you'll get raw deflate data. // TDEFL_COMPUTE_ADLER32: Always compute the adler-32 of the input data (even when not writing zlib headers). // TDEFL_GREEDY_PARSING_FLAG: Set to use faster greedy parsing, instead of more efficient lazy parsing. // TDEFL_NONDETERMINISTIC_PARSING_FLAG: Enable to decrease the compressor's initialization time to the minimum, but the output may vary from run to run given the same input (depending on the contents of memory). // TDEFL_RLE_MATCHES: Only look for RLE matches (matches with a distance of 1) // TDEFL_FILTER_MATCHES: Discards matches <= 5 chars if enabled. // TDEFL_FORCE_ALL_STATIC_BLOCKS: Disable usage of optimized Huffman tables. // TDEFL_FORCE_ALL_RAW_BLOCKS: Only use raw (uncompressed) deflate blocks. enum { TDEFL_WRITE_ZLIB_HEADER = 0x01000, TDEFL_COMPUTE_ADLER32 = 0x02000, TDEFL_GREEDY_PARSING_FLAG = 0x04000, TDEFL_NONDETERMINISTIC_PARSING_FLAG = 0x08000, TDEFL_RLE_MATCHES = 0x10000, TDEFL_FILTER_MATCHES = 0x20000, TDEFL_FORCE_ALL_STATIC_BLOCKS = 0x40000, TDEFL_FORCE_ALL_RAW_BLOCKS = 0x80000 }; // High level compression functions: // tdefl_compress_mem_to_heap() compresses a block in memory to a heap block allocated via malloc(). // On entry: // pSrc_buf, src_buf_len: Pointer and size of source block to compress. // flags: The max match finder probes (default is 128) logically OR'd against the above flags. Higher probes are slower but improve compression. // On return: // Function returns a pointer to the compressed data, or NULL on failure. // *pOut_len will be set to the compressed data's size, which could be larger than src_buf_len on uncompressible data. // The caller must free() the returned block when it's no longer needed. void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags); // tdefl_compress_mem_to_mem() compresses a block in memory to another block in memory. // Returns 0 on failure. size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags); // Compresses an image to a compressed PNG file in memory. // On entry: // pImage, w, h, and num_chans describe the image to compress. num_chans may be 1, 2, 3, or 4. // The image pitch in bytes per scanline will be w*num_chans. The leftmost pixel on the top scanline is stored first in memory. // On return: // Function returns a pointer to the compressed data, or NULL on failure. // *pLen_out will be set to the size of the PNG image file. // The caller must mz_free() the returned heap block (which will typically be larger than *pLen_out) when it's no longer needed. void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out); // Output stream interface. The compressor uses this interface to write compressed data. It'll typically be called TDEFL_OUT_BUF_SIZE at a time. typedef mz_bool(*tdefl_put_buf_func_ptr)(const void* pBuf, int len, void *pUser); // tdefl_compress_mem_to_output() compresses a block to an output stream. The above helpers use this function internally. mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags); enum { TDEFL_MAX_HUFF_TABLES = 3, TDEFL_MAX_HUFF_SYMBOLS_0 = 288, TDEFL_MAX_HUFF_SYMBOLS_1 = 32, TDEFL_MAX_HUFF_SYMBOLS_2 = 19, TDEFL_LZ_DICT_SIZE = 32768, TDEFL_LZ_DICT_SIZE_MASK = TDEFL_LZ_DICT_SIZE - 1, TDEFL_MIN_MATCH_LEN = 3, TDEFL_MAX_MATCH_LEN = 258 }; // TDEFL_OUT_BUF_SIZE MUST be large enough to hold a single entire compressed output block (using static/fixed Huffman codes). #if TDEFL_LESS_MEMORY enum { TDEFL_LZ_CODE_BUF_SIZE = 24 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 12, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS }; #else enum { TDEFL_LZ_CODE_BUF_SIZE = 64 * 1024, TDEFL_OUT_BUF_SIZE = (TDEFL_LZ_CODE_BUF_SIZE * 13) / 10, TDEFL_MAX_HUFF_SYMBOLS = 288, TDEFL_LZ_HASH_BITS = 15, TDEFL_LEVEL1_HASH_SIZE_MASK = 4095, TDEFL_LZ_HASH_SHIFT = (TDEFL_LZ_HASH_BITS + 2) / 3, TDEFL_LZ_HASH_SIZE = 1 << TDEFL_LZ_HASH_BITS }; #endif // The low-level tdefl functions below may be used directly if the above helper functions aren't flexible enough. The low-level functions don't make any heap allocations, unlike the above helper functions. typedef enum { TDEFL_STATUS_BAD_PARAM = -2, TDEFL_STATUS_PUT_BUF_FAILED = -1, TDEFL_STATUS_OKAY = 0, TDEFL_STATUS_DONE = 1, } tdefl_status; // Must map to MZ_NO_FLUSH, MZ_SYNC_FLUSH, etc. enums typedef enum { TDEFL_NO_FLUSH = 0, TDEFL_SYNC_FLUSH = 2, TDEFL_FULL_FLUSH = 3, TDEFL_FINISH = 4 } tdefl_flush; // tdefl's compression state structure. typedef struct { tdefl_put_buf_func_ptr m_pPut_buf_func; void *m_pPut_buf_user; mz_uint m_flags, m_max_probes[2]; int m_greedy_parsing; mz_uint m_adler32, m_lookahead_pos, m_lookahead_size, m_dict_size; mz_uint8 *m_pLZ_code_buf, *m_pLZ_flags, *m_pOutput_buf, *m_pOutput_buf_end; mz_uint m_num_flags_left, m_total_lz_bytes, m_lz_code_buf_dict_pos, m_bits_in, m_bit_buffer; mz_uint m_saved_match_dist, m_saved_match_len, m_saved_lit, m_output_flush_ofs, m_output_flush_remaining, m_finished, m_block_index, m_wants_to_finish; tdefl_status m_prev_return_status; const void *m_pIn_buf; void *m_pOut_buf; size_t *m_pIn_buf_size, *m_pOut_buf_size; tdefl_flush m_flush; const mz_uint8 *m_pSrc; size_t m_src_buf_left, m_out_buf_ofs; mz_uint8 m_dict[TDEFL_LZ_DICT_SIZE + TDEFL_MAX_MATCH_LEN - 1]; mz_uint16 m_huff_count[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; mz_uint16 m_huff_codes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; mz_uint8 m_huff_code_sizes[TDEFL_MAX_HUFF_TABLES][TDEFL_MAX_HUFF_SYMBOLS]; mz_uint8 m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE]; mz_uint16 m_next[TDEFL_LZ_DICT_SIZE]; mz_uint16 m_hash[TDEFL_LZ_HASH_SIZE]; mz_uint8 m_output_buf[TDEFL_OUT_BUF_SIZE]; } tdefl_compressor; // Initializes the compressor. // There is no corresponding deinit() function because the tdefl API's do not dynamically allocate memory. // pBut_buf_func: If NULL, output data will be supplied to the specified callback. In this case, the user should call the tdefl_compress_buffer() API for compression. // If pBut_buf_func is NULL the user should always call the tdefl_compress() API. // flags: See the above enums (TDEFL_HUFFMAN_ONLY, TDEFL_WRITE_ZLIB_HEADER, etc.) tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags); // Compresses a block of data, consuming as much of the specified input buffer as possible, and writing as much compressed data to the specified output buffer as possible. tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush); // tdefl_compress_buffer() is only usable when the tdefl_init() is called with a non-NULL tdefl_put_buf_func_ptr. // tdefl_compress_buffer() always consumes the entire input buffer. tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush); tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d); mz_uint32 tdefl_get_adler32(tdefl_compressor *d); // Can't use tdefl_create_comp_flags_from_zip_params if MINIZ_NO_ZLIB_APIS isn't defined, because it uses some of its macros. #ifndef MINIZ_NO_ZLIB_APIS // Create tdefl_compress() flags given zlib-style compression parameters. // level may range from [0,10] (where 10 is absolute max compression, but may be much slower on some files) // window_bits may be -15 (raw deflate) or 15 (zlib) // strategy may be either MZ_DEFAULT_STRATEGY, MZ_FILTERED, MZ_HUFFMAN_ONLY, MZ_RLE, or MZ_FIXED mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy); #endif // #ifndef MINIZ_NO_ZLIB_APIS #ifdef __cplusplus } #endif #endif // MINIZ_HEADER_INCLUDED // ------------------- End of Header: Implementation follows. (If you only want the header, define MINIZ_HEADER_FILE_ONLY.) #ifndef MINIZ_HEADER_FILE_ONLY typedef unsigned char mz_validate_uint16[sizeof(mz_uint16)==2 ? 1 : -1]; typedef unsigned char mz_validate_uint32[sizeof(mz_uint32)==4 ? 1 : -1]; typedef unsigned char mz_validate_uint64[sizeof(mz_uint64)==8 ? 1 : -1]; #include #include #define MZ_ASSERT(x) assert(x) #ifdef MINIZ_NO_MALLOC #define MZ_MALLOC(x) NULL #define MZ_FREE(x) (void)x, ((void)0) #define MZ_REALLOC(p, x) NULL #else #define MZ_MALLOC(x) malloc(x) #define MZ_FREE(x) free(x) #define MZ_REALLOC(p, x) realloc(p, x) #endif #define MZ_MAX(a,b) (((a)>(b))?(a):(b)) #define MZ_MIN(a,b) (((a)<(b))?(a):(b)) #define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj)) #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN #define MZ_READ_LE16(p) *((const mz_uint16 *)(p)) #define MZ_READ_LE32(p) *((const mz_uint32 *)(p)) #else #define MZ_READ_LE16(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U)) #define MZ_READ_LE32(p) ((mz_uint32)(((const mz_uint8 *)(p))[0]) | ((mz_uint32)(((const mz_uint8 *)(p))[1]) << 8U) | ((mz_uint32)(((const mz_uint8 *)(p))[2]) << 16U) | ((mz_uint32)(((const mz_uint8 *)(p))[3]) << 24U)) #endif #ifdef _MSC_VER #define MZ_FORCEINLINE __forceinline #elif defined(__GNUC__) #define MZ_FORCEINLINE __attribute__((__always_inline__)) #else #define MZ_FORCEINLINE #endif #ifdef __cplusplus extern "C" { #endif // ------------------- zlib-style API's mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len) { mz_uint32 i, s1 = (mz_uint32)(adler & 0xffff), s2 = (mz_uint32)(adler >> 16); size_t block_len = buf_len % 5552; if (!ptr) return MZ_ADLER32_INIT; while (buf_len) { for (i = 0; i + 7 < block_len; i += 8, ptr += 8) { s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1; s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1; } for (; i < block_len; ++i) s1 += *ptr++, s2 += s1; s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552; } return (s2 << 16) + s1; } // Karl Malbrain's compact CRC-32. See "A compact CCITT crc16 and crc32 C implementation that balances processor cache usage against speed": http://www.geocities.com/malbrain/ mz_ulong mz_crc32(mz_ulong crc, const mz_uint8 *ptr, size_t buf_len) { static const mz_uint32 s_crc32[16] = { 0, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c }; mz_uint32 crcu32 = (mz_uint32)crc; if (!ptr) return MZ_CRC32_INIT; crcu32 = ~crcu32; while (buf_len--) { mz_uint8 b = *ptr++; crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^(b & 0xF)]; crcu32 = (crcu32 >> 4) ^ s_crc32[(crcu32 & 0xF) ^(b >> 4)]; } return ~crcu32; } void mz_free(void *p) { MZ_FREE(p); } #ifndef MINIZ_NO_ZLIB_APIS static void *def_alloc_func(void *opaque, size_t items, size_t size) { (void)opaque, (void)items, (void)size; return MZ_MALLOC(items * size); } static void def_free_func(void *opaque, void *address) { (void)opaque, (void)address; MZ_FREE(address); } static void *def_realloc_func(void *opaque, void *address, size_t items, size_t size) { (void)opaque, (void)address, (void)items, (void)size; return MZ_REALLOC(address, items * size); } const char *mz_version(void) { return MZ_VERSION; } int mz_deflateInit(mz_streamp pStream, int level) { return mz_deflateInit2(pStream, level, MZ_DEFLATED, MZ_DEFAULT_WINDOW_BITS, 9, MZ_DEFAULT_STRATEGY); } int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy) { tdefl_compressor *pComp; mz_uint comp_flags = TDEFL_COMPUTE_ADLER32 | tdefl_create_comp_flags_from_zip_params(level, window_bits, strategy); if (!pStream) return MZ_STREAM_ERROR; if ((method != MZ_DEFLATED) || ((mem_level < 1) || (mem_level > 9)) || ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS))) return MZ_PARAM_ERROR; pStream->data_type = 0; pStream->adler = MZ_ADLER32_INIT; pStream->msg = NULL; pStream->reserved = 0; pStream->total_in = 0; pStream->total_out = 0; if (!pStream->zalloc) pStream->zalloc = def_alloc_func; if (!pStream->zfree) pStream->zfree = def_free_func; pComp = (tdefl_compressor *)pStream->zalloc(pStream->opaque, 1, sizeof(tdefl_compressor)); if (!pComp) return MZ_MEM_ERROR; pStream->state = (struct mz_internal_state *)pComp; if (tdefl_init(pComp, NULL, NULL, comp_flags) != TDEFL_STATUS_OKAY) { mz_deflateEnd(pStream); return MZ_PARAM_ERROR; } return MZ_OK; } int mz_deflateReset(mz_streamp pStream) { if ((!pStream) || (!pStream->state) || (!pStream->zalloc) || (!pStream->zfree)) return MZ_STREAM_ERROR; pStream->total_in = pStream->total_out = 0; tdefl_init((tdefl_compressor*)pStream->state, NULL, NULL, ((tdefl_compressor*)pStream->state)->m_flags); return MZ_OK; } int mz_deflate(mz_streamp pStream, int flush) { size_t in_bytes, out_bytes; mz_ulong orig_total_in, orig_total_out; int mz_status = MZ_OK; if ((!pStream) || (!pStream->state) || (flush < 0) || (flush > MZ_FINISH) || (!pStream->next_out)) return MZ_STREAM_ERROR; if (!pStream->avail_out) return MZ_BUF_ERROR; if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH; if (((tdefl_compressor*)pStream->state)->m_prev_return_status == TDEFL_STATUS_DONE) return (flush == MZ_FINISH) ? MZ_STREAM_END : MZ_BUF_ERROR; orig_total_in = pStream->total_in; orig_total_out = pStream->total_out; for (; ;) { tdefl_status defl_status; in_bytes = pStream->avail_in; out_bytes = pStream->avail_out; defl_status = tdefl_compress((tdefl_compressor*)pStream->state, pStream->next_in, &in_bytes, pStream->next_out, &out_bytes, (tdefl_flush)flush); pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes; pStream->total_in += (mz_uint)in_bytes; pStream->adler = tdefl_get_adler32((tdefl_compressor*)pStream->state); pStream->next_out += (mz_uint)out_bytes; pStream->avail_out -= (mz_uint)out_bytes; pStream->total_out += (mz_uint)out_bytes; if (defl_status < 0) { mz_status = MZ_STREAM_ERROR; break; } else if (defl_status == TDEFL_STATUS_DONE) { mz_status = MZ_STREAM_END; break; } else if (!pStream->avail_out) break; else if ((!pStream->avail_in) && (flush != MZ_FINISH)) { if ((flush) || (pStream->total_in != orig_total_in) || (pStream->total_out != orig_total_out)) break; return MZ_BUF_ERROR; // Can't make forward progress without some input. } } return mz_status; } int mz_deflateEnd(mz_streamp pStream) { if (!pStream) return MZ_STREAM_ERROR; if (pStream->state) { pStream->zfree(pStream->opaque, pStream->state); pStream->state = NULL; } return MZ_OK; } mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len) { (void)pStream; // This is really over conservative. (And lame, but it's actually pretty tricky to compute a true upper bound given the way tdefl's blocking works.) return MZ_MAX(128 + (source_len * 110) / 100, 128 + source_len + ((source_len / (31 * 1024)) + 1) * 5); } int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level) { int status; mz_stream stream; memset(&stream, 0, sizeof(stream)); // In case mz_ulong is 64-bits (argh I hate longs). if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR; stream.next_in = pSource; stream.avail_in = (mz_uint32)source_len; stream.next_out = pDest; stream.avail_out = (mz_uint32)*pDest_len; status = mz_deflateInit(&stream, level); if (status != MZ_OK) return status; status = mz_deflate(&stream, MZ_FINISH); if (status != MZ_STREAM_END) { mz_deflateEnd(&stream); return (status == MZ_OK) ? MZ_BUF_ERROR : status; } *pDest_len = stream.total_out; return mz_deflateEnd(&stream); } int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len) { return mz_compress2(pDest, pDest_len, pSource, source_len, MZ_DEFAULT_COMPRESSION); } mz_ulong mz_compressBound(mz_ulong source_len) { return mz_deflateBound(NULL, source_len); } typedef struct { tinfl_decompressor m_decomp; mz_uint m_dict_ofs, m_dict_avail, m_first_call, m_has_flushed; int m_window_bits; mz_uint8 m_dict[TINFL_LZ_DICT_SIZE]; tinfl_status m_last_status; } inflate_state; int mz_inflateInit2(mz_streamp pStream, int window_bits) { inflate_state *pDecomp; if (!pStream) return MZ_STREAM_ERROR; if ((window_bits != MZ_DEFAULT_WINDOW_BITS) && (-window_bits != MZ_DEFAULT_WINDOW_BITS)) return MZ_PARAM_ERROR; pStream->data_type = 0; pStream->adler = 0; pStream->msg = NULL; pStream->total_in = 0; pStream->total_out = 0; pStream->reserved = 0; if (!pStream->zalloc) pStream->zalloc = def_alloc_func; if (!pStream->zfree) pStream->zfree = def_free_func; pDecomp = (inflate_state*)pStream->zalloc(pStream->opaque, 1, sizeof(inflate_state)); if (!pDecomp) return MZ_MEM_ERROR; pStream->state = (struct mz_internal_state *)pDecomp; tinfl_init(&pDecomp->m_decomp); pDecomp->m_dict_ofs = 0; pDecomp->m_dict_avail = 0; pDecomp->m_last_status = TINFL_STATUS_NEEDS_MORE_INPUT; pDecomp->m_first_call = 1; pDecomp->m_has_flushed = 0; pDecomp->m_window_bits = window_bits; return MZ_OK; } int mz_inflateInit(mz_streamp pStream) { return mz_inflateInit2(pStream, MZ_DEFAULT_WINDOW_BITS); } int mz_inflate(mz_streamp pStream, int flush) { inflate_state* pState; mz_uint n, first_call, decomp_flags = TINFL_FLAG_COMPUTE_ADLER32; size_t in_bytes, out_bytes, orig_avail_in; tinfl_status status; if ((!pStream) || (!pStream->state)) return MZ_STREAM_ERROR; if (flush == MZ_PARTIAL_FLUSH) flush = MZ_SYNC_FLUSH; if ((flush) && (flush != MZ_SYNC_FLUSH) && (flush != MZ_FINISH)) return MZ_STREAM_ERROR; pState = (inflate_state*)pStream->state; if (pState->m_window_bits > 0) decomp_flags |= TINFL_FLAG_PARSE_ZLIB_HEADER; orig_avail_in = pStream->avail_in; first_call = pState->m_first_call; pState->m_first_call = 0; if (pState->m_last_status < 0) return MZ_DATA_ERROR; if (pState->m_has_flushed && (flush != MZ_FINISH)) return MZ_STREAM_ERROR; pState->m_has_flushed |= (flush == MZ_FINISH); if ((flush == MZ_FINISH) && (first_call)) { // MZ_FINISH on the first call implies that the input and output buffers are large enough to hold the entire compressed/decompressed file. decomp_flags |= TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF; in_bytes = pStream->avail_in; out_bytes = pStream->avail_out; status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pStream->next_out, pStream->next_out, &out_bytes, decomp_flags); pState->m_last_status = status; pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes; pStream->total_in += (mz_uint)in_bytes; pStream->adler = tinfl_get_adler32(&pState->m_decomp); pStream->next_out += (mz_uint)out_bytes; pStream->avail_out -= (mz_uint)out_bytes; pStream->total_out += (mz_uint)out_bytes; if (status < 0) return MZ_DATA_ERROR; else if (status != TINFL_STATUS_DONE) { pState->m_last_status = TINFL_STATUS_FAILED; return MZ_BUF_ERROR; } return MZ_STREAM_END; } // flush != MZ_FINISH then we must assume there's more input. if (flush != MZ_FINISH) decomp_flags |= TINFL_FLAG_HAS_MORE_INPUT; if (pState->m_dict_avail) { n = MZ_MIN(pState->m_dict_avail, pStream->avail_out); memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n); pStream->next_out += n; pStream->avail_out -= n; pStream->total_out += n; pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1); return ((pState->m_last_status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK; } for (; ;) { in_bytes = pStream->avail_in; out_bytes = TINFL_LZ_DICT_SIZE - pState->m_dict_ofs; status = tinfl_decompress(&pState->m_decomp, pStream->next_in, &in_bytes, pState->m_dict, pState->m_dict + pState->m_dict_ofs, &out_bytes, decomp_flags); pState->m_last_status = status; pStream->next_in += (mz_uint)in_bytes; pStream->avail_in -= (mz_uint)in_bytes; pStream->total_in += (mz_uint)in_bytes; pStream->adler = tinfl_get_adler32(&pState->m_decomp); pState->m_dict_avail = (mz_uint)out_bytes; n = MZ_MIN(pState->m_dict_avail, pStream->avail_out); memcpy(pStream->next_out, pState->m_dict + pState->m_dict_ofs, n); pStream->next_out += n; pStream->avail_out -= n; pStream->total_out += n; pState->m_dict_avail -= n; pState->m_dict_ofs = (pState->m_dict_ofs + n) & (TINFL_LZ_DICT_SIZE - 1); if (status < 0) return MZ_DATA_ERROR; // Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well). else if ((status == TINFL_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in)) return MZ_BUF_ERROR; // Signal caller that we can't make forward progress without supplying more input or by setting flush to MZ_FINISH. else if (flush == MZ_FINISH) { // The output buffer MUST be large to hold the remaining uncompressed data when flush==MZ_FINISH. if (status == TINFL_STATUS_DONE) return pState->m_dict_avail ? MZ_BUF_ERROR : MZ_STREAM_END; // status here must be TINFL_STATUS_HAS_MORE_OUTPUT, which means there's at least 1 more byte on the way. If there's no more room left in the output buffer then something is wrong. else if (!pStream->avail_out) return MZ_BUF_ERROR; } else if ((status == TINFL_STATUS_DONE) || (!pStream->avail_in) || (!pStream->avail_out) || (pState->m_dict_avail)) break; } return ((status == TINFL_STATUS_DONE) && (!pState->m_dict_avail)) ? MZ_STREAM_END : MZ_OK; } int mz_inflateEnd(mz_streamp pStream) { if (!pStream) return MZ_STREAM_ERROR; if (pStream->state) { pStream->zfree(pStream->opaque, pStream->state); pStream->state = NULL; } return MZ_OK; } int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len) { mz_stream stream; int status; memset(&stream, 0, sizeof(stream)); // In case mz_ulong is 64-bits (argh I hate longs). if ((source_len | *pDest_len) > 0xFFFFFFFFU) return MZ_PARAM_ERROR; stream.next_in = pSource; stream.avail_in = (mz_uint32)source_len; stream.next_out = pDest; stream.avail_out = (mz_uint32)*pDest_len; status = mz_inflateInit(&stream); if (status != MZ_OK) return status; status = mz_inflate(&stream, MZ_FINISH); if (status != MZ_STREAM_END) { mz_inflateEnd(&stream); return ((status == MZ_BUF_ERROR) && (!stream.avail_in)) ? MZ_DATA_ERROR : status; } *pDest_len = stream.total_out; return mz_inflateEnd(&stream); } const char *mz_error(int err) { static struct { int m_err; const char *m_pDesc; } s_error_descs[] = { { MZ_OK, "" }, { MZ_STREAM_END, "stream end" }, { MZ_NEED_DICT, "need dictionary" }, { MZ_ERRNO, "file error" }, { MZ_STREAM_ERROR, "stream error" }, { MZ_DATA_ERROR, "data error" }, { MZ_MEM_ERROR, "out of memory" }, { MZ_BUF_ERROR, "buf error" }, { MZ_VERSION_ERROR, "version error" }, { MZ_PARAM_ERROR, "parameter error" } }; mz_uint i; for (i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i) if (s_error_descs[i].m_err == err) return s_error_descs[i].m_pDesc; return NULL; } #endif //MINIZ_NO_ZLIB_APIS // ------------------- Low-level Decompression (completely independent from all compression API's) #define TINFL_MEMCPY(d, s, l) memcpy(d, s, l) #define TINFL_MEMSET(p, c, l) memset(p, c, l) #define TINFL_CR_BEGIN switch(r->m_state) { case 0: #define TINFL_CR_RETURN(state_index, result) do { status = result; r->m_state = state_index; goto common_exit; case state_index:; } MZ_MACRO_END #define TINFL_CR_RETURN_FOREVER(state_index, result) do { for ( ; ; ) { TINFL_CR_RETURN(state_index, result); } } MZ_MACRO_END #define TINFL_CR_FINISH } // TODO: If the caller has indicated that there's no more input, and we attempt to read beyond the input buf, then something is wrong with the input because the inflator never // reads ahead more than it needs to. Currently TINFL_GET_BYTE() pads the end of the stream with 0's in this scenario. #define TINFL_GET_BYTE(state_index, c) do { \ if (pIn_buf_cur >= pIn_buf_end) { \ for ( ; ; ) { \ if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) { \ TINFL_CR_RETURN(state_index, TINFL_STATUS_NEEDS_MORE_INPUT); \ if (pIn_buf_cur < pIn_buf_end) { \ c = *pIn_buf_cur++; \ break; \ } \ } else { \ c = 0; \ break; \ } \ } \ } else c = *pIn_buf_cur++; } MZ_MACRO_END #define TINFL_NEED_BITS(state_index, n) do { mz_uint c; TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; } while (num_bits < (mz_uint)(n)) #define TINFL_SKIP_BITS(state_index, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END #define TINFL_GET_BITS(state_index, b, n) do { if (num_bits < (mz_uint)(n)) { TINFL_NEED_BITS(state_index, n); } b = bit_buf & ((1 << (n)) - 1); bit_buf >>= (n); num_bits -= (n); } MZ_MACRO_END // TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes remaining in the input buffer falls below 2. // It reads just enough bytes from the input stream that are needed to decode the next Huffman code (and absolutely no more). It works by trying to fully decode a // Huffman code by using whatever bits are currently present in the bit buffer. If this fails, it reads another byte, and tries again until it succeeds or until the // bit buffer contains >=15 bits (deflate's max. Huffman code size). #define TINFL_HUFF_BITBUF_FILL(state_index, pHuff) \ do { \ temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]; \ if (temp >= 0) { \ code_len = temp >> 9; \ if ((code_len) && (num_bits >= code_len)) \ break; \ } else if (num_bits > TINFL_FAST_LOOKUP_BITS) { \ code_len = TINFL_FAST_LOOKUP_BITS; \ do { \ temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; \ } while ((temp < 0) && (num_bits >= (code_len + 1))); if (temp >= 0) break; \ } TINFL_GET_BYTE(state_index, c); bit_buf |= (((tinfl_bit_buf_t)c) << num_bits); num_bits += 8; \ } while (num_bits < 15); // TINFL_HUFF_DECODE() decodes the next Huffman coded symbol. It's more complex than you would initially expect because the zlib API expects the decompressor to never read // beyond the final byte of the deflate stream. (In other words, when this macro wants to read another byte from the input, it REALLY needs another byte in order to fully // decode the next Huffman code.) Handling this properly is particularly important on raw deflate (non-zlib) streams, which aren't followed by a byte aligned adler-32. // The slow path is only executed at the very end of the input buffer. #define TINFL_HUFF_DECODE(state_index, sym, pHuff) do { \ int temp; mz_uint code_len, c; \ if (num_bits < 15) { \ if ((pIn_buf_end - pIn_buf_cur) < 2) { \ TINFL_HUFF_BITBUF_FILL(state_index, pHuff); \ } else { \ bit_buf |= (((tinfl_bit_buf_t)pIn_buf_cur[0]) << num_bits) | (((tinfl_bit_buf_t)pIn_buf_cur[1]) << (num_bits + 8)); pIn_buf_cur += 2; num_bits += 16; \ } \ } \ if ((temp = (pHuff)->m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) \ code_len = temp >> 9, temp &= 511; \ else { \ code_len = TINFL_FAST_LOOKUP_BITS; do { temp = (pHuff)->m_tree[~temp + ((bit_buf >> code_len++) & 1)]; } while (temp < 0); \ } sym = temp; bit_buf >>= code_len; num_bits -= code_len; } MZ_MACRO_END tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags) { static const int s_length_base[31] = { 3,4,5,6,7,8,9,10,11,13, 15,17,19,23,27,31,35,43,51,59, 67,83,99,115,131,163,195,227,258,0,0 }; static const int s_length_extra[31]= { 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; static const int s_dist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, 257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; static const int s_dist_extra[32] = { 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; static const mz_uint8 s_length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; static const int s_min_table_sizes[3] = { 257, 1, 4 }; tinfl_status status = TINFL_STATUS_FAILED; mz_uint32 num_bits, dist, counter, num_extra; tinfl_bit_buf_t bit_buf; const mz_uint8 *pIn_buf_cur = pIn_buf_next, *const pIn_buf_end = pIn_buf_next + *pIn_buf_size; mz_uint8 *pOut_buf_cur = pOut_buf_next, *const pOut_buf_end = pOut_buf_next + *pOut_buf_size; size_t out_buf_size_mask = (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) ? (size_t)-1 : ((pOut_buf_next - pOut_buf_start) + *pOut_buf_size) - 1, dist_from_out_buf_start; // Ensure the output buffer's size is a power of 2, unless the output buffer is large enough to hold the entire output file (in which case it doesn't matter). if (((out_buf_size_mask + 1) & out_buf_size_mask) || (pOut_buf_next < pOut_buf_start)) { *pIn_buf_size = *pOut_buf_size = 0; return TINFL_STATUS_BAD_PARAM; } num_bits = r->m_num_bits; bit_buf = r->m_bit_buf; dist = r->m_dist; counter = r->m_counter; num_extra = r->m_num_extra; dist_from_out_buf_start = r->m_dist_from_out_buf_start; TINFL_CR_BEGIN bit_buf = num_bits = dist = counter = num_extra = r->m_zhdr0 = r->m_zhdr1 = 0; r->m_z_adler32 = r->m_check_adler32 = 1; if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) { TINFL_GET_BYTE(1, r->m_zhdr0); TINFL_GET_BYTE(2, r->m_zhdr1); counter = (((r->m_zhdr0 * 256 + r->m_zhdr1) % 31 != 0) || (r->m_zhdr1 & 32) || ((r->m_zhdr0 & 15) != 8)); if (!(decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) counter |= (((1U << (8U + (r->m_zhdr0 >> 4))) > 32768U) || ((out_buf_size_mask + 1) < (size_t)(1U << (8U + (r->m_zhdr0 >> 4))))); if (counter) { TINFL_CR_RETURN_FOREVER(36, TINFL_STATUS_FAILED); } } do { TINFL_GET_BITS(3, r->m_final, 3); r->m_type = r->m_final >> 1; if (r->m_type == 0) { TINFL_SKIP_BITS(5, num_bits & 7); for (counter = 0; counter < 4; ++counter) { if (num_bits) TINFL_GET_BITS(6, r->m_raw_header[counter], 8); else TINFL_GET_BYTE(7, r->m_raw_header[counter]); } if ((counter = (r->m_raw_header[0] | (r->m_raw_header[1] << 8))) != (mz_uint)(0xFFFF ^(r->m_raw_header[2] | (r->m_raw_header[3] << 8)))) { TINFL_CR_RETURN_FOREVER(39, TINFL_STATUS_FAILED); } while ((counter) && (num_bits)) { TINFL_GET_BITS(51, dist, 8); while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(52, TINFL_STATUS_HAS_MORE_OUTPUT); } *pOut_buf_cur++ = (mz_uint8)dist; counter--; } while (counter) { size_t n; while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(9, TINFL_STATUS_HAS_MORE_OUTPUT); } while (pIn_buf_cur >= pIn_buf_end) { if (decomp_flags & TINFL_FLAG_HAS_MORE_INPUT) { TINFL_CR_RETURN(38, TINFL_STATUS_NEEDS_MORE_INPUT); } else { TINFL_CR_RETURN_FOREVER(40, TINFL_STATUS_FAILED); } } n = MZ_MIN(MZ_MIN((size_t)(pOut_buf_end - pOut_buf_cur), (size_t)(pIn_buf_end - pIn_buf_cur)), counter); TINFL_MEMCPY(pOut_buf_cur, pIn_buf_cur, n); pIn_buf_cur += n; pOut_buf_cur += n; counter -= (mz_uint)n; } } else if (r->m_type == 3) { TINFL_CR_RETURN_FOREVER(10, TINFL_STATUS_FAILED); } else { if (r->m_type == 1) { mz_uint8 *p = r->m_tables[0].m_code_size; mz_uint i; r->m_table_sizes[0] = 288; r->m_table_sizes[1] = 32; TINFL_MEMSET(r->m_tables[1].m_code_size, 5, 32); for (i = 0; i <= 143; ++i) *p++ = 8; for (; i <= 255; ++i) *p++ = 9; for (; i <= 279; ++i) *p++ = 7; for (; i <= 287; ++i) *p++ = 8; } else { for (counter = 0; counter < 3; counter++) { TINFL_GET_BITS(11, r->m_table_sizes[counter], "\05\05\04"[counter]); r->m_table_sizes[counter] += s_min_table_sizes[counter]; } MZ_CLEAR_OBJ(r->m_tables[2].m_code_size); for (counter = 0; counter < r->m_table_sizes[2]; counter++) { mz_uint s; TINFL_GET_BITS(14, s, 3); r->m_tables[2].m_code_size[s_length_dezigzag[counter]] = (mz_uint8)s; } r->m_table_sizes[2] = 19; } for (; (int)r->m_type >= 0; r->m_type--) { int tree_next, tree_cur; tinfl_huff_table *pTable; mz_uint i, j, used_syms, total, sym_index, next_code[17], total_syms[16]; pTable = &r->m_tables[r->m_type]; MZ_CLEAR_OBJ(total_syms); MZ_CLEAR_OBJ(pTable->m_look_up); MZ_CLEAR_OBJ(pTable->m_tree); for (i = 0; i < r->m_table_sizes[r->m_type]; ++i) total_syms[pTable->m_code_size[i]]++; used_syms = 0, total = 0; next_code[0] = next_code[1] = 0; for (i = 1; i <= 15; ++i) { used_syms += total_syms[i]; next_code[i + 1] = (total = ((total + total_syms[i]) << 1)); } if ((65536 != total) && (used_syms > 1)) { TINFL_CR_RETURN_FOREVER(35, TINFL_STATUS_FAILED); } for (tree_next = -1, sym_index = 0; sym_index < r->m_table_sizes[r->m_type]; ++sym_index) { mz_uint rev_code = 0, l, cur_code, code_size = pTable->m_code_size[sym_index]; if (!code_size) continue; cur_code = next_code[code_size]++; for (l = code_size; l > 0; l--, cur_code >>= 1) rev_code = (rev_code << 1) | (cur_code & 1); if (code_size <= TINFL_FAST_LOOKUP_BITS) { mz_int16 k = (mz_int16)((code_size << 9) | sym_index); while (rev_code < TINFL_FAST_LOOKUP_SIZE) { pTable->m_look_up[rev_code] = k; rev_code += (1 << code_size); } continue; } if (0 == (tree_cur = pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)])) { pTable->m_look_up[rev_code & (TINFL_FAST_LOOKUP_SIZE - 1)] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; } rev_code >>= (TINFL_FAST_LOOKUP_BITS - 1); for (j = code_size; j > (TINFL_FAST_LOOKUP_BITS + 1); j--) { tree_cur -= ((rev_code >>= 1) & 1); if (!pTable->m_tree[-tree_cur - 1]) { pTable->m_tree[-tree_cur - 1] = (mz_int16)tree_next; tree_cur = tree_next; tree_next -= 2; } else tree_cur = pTable->m_tree[-tree_cur - 1]; } tree_cur -= ((rev_code >>= 1) & 1); pTable->m_tree[-tree_cur - 1] = (mz_int16)sym_index; } if (r->m_type == 2) { for (counter = 0; counter < (r->m_table_sizes[0] + r->m_table_sizes[1]);) { mz_uint s; TINFL_HUFF_DECODE(16, dist, &r->m_tables[2]); if (dist < 16) { r->m_len_codes[counter++] = (mz_uint8)dist; continue; } if ((dist == 16) && (!counter)) { TINFL_CR_RETURN_FOREVER(17, TINFL_STATUS_FAILED); } num_extra = "\02\03\07"[dist - 16]; TINFL_GET_BITS(18, s, num_extra); s += "\03\03\013"[dist - 16]; TINFL_MEMSET(r->m_len_codes + counter, (dist == 16) ? r->m_len_codes[counter - 1] : 0, s); counter += s; } if ((r->m_table_sizes[0] + r->m_table_sizes[1]) != counter) { TINFL_CR_RETURN_FOREVER(21, TINFL_STATUS_FAILED); } TINFL_MEMCPY(r->m_tables[0].m_code_size, r->m_len_codes, r->m_table_sizes[0]); TINFL_MEMCPY(r->m_tables[1].m_code_size, r->m_len_codes + r->m_table_sizes[0], r->m_table_sizes[1]); } } for (; ;) { mz_uint8 *pSrc; for (; ;) { if (((pIn_buf_end - pIn_buf_cur) < 4) || ((pOut_buf_end - pOut_buf_cur) < 2)) { TINFL_HUFF_DECODE(23, counter, &r->m_tables[0]); if (counter >= 256) break; while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(24, TINFL_STATUS_HAS_MORE_OUTPUT); } *pOut_buf_cur++ = (mz_uint8)counter; } else { int sym2; mz_uint code_len; #if TINFL_USE_64BIT_BITBUF if (num_bits < 30) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE32(pIn_buf_cur)) << num_bits); pIn_buf_cur += 4; num_bits += 32; } #else if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; } #endif if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) code_len = sym2 >> 9; else { code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0); } counter = sym2; bit_buf >>= code_len; num_bits -= code_len; if (counter & 256) break; #if !TINFL_USE_64BIT_BITBUF if (num_bits < 15) { bit_buf |= (((tinfl_bit_buf_t)MZ_READ_LE16(pIn_buf_cur)) << num_bits); pIn_buf_cur += 2; num_bits += 16; } #endif if ((sym2 = r->m_tables[0].m_look_up[bit_buf & (TINFL_FAST_LOOKUP_SIZE - 1)]) >= 0) code_len = sym2 >> 9; else { code_len = TINFL_FAST_LOOKUP_BITS; do { sym2 = r->m_tables[0].m_tree[~sym2 + ((bit_buf >> code_len++) & 1)]; } while (sym2 < 0); } bit_buf >>= code_len; num_bits -= code_len; pOut_buf_cur[0] = (mz_uint8)counter; if (sym2 & 256) { pOut_buf_cur++; counter = sym2; break; } pOut_buf_cur[1] = (mz_uint8)sym2; pOut_buf_cur += 2; } } if ((counter &= 511) == 256) break; num_extra = s_length_extra[counter - 257]; counter = s_length_base[counter - 257]; if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(25, extra_bits, num_extra); counter += extra_bits; } TINFL_HUFF_DECODE(26, dist, &r->m_tables[1]); num_extra = s_dist_extra[dist]; dist = s_dist_base[dist]; if (num_extra) { mz_uint extra_bits; TINFL_GET_BITS(27, extra_bits, num_extra); dist += extra_bits; } dist_from_out_buf_start = pOut_buf_cur - pOut_buf_start; if ((dist > dist_from_out_buf_start) && (decomp_flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF)) { TINFL_CR_RETURN_FOREVER(37, TINFL_STATUS_FAILED); } pSrc = pOut_buf_start + ((dist_from_out_buf_start - dist) & out_buf_size_mask); if ((MZ_MAX(pOut_buf_cur, pSrc) + counter) > pOut_buf_end) { while (counter--) { while (pOut_buf_cur >= pOut_buf_end) { TINFL_CR_RETURN(53, TINFL_STATUS_HAS_MORE_OUTPUT); } *pOut_buf_cur++ = pOut_buf_start[(dist_from_out_buf_start++ - dist) & out_buf_size_mask]; } continue; } #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES else if ((counter >= 9) && (counter <= dist)) { const mz_uint8 *pSrc_end = pSrc + (counter & ~7); do { ((mz_uint32 *)pOut_buf_cur)[0] = ((const mz_uint32 *)pSrc)[0]; ((mz_uint32 *)pOut_buf_cur)[1] = ((const mz_uint32 *)pSrc)[1]; pOut_buf_cur += 8; } while ((pSrc += 8) < pSrc_end); if ((counter &= 7) < 3) { if (counter) { pOut_buf_cur[0] = pSrc[0]; if (counter > 1) pOut_buf_cur[1] = pSrc[1]; pOut_buf_cur += counter; } continue; } } #endif do { pOut_buf_cur[0] = pSrc[0]; pOut_buf_cur[1] = pSrc[1]; pOut_buf_cur[2] = pSrc[2]; pOut_buf_cur += 3; pSrc += 3; } while ((int)(counter -= 3) > 2); if ((int)counter > 0) { pOut_buf_cur[0] = pSrc[0]; if ((int)counter > 1) pOut_buf_cur[1] = pSrc[1]; pOut_buf_cur += counter; } } } } while (!(r->m_final & 1)); if (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) { TINFL_SKIP_BITS(32, num_bits & 7); for (counter = 0; counter < 4; ++counter) { mz_uint s; if (num_bits) TINFL_GET_BITS(41, s, 8); else TINFL_GET_BYTE(42, s); r->m_z_adler32 = (r->m_z_adler32 << 8) | s; } } TINFL_CR_RETURN_FOREVER(34, TINFL_STATUS_DONE); TINFL_CR_FINISH common_exit: r->m_num_bits = num_bits; r->m_bit_buf = bit_buf; r->m_dist = dist; r->m_counter = counter; r->m_num_extra = num_extra; r->m_dist_from_out_buf_start = dist_from_out_buf_start; *pIn_buf_size = pIn_buf_cur - pIn_buf_next; *pOut_buf_size = pOut_buf_cur - pOut_buf_next; if ((decomp_flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32)) && (status >= 0)) { const mz_uint8 *ptr = pOut_buf_next; size_t buf_len = *pOut_buf_size; mz_uint32 i, s1 = r->m_check_adler32 & 0xffff, s2 = r->m_check_adler32 >> 16; size_t block_len = buf_len % 5552; while (buf_len) { for (i = 0; i + 7 < block_len; i += 8, ptr += 8) { s1 += ptr[0], s2 += s1; s1 += ptr[1], s2 += s1; s1 += ptr[2], s2 += s1; s1 += ptr[3], s2 += s1; s1 += ptr[4], s2 += s1; s1 += ptr[5], s2 += s1; s1 += ptr[6], s2 += s1; s1 += ptr[7], s2 += s1; } for (; i < block_len; ++i) s1 += *ptr++, s2 += s1; s1 %= 65521U, s2 %= 65521U; buf_len -= block_len; block_len = 5552; } r->m_check_adler32 = (s2 << 16) + s1; if ((status == TINFL_STATUS_DONE) && (decomp_flags & TINFL_FLAG_PARSE_ZLIB_HEADER) && (r->m_check_adler32 != r->m_z_adler32)) status = TINFL_STATUS_ADLER32_MISMATCH; } return status; } // Higher level helper functions. void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags) { tinfl_decompressor decomp; void *pBuf = NULL, *pNew_buf; size_t src_buf_ofs = 0, out_buf_capacity = 0; *pOut_len = 0; tinfl_init(&decomp); for (; ;) { size_t src_buf_size = src_buf_len - src_buf_ofs, dst_buf_size = out_buf_capacity - *pOut_len, new_out_buf_capacity; tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf + src_buf_ofs, &src_buf_size, (mz_uint8*)pBuf, pBuf ? (mz_uint8*)pBuf + *pOut_len : NULL, &dst_buf_size, (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF); if ((status < 0) || (status == TINFL_STATUS_NEEDS_MORE_INPUT)) { MZ_FREE(pBuf); *pOut_len = 0; return NULL; } src_buf_ofs += src_buf_size; *pOut_len += dst_buf_size; if (status == TINFL_STATUS_DONE) break; new_out_buf_capacity = out_buf_capacity * 2; if (new_out_buf_capacity < 128) new_out_buf_capacity = 128; pNew_buf = MZ_REALLOC(pBuf, new_out_buf_capacity); if (!pNew_buf) { MZ_FREE(pBuf); *pOut_len = 0; return NULL; } pBuf = pNew_buf; out_buf_capacity = new_out_buf_capacity; } return pBuf; } size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags) { tinfl_decompressor decomp; tinfl_status status; tinfl_init(&decomp); status = tinfl_decompress(&decomp, (const mz_uint8*)pSrc_buf, &src_buf_len, (mz_uint8*)pOut_buf, (mz_uint8*)pOut_buf, &out_buf_len, (flags & ~TINFL_FLAG_HAS_MORE_INPUT) | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF); return (status != TINFL_STATUS_DONE) ? TINFL_DECOMPRESS_MEM_TO_MEM_FAILED : out_buf_len; } int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags) { int result = 0; tinfl_decompressor decomp; mz_uint8 *pDict = (mz_uint8*)MZ_MALLOC(TINFL_LZ_DICT_SIZE); size_t in_buf_ofs = 0, dict_ofs = 0; if (!pDict) return TINFL_STATUS_FAILED; tinfl_init(&decomp); for (; ;) { size_t in_buf_size = *pIn_buf_size - in_buf_ofs, dst_buf_size = TINFL_LZ_DICT_SIZE - dict_ofs; tinfl_status status = tinfl_decompress(&decomp, (const mz_uint8*)pIn_buf + in_buf_ofs, &in_buf_size, pDict, pDict + dict_ofs, &dst_buf_size, (flags & ~(TINFL_FLAG_HAS_MORE_INPUT | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF))); in_buf_ofs += in_buf_size; if ((dst_buf_size) && (!(*pPut_buf_func)(pDict + dict_ofs, (int)dst_buf_size, pPut_buf_user))) break; if (status != TINFL_STATUS_HAS_MORE_OUTPUT) { result = (status == TINFL_STATUS_DONE); break; } dict_ofs = (dict_ofs + dst_buf_size) & (TINFL_LZ_DICT_SIZE - 1); } MZ_FREE(pDict); *pIn_buf_size = in_buf_ofs; return result; } // ------------------- Low-level Compression (independent from all decompression API's) // Purposely making these tables static for faster init and thread safety. static const mz_uint16 s_tdefl_len_sym[256] = { 257,258,259,260,261,262,263,264,265,265,266,266,267,267,268,268,269,269,269,269,270,270,270,270,271,271,271,271,272,272,272,272, 273,273,273,273,273,273,273,273,274,274,274,274,274,274,274,274,275,275,275,275,275,275,275,275,276,276,276,276,276,276,276,276, 277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,277,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278,278, 279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,279,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280,280, 281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281,281, 282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282,282, 283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283,283, 284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,284,285 }; static const mz_uint8 s_tdefl_len_extra[256] = { 0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,0 }; static const mz_uint8 s_tdefl_small_dist_sym[512] = { 0,1,2,3,4,4,5,5,6,6,6,6,7,7,7,7,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11, 11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13, 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,14,14,14,14,14,14, 14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14, 14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15, 15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,16,16,16,16,16,16,16,16,16,16,16,16,16, 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,17,17,17,17,17,17,17,17,17,17,17,17,17,17, 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17, 17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17,17 }; static const mz_uint8 s_tdefl_small_dist_extra[512] = { 0,0,0,0,1,1,1,1,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5, 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7 }; static const mz_uint8 s_tdefl_large_dist_sym[128] = { 0,0,18,19,20,20,21,21,22,22,22,22,23,23,23,23,24,24,24,24,24,24,24,24,25,25,25,25,25,25,25,25,26,26,26,26,26,26,26,26,26,26,26,26, 26,26,26,26,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28, 28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29,29 }; static const mz_uint8 s_tdefl_large_dist_extra[128] = { 0,0,8,8,9,9,9,9,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13, 13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13 }; // Radix sorts tdefl_sym_freq[] array by 16-bit key m_key. Returns ptr to sorted values. typedef struct { mz_uint16 m_key, m_sym_index; } tdefl_sym_freq; static tdefl_sym_freq* tdefl_radix_sort_syms(mz_uint num_syms, tdefl_sym_freq* pSyms0, tdefl_sym_freq* pSyms1) { mz_uint32 total_passes = 2, pass_shift, pass, i, hist[256 * 2]; tdefl_sym_freq* pCur_syms = pSyms0, *pNew_syms = pSyms1; MZ_CLEAR_OBJ(hist); for (i = 0; i < num_syms; i++) { mz_uint freq = pSyms0[i].m_key; hist[freq & 0xFF]++; hist[256 + ((freq >> 8) & 0xFF)]++; } while ((total_passes > 1) && (num_syms == hist[(total_passes - 1) * 256])) total_passes--; for (pass_shift = 0, pass = 0; pass < total_passes; pass++, pass_shift += 8) { const mz_uint32* pHist = &hist[pass << 8]; mz_uint offsets[256], cur_ofs = 0; for (i = 0; i < 256; i++) { offsets[i] = cur_ofs; cur_ofs += pHist[i]; } for (i = 0; i < num_syms; i++) pNew_syms[offsets[(pCur_syms[i].m_key >> pass_shift) & 0xFF]++] = pCur_syms[i]; { tdefl_sym_freq* t = pCur_syms; pCur_syms = pNew_syms; pNew_syms = t; } } return pCur_syms; } // tdefl_calculate_minimum_redundancy() originally written by: Alistair Moffat, alistair@cs.mu.oz.au, Jyrki Katajainen, jyrki@diku.dk, November 1996. static void tdefl_calculate_minimum_redundancy(tdefl_sym_freq *A, int n) { int root, leaf, next, avbl, used, dpth; if (n==0) return; else if (n==1) { A[0].m_key = 1; return; } A[0].m_key += A[1].m_key; root = 0; leaf = 2; for (next=1; next < n-1; next++) { if (leaf>=n || A[root].m_key=n || (root=0; next--) A[next].m_key = A[A[next].m_key].m_key+1; avbl = 1; used = dpth = 0; root = n-2; next = n-1; while (avbl>0) { while (root>=0 && (int)A[root].m_key==dpth) { used++; root--; } while (avbl>used) { A[next--].m_key = (mz_uint16)(dpth); avbl--; } avbl = 2*used; dpth++; used = 0; } } // Limits canonical Huffman code table's max code size. enum { TDEFL_MAX_SUPPORTED_HUFF_CODESIZE = 32 }; static void tdefl_huffman_enforce_max_code_size(int *pNum_codes, int code_list_len, int max_code_size) { int i; mz_uint32 total = 0; if (code_list_len <= 1) return; for (i = max_code_size + 1; i <= TDEFL_MAX_SUPPORTED_HUFF_CODESIZE; i++) pNum_codes[max_code_size] += pNum_codes[i]; for (i = max_code_size; i > 0; i--) total += (((mz_uint32)pNum_codes[i]) << (max_code_size - i)); while (total != (1UL << max_code_size)) { pNum_codes[max_code_size]--; for (i = max_code_size - 1; i > 0; i--) if (pNum_codes[i]) { pNum_codes[i]--; pNum_codes[i + 1] += 2; break; } total--; } } static void tdefl_optimize_huffman_table(tdefl_compressor *d, int table_num, int table_len, int code_size_limit, int static_table) { int i, j, l, num_codes[1 + TDEFL_MAX_SUPPORTED_HUFF_CODESIZE]; mz_uint next_code[TDEFL_MAX_SUPPORTED_HUFF_CODESIZE + 1]; MZ_CLEAR_OBJ(num_codes); if (static_table) { for (i = 0; i < table_len; i++) num_codes[d->m_huff_code_sizes[table_num][i]]++; } else { tdefl_sym_freq syms0[TDEFL_MAX_HUFF_SYMBOLS], syms1[TDEFL_MAX_HUFF_SYMBOLS], *pSyms; int num_used_syms = 0; const mz_uint16 *pSym_count = &d->m_huff_count[table_num][0]; for (i = 0; i < table_len; i++) if (pSym_count[i]) { syms0[num_used_syms].m_key = (mz_uint16)pSym_count[i]; syms0[num_used_syms++].m_sym_index = (mz_uint16)i; } pSyms = tdefl_radix_sort_syms(num_used_syms, syms0, syms1); tdefl_calculate_minimum_redundancy(pSyms, num_used_syms); for (i = 0; i < num_used_syms; i++) num_codes[pSyms[i].m_key]++; tdefl_huffman_enforce_max_code_size(num_codes, num_used_syms, code_size_limit); MZ_CLEAR_OBJ(d->m_huff_code_sizes[table_num]); MZ_CLEAR_OBJ(d->m_huff_codes[table_num]); for (i = 1, j = num_used_syms; i <= code_size_limit; i++) for (l = num_codes[i]; l > 0; l--) d->m_huff_code_sizes[table_num][pSyms[--j].m_sym_index] = (mz_uint8)(i); } next_code[1] = 0; for (j = 0, i = 2; i <= code_size_limit; i++) next_code[i] = j = ((j + num_codes[i - 1]) << 1); for (i = 0; i < table_len; i++) { mz_uint rev_code = 0, code, code_size; if ((code_size = d->m_huff_code_sizes[table_num][i]) == 0) continue; code = next_code[code_size]++; for (l = code_size; l > 0; l--, code >>= 1) rev_code = (rev_code << 1) | (code & 1); d->m_huff_codes[table_num][i] = (mz_uint16)rev_code; } } #define TDEFL_PUT_BITS(b, l) do { \ mz_uint bits = b; mz_uint len = l; MZ_ASSERT(bits <= ((1U << len) - 1U)); \ d->m_bit_buffer |= (bits << d->m_bits_in); d->m_bits_in += len; \ while (d->m_bits_in >= 8) { \ if (d->m_pOutput_buf < d->m_pOutput_buf_end) \ *d->m_pOutput_buf++ = (mz_uint8)(d->m_bit_buffer); \ d->m_bit_buffer >>= 8; \ d->m_bits_in -= 8; \ } \ } MZ_MACRO_END #define TDEFL_RLE_PREV_CODE_SIZE() { if (rle_repeat_count) { \ if (rle_repeat_count < 3) { \ d->m_huff_count[2][prev_code_size] = (mz_uint16)(d->m_huff_count[2][prev_code_size] + rle_repeat_count); \ while (rle_repeat_count--) packed_code_sizes[num_packed_code_sizes++] = prev_code_size; \ } else { \ d->m_huff_count[2][16] = (mz_uint16)(d->m_huff_count[2][16] + 1); packed_code_sizes[num_packed_code_sizes++] = 16; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_repeat_count - 3); \ } rle_repeat_count = 0; } } #define TDEFL_RLE_ZERO_CODE_SIZE() { if (rle_z_count) { \ if (rle_z_count < 3) { \ d->m_huff_count[2][0] = (mz_uint16)(d->m_huff_count[2][0] + rle_z_count); while (rle_z_count--) packed_code_sizes[num_packed_code_sizes++] = 0; \ } else if (rle_z_count <= 10) { \ d->m_huff_count[2][17] = (mz_uint16)(d->m_huff_count[2][17] + 1); packed_code_sizes[num_packed_code_sizes++] = 17; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 3); \ } else { \ d->m_huff_count[2][18] = (mz_uint16)(d->m_huff_count[2][18] + 1); packed_code_sizes[num_packed_code_sizes++] = 18; packed_code_sizes[num_packed_code_sizes++] = (mz_uint8)(rle_z_count - 11); \ } rle_z_count = 0; } } static mz_uint8 s_tdefl_packed_code_size_syms_swizzle[] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; static void tdefl_start_dynamic_block(tdefl_compressor *d) { int num_lit_codes, num_dist_codes, num_bit_lengths; mz_uint i, total_code_sizes_to_pack, num_packed_code_sizes, rle_z_count, rle_repeat_count, packed_code_sizes_index; mz_uint8 code_sizes_to_pack[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], packed_code_sizes[TDEFL_MAX_HUFF_SYMBOLS_0 + TDEFL_MAX_HUFF_SYMBOLS_1], prev_code_size = 0xFF; d->m_huff_count[0][256] = 1; tdefl_optimize_huffman_table(d, 0, TDEFL_MAX_HUFF_SYMBOLS_0, 15, MZ_FALSE); tdefl_optimize_huffman_table(d, 1, TDEFL_MAX_HUFF_SYMBOLS_1, 15, MZ_FALSE); for (num_lit_codes = 286; num_lit_codes > 257; num_lit_codes--) if (d->m_huff_code_sizes[0][num_lit_codes - 1]) break; for (num_dist_codes = 30; num_dist_codes > 1; num_dist_codes--) if (d->m_huff_code_sizes[1][num_dist_codes - 1]) break; memcpy(code_sizes_to_pack, &d->m_huff_code_sizes[0][0], num_lit_codes); memcpy(code_sizes_to_pack + num_lit_codes, &d->m_huff_code_sizes[1][0], num_dist_codes); total_code_sizes_to_pack = num_lit_codes + num_dist_codes; num_packed_code_sizes = 0; rle_z_count = 0; rle_repeat_count = 0; memset(&d->m_huff_count[2][0], 0, sizeof(d->m_huff_count[2][0]) * TDEFL_MAX_HUFF_SYMBOLS_2); for (i = 0; i < total_code_sizes_to_pack; i++) { mz_uint8 code_size = code_sizes_to_pack[i]; if (!code_size) { TDEFL_RLE_PREV_CODE_SIZE(); if (++rle_z_count == 138) { TDEFL_RLE_ZERO_CODE_SIZE(); } } else { TDEFL_RLE_ZERO_CODE_SIZE(); if (code_size != prev_code_size) { TDEFL_RLE_PREV_CODE_SIZE(); d->m_huff_count[2][code_size] = (mz_uint16)(d->m_huff_count[2][code_size] + 1); packed_code_sizes[num_packed_code_sizes++] = code_size; } else if (++rle_repeat_count == 6) { TDEFL_RLE_PREV_CODE_SIZE(); } } prev_code_size = code_size; } if (rle_repeat_count) { TDEFL_RLE_PREV_CODE_SIZE(); } else { TDEFL_RLE_ZERO_CODE_SIZE(); } tdefl_optimize_huffman_table(d, 2, TDEFL_MAX_HUFF_SYMBOLS_2, 7, MZ_FALSE); TDEFL_PUT_BITS(2, 2); TDEFL_PUT_BITS(num_lit_codes - 257, 5); TDEFL_PUT_BITS(num_dist_codes - 1, 5); for (num_bit_lengths = 18; num_bit_lengths >= 0; num_bit_lengths--) if (d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[num_bit_lengths]]) break; num_bit_lengths = MZ_MAX(4, (num_bit_lengths + 1)); TDEFL_PUT_BITS(num_bit_lengths - 4, 4); for (i = 0; (int)i < num_bit_lengths; i++) TDEFL_PUT_BITS(d->m_huff_code_sizes[2][s_tdefl_packed_code_size_syms_swizzle[i]], 3); for (packed_code_sizes_index = 0; packed_code_sizes_index < num_packed_code_sizes;) { mz_uint code = packed_code_sizes[packed_code_sizes_index++]; MZ_ASSERT(code < TDEFL_MAX_HUFF_SYMBOLS_2); TDEFL_PUT_BITS(d->m_huff_codes[2][code], d->m_huff_code_sizes[2][code]); if (code >= 16) TDEFL_PUT_BITS(packed_code_sizes[packed_code_sizes_index++], "\02\03\07"[code - 16]); } } static void tdefl_start_static_block(tdefl_compressor *d) { mz_uint i; mz_uint8 *p = &d->m_huff_code_sizes[0][0]; for (i = 0; i <= 143; ++i) *p++ = 8; for (; i <= 255; ++i) *p++ = 9; for (; i <= 279; ++i) *p++ = 7; for (; i <= 287; ++i) *p++ = 8; memset(d->m_huff_code_sizes[1], 5, 32); tdefl_optimize_huffman_table(d, 0, 288, 15, MZ_TRUE); tdefl_optimize_huffman_table(d, 1, 32, 15, MZ_TRUE); TDEFL_PUT_BITS(1, 2); } static const mz_uint mz_bitmasks[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF }; #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) { mz_uint flags; mz_uint8 *pLZ_codes; mz_uint8 *pOutput_buf = d->m_pOutput_buf; mz_uint8 *pLZ_code_buf_end = d->m_pLZ_code_buf; mz_uint64 bit_buffer = d->m_bit_buffer; mz_uint bits_in = d->m_bits_in; #define TDEFL_PUT_BITS_FAST(b, l) { bit_buffer |= (((mz_uint64)(b)) << bits_in); bits_in += (l); } flags = 1; for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < pLZ_code_buf_end; flags >>= 1) { if (flags == 1) flags = *pLZ_codes++ | 0x100; if (flags & 1) { mz_uint s0, s1, n0, n1, sym, num_extra_bits; mz_uint match_len = pLZ_codes[0], match_dist = *(const mz_uint16 *)(pLZ_codes + 1); pLZ_codes += 3; MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); TDEFL_PUT_BITS_FAST(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]); // This sequence coaxes MSVC into using cmov's vs. jmp's. s0 = s_tdefl_small_dist_sym[match_dist & 511]; n0 = s_tdefl_small_dist_extra[match_dist & 511]; s1 = s_tdefl_large_dist_sym[match_dist >> 8]; n1 = s_tdefl_large_dist_extra[match_dist >> 8]; sym = (match_dist < 512) ? s0 : s1; num_extra_bits = (match_dist < 512) ? n0 : n1; MZ_ASSERT(d->m_huff_code_sizes[1][sym]); TDEFL_PUT_BITS_FAST(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]); TDEFL_PUT_BITS_FAST(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits); } else { mz_uint lit = *pLZ_codes++; MZ_ASSERT(d->m_huff_code_sizes[0][lit]); TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) { flags >>= 1; lit = *pLZ_codes++; MZ_ASSERT(d->m_huff_code_sizes[0][lit]); TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); if (((flags & 2) == 0) && (pLZ_codes < pLZ_code_buf_end)) { flags >>= 1; lit = *pLZ_codes++; MZ_ASSERT(d->m_huff_code_sizes[0][lit]); TDEFL_PUT_BITS_FAST(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); } } } if (pOutput_buf >= d->m_pOutput_buf_end) return MZ_FALSE; *(mz_uint64*)pOutput_buf = bit_buffer; pOutput_buf += (bits_in >> 3); bit_buffer >>= (bits_in & ~7); bits_in &= 7; } #undef TDEFL_PUT_BITS_FAST d->m_pOutput_buf = pOutput_buf; d->m_bits_in = 0; d->m_bit_buffer = 0; while (bits_in) { mz_uint32 n = MZ_MIN(bits_in, 16); TDEFL_PUT_BITS((mz_uint)bit_buffer & mz_bitmasks[n], n); bit_buffer >>= n; bits_in -= n; } TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]); return (d->m_pOutput_buf < d->m_pOutput_buf_end); } #else static mz_bool tdefl_compress_lz_codes(tdefl_compressor *d) { mz_uint flags; mz_uint8 *pLZ_codes; flags = 1; for (pLZ_codes = d->m_lz_code_buf; pLZ_codes < d->m_pLZ_code_buf; flags >>= 1) { if (flags == 1) flags = *pLZ_codes++ | 0x100; if (flags & 1) { mz_uint sym, num_extra_bits; mz_uint match_len = pLZ_codes[0], match_dist = (pLZ_codes[1] | (pLZ_codes[2] << 8)); pLZ_codes += 3; MZ_ASSERT(d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); TDEFL_PUT_BITS(d->m_huff_codes[0][s_tdefl_len_sym[match_len]], d->m_huff_code_sizes[0][s_tdefl_len_sym[match_len]]); TDEFL_PUT_BITS(match_len & mz_bitmasks[s_tdefl_len_extra[match_len]], s_tdefl_len_extra[match_len]); if (match_dist < 512) { sym = s_tdefl_small_dist_sym[match_dist]; num_extra_bits = s_tdefl_small_dist_extra[match_dist]; } else { sym = s_tdefl_large_dist_sym[match_dist >> 8]; num_extra_bits = s_tdefl_large_dist_extra[match_dist >> 8]; } MZ_ASSERT(d->m_huff_code_sizes[1][sym]); TDEFL_PUT_BITS(d->m_huff_codes[1][sym], d->m_huff_code_sizes[1][sym]); TDEFL_PUT_BITS(match_dist & mz_bitmasks[num_extra_bits], num_extra_bits); } else { mz_uint lit = *pLZ_codes++; MZ_ASSERT(d->m_huff_code_sizes[0][lit]); TDEFL_PUT_BITS(d->m_huff_codes[0][lit], d->m_huff_code_sizes[0][lit]); } } TDEFL_PUT_BITS(d->m_huff_codes[0][256], d->m_huff_code_sizes[0][256]); return (d->m_pOutput_buf < d->m_pOutput_buf_end); } #endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN && MINIZ_HAS_64BIT_REGISTERS static mz_bool tdefl_compress_block(tdefl_compressor *d, mz_bool static_block) { if (static_block) tdefl_start_static_block(d); else tdefl_start_dynamic_block(d); return tdefl_compress_lz_codes(d); } static int tdefl_flush_block(tdefl_compressor *d, int flush) { mz_uint saved_bit_buf, saved_bits_in; mz_uint8 *pSaved_output_buf; mz_bool comp_block_succeeded = MZ_FALSE; int n, use_raw_block = ((d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS) != 0) && (d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size; mz_uint8 *pOutput_buf_start = ((d->m_pPut_buf_func == NULL) && ((*d->m_pOut_buf_size - d->m_out_buf_ofs) >= TDEFL_OUT_BUF_SIZE)) ? ((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs) : d->m_output_buf; d->m_pOutput_buf = pOutput_buf_start; d->m_pOutput_buf_end = d->m_pOutput_buf + TDEFL_OUT_BUF_SIZE - 16; MZ_ASSERT(!d->m_output_flush_remaining); d->m_output_flush_ofs = 0; d->m_output_flush_remaining = 0; *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> d->m_num_flags_left); d->m_pLZ_code_buf -= (d->m_num_flags_left == 8); if ((d->m_flags & TDEFL_WRITE_ZLIB_HEADER) && (!d->m_block_index)) { TDEFL_PUT_BITS(0x78, 8); TDEFL_PUT_BITS(0x01, 8); } TDEFL_PUT_BITS(flush == TDEFL_FINISH, 1); pSaved_output_buf = d->m_pOutput_buf; saved_bit_buf = d->m_bit_buffer; saved_bits_in = d->m_bits_in; if (!use_raw_block) comp_block_succeeded = tdefl_compress_block(d, (d->m_flags & TDEFL_FORCE_ALL_STATIC_BLOCKS) || (d->m_total_lz_bytes < 48)); // If the block gets expanded, forget the current contents of the output buffer and send a raw block instead. if (((use_raw_block) || ((d->m_total_lz_bytes) && ((d->m_pOutput_buf - pSaved_output_buf + 1U) >= d->m_total_lz_bytes))) && ((d->m_lookahead_pos - d->m_lz_code_buf_dict_pos) <= d->m_dict_size)) { mz_uint i; d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in; TDEFL_PUT_BITS(0, 2); if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } for (i = 2; i; --i, d->m_total_lz_bytes ^= 0xFFFF) { TDEFL_PUT_BITS(d->m_total_lz_bytes & 0xFFFF, 16); } for (i = 0; i < d->m_total_lz_bytes; ++i) { TDEFL_PUT_BITS(d->m_dict[(d->m_lz_code_buf_dict_pos + i) & TDEFL_LZ_DICT_SIZE_MASK], 8); } } // Check for the extremely unlikely (if not impossible) case of the compressed block not fitting into the output buffer when using dynamic codes. else if (!comp_block_succeeded) { d->m_pOutput_buf = pSaved_output_buf; d->m_bit_buffer = saved_bit_buf, d->m_bits_in = saved_bits_in; tdefl_compress_block(d, MZ_TRUE); } if (flush) { if (flush == TDEFL_FINISH) { if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } if (d->m_flags & TDEFL_WRITE_ZLIB_HEADER) { mz_uint i, a = d->m_adler32; for (i = 0; i < 4; i++) { TDEFL_PUT_BITS((a >> 24) & 0xFF, 8); a <<= 8; } } } else { mz_uint i, z = 0; TDEFL_PUT_BITS(0, 3); if (d->m_bits_in) { TDEFL_PUT_BITS(0, 8 - d->m_bits_in); } for (i = 2; i; --i, z ^= 0xFFFF) { TDEFL_PUT_BITS(z & 0xFFFF, 16); } } } MZ_ASSERT(d->m_pOutput_buf < d->m_pOutput_buf_end); memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0); memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1); d->m_pLZ_code_buf = d->m_lz_code_buf + 1; d->m_pLZ_flags = d->m_lz_code_buf; d->m_num_flags_left = 8; d->m_lz_code_buf_dict_pos += d->m_total_lz_bytes; d->m_total_lz_bytes = 0; d->m_block_index++; if ((n = (int)(d->m_pOutput_buf - pOutput_buf_start)) != 0) { if (d->m_pPut_buf_func) { *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf; if (!(*d->m_pPut_buf_func)(d->m_output_buf, n, d->m_pPut_buf_user)) return (d->m_prev_return_status = TDEFL_STATUS_PUT_BUF_FAILED); } else if (pOutput_buf_start == d->m_output_buf) { int bytes_to_copy = (int)MZ_MIN((size_t)n, (size_t)(*d->m_pOut_buf_size - d->m_out_buf_ofs)); memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf, bytes_to_copy); d->m_out_buf_ofs += bytes_to_copy; if ((n -= bytes_to_copy) != 0) { d->m_output_flush_ofs = bytes_to_copy; d->m_output_flush_remaining = n; } } else { d->m_out_buf_ofs += n; } } return d->m_output_flush_remaining; } #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES #define TDEFL_READ_UNALIGNED_WORD(p) *(const mz_uint16*)(p) static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len) { mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len; mz_uint num_probes_left = d->m_max_probes[match_len >= 32]; const mz_uint16 *s = (const mz_uint16*)(d->m_dict + pos), *p, *q; mz_uint16 c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]), s01 = TDEFL_READ_UNALIGNED_WORD(s); MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); if (max_match_len <= match_len) return; for (; ;) { for (; ;) { if (--num_probes_left == 0) return; #define TDEFL_PROBE \ next_probe_pos = d->m_next[probe_pos]; \ if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \ probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \ if (TDEFL_READ_UNALIGNED_WORD(&d->m_dict[probe_pos + match_len - 1]) == c01) break; TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE; } if (!dist) break; q = (const mz_uint16*)(d->m_dict + probe_pos); if (TDEFL_READ_UNALIGNED_WORD(q) != s01) continue; p = s; probe_len = 32; do { } while ((TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0)); if (!probe_len) { *pMatch_dist = dist; *pMatch_len = MZ_MIN(max_match_len, TDEFL_MAX_MATCH_LEN); break; } else if ((probe_len = ((mz_uint)(p - s) * 2) + (mz_uint)(*(const mz_uint8*)p == *(const mz_uint8*)q)) > match_len) { *pMatch_dist = dist; if ((*pMatch_len = match_len = MZ_MIN(max_match_len, probe_len)) == max_match_len) break; c01 = TDEFL_READ_UNALIGNED_WORD(&d->m_dict[pos + match_len - 1]); } } } #else static MZ_FORCEINLINE void tdefl_find_match(tdefl_compressor *d, mz_uint lookahead_pos, mz_uint max_dist, mz_uint max_match_len, mz_uint *pMatch_dist, mz_uint *pMatch_len) { mz_uint dist, pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK, match_len = *pMatch_len, probe_pos = pos, next_probe_pos, probe_len; mz_uint num_probes_left = d->m_max_probes[match_len >= 32]; const mz_uint8 *s = d->m_dict + pos, *p, *q; mz_uint8 c0 = d->m_dict[pos + match_len], c1 = d->m_dict[pos + match_len - 1]; MZ_ASSERT(max_match_len <= TDEFL_MAX_MATCH_LEN); if (max_match_len <= match_len) return; for (; ;) { for (; ;) { if (--num_probes_left == 0) return; #define TDEFL_PROBE \ next_probe_pos = d->m_next[probe_pos]; \ if ((!next_probe_pos) || ((dist = (mz_uint16)(lookahead_pos - next_probe_pos)) > max_dist)) return; \ probe_pos = next_probe_pos & TDEFL_LZ_DICT_SIZE_MASK; \ if ((d->m_dict[probe_pos + match_len] == c0) && (d->m_dict[probe_pos + match_len - 1] == c1)) break; TDEFL_PROBE; TDEFL_PROBE; TDEFL_PROBE; } if (!dist) break; p = s; q = d->m_dict + probe_pos; for (probe_len = 0; probe_len < max_match_len; probe_len++) if (*p++ != *q++) break; if (probe_len > match_len) { *pMatch_dist = dist; if ((*pMatch_len = match_len = probe_len) == max_match_len) return; c0 = d->m_dict[pos + match_len]; c1 = d->m_dict[pos + match_len - 1]; } } } #endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN static mz_bool tdefl_compress_fast(tdefl_compressor *d) { // Faster, minimally featured LZRW1-style match+parse loop with better register utilization. Intended for applications where raw throughput is valued more highly than ratio. mz_uint lookahead_pos = d->m_lookahead_pos, lookahead_size = d->m_lookahead_size, dict_size = d->m_dict_size, total_lz_bytes = d->m_total_lz_bytes, num_flags_left = d->m_num_flags_left; mz_uint8 *pLZ_code_buf = d->m_pLZ_code_buf, *pLZ_flags = d->m_pLZ_flags; mz_uint cur_pos = lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK; while ((d->m_src_buf_left) || ((d->m_flush) && (lookahead_size))) { const mz_uint TDEFL_COMP_FAST_LOOKAHEAD_SIZE = 4096; mz_uint dst_pos = (lookahead_pos + lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK; mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(d->m_src_buf_left, TDEFL_COMP_FAST_LOOKAHEAD_SIZE - lookahead_size); d->m_src_buf_left -= num_bytes_to_process; lookahead_size += num_bytes_to_process; while (num_bytes_to_process) { mz_uint32 n = MZ_MIN(TDEFL_LZ_DICT_SIZE - dst_pos, num_bytes_to_process); memcpy(d->m_dict + dst_pos, d->m_pSrc, n); if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) memcpy(d->m_dict + TDEFL_LZ_DICT_SIZE + dst_pos, d->m_pSrc, MZ_MIN(n, (TDEFL_MAX_MATCH_LEN - 1) - dst_pos)); d->m_pSrc += n; dst_pos = (dst_pos + n) & TDEFL_LZ_DICT_SIZE_MASK; num_bytes_to_process -= n; } dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - lookahead_size, dict_size); if ((!d->m_flush) && (lookahead_size < TDEFL_COMP_FAST_LOOKAHEAD_SIZE)) break; while (lookahead_size >= 4) { mz_uint cur_match_dist, cur_match_len = 1; mz_uint8 *pCur_dict = d->m_dict + cur_pos; mz_uint first_trigram = (*(const mz_uint32 *)pCur_dict) & 0xFFFFFF; mz_uint hash = (first_trigram ^(first_trigram >> (24 - (TDEFL_LZ_HASH_BITS - 8)))) & TDEFL_LEVEL1_HASH_SIZE_MASK; mz_uint probe_pos = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)lookahead_pos; if (((cur_match_dist = (mz_uint16)(lookahead_pos - probe_pos)) <= dict_size) && ((*(const mz_uint32 *)(d->m_dict + (probe_pos &= TDEFL_LZ_DICT_SIZE_MASK)) & 0xFFFFFF) == first_trigram)) { const mz_uint16 *p = (const mz_uint16 *)pCur_dict; const mz_uint16 *q = (const mz_uint16 *)(d->m_dict + probe_pos); mz_uint32 probe_len = 32; do { } while ((TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (TDEFL_READ_UNALIGNED_WORD(++p) == TDEFL_READ_UNALIGNED_WORD(++q)) && (--probe_len > 0)); cur_match_len = ((mz_uint)(p - (const mz_uint16 *)pCur_dict) * 2) + (mz_uint)(*(const mz_uint8 *)p == *(const mz_uint8 *)q); if (!probe_len) cur_match_len = cur_match_dist ? TDEFL_MAX_MATCH_LEN : 0; if ((cur_match_len < TDEFL_MIN_MATCH_LEN) || ((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U*1024U))) { cur_match_len = 1; *pLZ_code_buf++ = (mz_uint8)first_trigram; *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); d->m_huff_count[0][(mz_uint8)first_trigram]++; } else { mz_uint32 s0, s1; cur_match_len = MZ_MIN(cur_match_len, lookahead_size); MZ_ASSERT((cur_match_len >= TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 1) && (cur_match_dist <= TDEFL_LZ_DICT_SIZE)); cur_match_dist--; pLZ_code_buf[0] = (mz_uint8)(cur_match_len - TDEFL_MIN_MATCH_LEN); *(mz_uint16 *)(&pLZ_code_buf[1]) = (mz_uint16)cur_match_dist; pLZ_code_buf += 3; *pLZ_flags = (mz_uint8)((*pLZ_flags >> 1) | 0x80); s0 = s_tdefl_small_dist_sym[cur_match_dist & 511]; s1 = s_tdefl_large_dist_sym[cur_match_dist >> 8]; d->m_huff_count[1][(cur_match_dist < 512) ? s0 : s1]++; d->m_huff_count[0][s_tdefl_len_sym[cur_match_len - TDEFL_MIN_MATCH_LEN]]++; } } else { *pLZ_code_buf++ = (mz_uint8)first_trigram; *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); d->m_huff_count[0][(mz_uint8)first_trigram]++; } if (--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; } total_lz_bytes += cur_match_len; lookahead_pos += cur_match_len; dict_size = MZ_MIN(dict_size + cur_match_len, TDEFL_LZ_DICT_SIZE); cur_pos = (cur_pos + cur_match_len) & TDEFL_LZ_DICT_SIZE_MASK; MZ_ASSERT(lookahead_size >= cur_match_len); lookahead_size -= cur_match_len; if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) { int n; d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size; d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left; if ((n = tdefl_flush_block(d, 0)) != 0) return (n < 0) ? MZ_FALSE : MZ_TRUE; total_lz_bytes = d->m_total_lz_bytes; pLZ_code_buf = d->m_pLZ_code_buf; pLZ_flags = d->m_pLZ_flags; num_flags_left = d->m_num_flags_left; } } while (lookahead_size) { mz_uint8 lit = d->m_dict[cur_pos]; total_lz_bytes++; *pLZ_code_buf++ = lit; *pLZ_flags = (mz_uint8)(*pLZ_flags >> 1); if (--num_flags_left == 0) { num_flags_left = 8; pLZ_flags = pLZ_code_buf++; } d->m_huff_count[0][lit]++; lookahead_pos++; dict_size = MZ_MIN(dict_size + 1, TDEFL_LZ_DICT_SIZE); cur_pos = (cur_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; lookahead_size--; if (pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) { int n; d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size; d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left; if ((n = tdefl_flush_block(d, 0)) != 0) return (n < 0) ? MZ_FALSE : MZ_TRUE; total_lz_bytes = d->m_total_lz_bytes; pLZ_code_buf = d->m_pLZ_code_buf; pLZ_flags = d->m_pLZ_flags; num_flags_left = d->m_num_flags_left; } } } d->m_lookahead_pos = lookahead_pos; d->m_lookahead_size = lookahead_size; d->m_dict_size = dict_size; d->m_total_lz_bytes = total_lz_bytes; d->m_pLZ_code_buf = pLZ_code_buf; d->m_pLZ_flags = pLZ_flags; d->m_num_flags_left = num_flags_left; return MZ_TRUE; } #endif // MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN static MZ_FORCEINLINE void tdefl_record_literal(tdefl_compressor *d, mz_uint8 lit) { d->m_total_lz_bytes++; *d->m_pLZ_code_buf++ = lit; *d->m_pLZ_flags = (mz_uint8)(*d->m_pLZ_flags >> 1); if (--d->m_num_flags_left == 0) { d->m_num_flags_left = 8; d->m_pLZ_flags = d->m_pLZ_code_buf++; } d->m_huff_count[0][lit]++; } static MZ_FORCEINLINE void tdefl_record_match(tdefl_compressor *d, mz_uint match_len, mz_uint match_dist) { mz_uint32 s0, s1; MZ_ASSERT((match_len >= TDEFL_MIN_MATCH_LEN) && (match_dist >= 1) && (match_dist <= TDEFL_LZ_DICT_SIZE)); d->m_total_lz_bytes += match_len; d->m_pLZ_code_buf[0] = (mz_uint8)(match_len - TDEFL_MIN_MATCH_LEN); match_dist -= 1; d->m_pLZ_code_buf[1] = (mz_uint8)(match_dist & 0xFF); d->m_pLZ_code_buf[2] = (mz_uint8)(match_dist >> 8); d->m_pLZ_code_buf += 3; *d->m_pLZ_flags = (mz_uint8)((*d->m_pLZ_flags >> 1) | 0x80); if (--d->m_num_flags_left == 0) { d->m_num_flags_left = 8; d->m_pLZ_flags = d->m_pLZ_code_buf++; } s0 = s_tdefl_small_dist_sym[match_dist & 511]; s1 = s_tdefl_large_dist_sym[(match_dist >> 8) & 127]; d->m_huff_count[1][(match_dist < 512) ? s0 : s1]++; if (match_len >= TDEFL_MIN_MATCH_LEN) d->m_huff_count[0][s_tdefl_len_sym[match_len - TDEFL_MIN_MATCH_LEN]]++; } static mz_bool tdefl_compress_normal(tdefl_compressor *d) { const mz_uint8 *pSrc = d->m_pSrc; size_t src_buf_left = d->m_src_buf_left; tdefl_flush flush = d->m_flush; while ((src_buf_left) || ((flush) && (d->m_lookahead_size))) { mz_uint len_to_move, cur_match_dist, cur_match_len, cur_pos; // Update dictionary and hash chains. Keeps the lookahead size equal to TDEFL_MAX_MATCH_LEN. if ((d->m_lookahead_size + d->m_dict_size) >= (TDEFL_MIN_MATCH_LEN - 1)) { mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK, ins_pos = d->m_lookahead_pos + d->m_lookahead_size - 2; mz_uint hash = (d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK]; mz_uint num_bytes_to_process = (mz_uint)MZ_MIN(src_buf_left, TDEFL_MAX_MATCH_LEN - d->m_lookahead_size); const mz_uint8 *pSrc_end = pSrc + num_bytes_to_process; src_buf_left -= num_bytes_to_process; d->m_lookahead_size += num_bytes_to_process; while (pSrc != pSrc_end) { mz_uint8 c = *pSrc++; d->m_dict[dst_pos] = c; if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c; hash = ((hash << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1); d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos); dst_pos = (dst_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK; ins_pos++; } } else { while ((src_buf_left) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) { mz_uint8 c = *pSrc++; mz_uint dst_pos = (d->m_lookahead_pos + d->m_lookahead_size) & TDEFL_LZ_DICT_SIZE_MASK; src_buf_left--; d->m_dict[dst_pos] = c; if (dst_pos < (TDEFL_MAX_MATCH_LEN - 1)) d->m_dict[TDEFL_LZ_DICT_SIZE + dst_pos] = c; if ((++d->m_lookahead_size + d->m_dict_size) >= TDEFL_MIN_MATCH_LEN) { mz_uint ins_pos = d->m_lookahead_pos + (d->m_lookahead_size - 1) - 2; mz_uint hash = ((d->m_dict[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] << (TDEFL_LZ_HASH_SHIFT * 2)) ^(d->m_dict[(ins_pos + 1) & TDEFL_LZ_DICT_SIZE_MASK] << TDEFL_LZ_HASH_SHIFT) ^ c) & (TDEFL_LZ_HASH_SIZE - 1); d->m_next[ins_pos & TDEFL_LZ_DICT_SIZE_MASK] = d->m_hash[hash]; d->m_hash[hash] = (mz_uint16)(ins_pos); } } } d->m_dict_size = MZ_MIN(TDEFL_LZ_DICT_SIZE - d->m_lookahead_size, d->m_dict_size); if ((!flush) && (d->m_lookahead_size < TDEFL_MAX_MATCH_LEN)) break; // Simple lazy/greedy parsing state machine. len_to_move = 1; cur_match_dist = 0; cur_match_len = d->m_saved_match_len ? d->m_saved_match_len : (TDEFL_MIN_MATCH_LEN - 1); cur_pos = d->m_lookahead_pos & TDEFL_LZ_DICT_SIZE_MASK; if (d->m_flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS)) { if ((d->m_dict_size) && (!(d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS))) { mz_uint8 c = d->m_dict[(cur_pos - 1) & TDEFL_LZ_DICT_SIZE_MASK]; cur_match_len = 0; while (cur_match_len < d->m_lookahead_size) { if (d->m_dict[cur_pos + cur_match_len] != c) break; cur_match_len++; } if (cur_match_len < TDEFL_MIN_MATCH_LEN) cur_match_len = 0; else cur_match_dist = 1; } } else { tdefl_find_match(d, d->m_lookahead_pos, d->m_dict_size, d->m_lookahead_size, &cur_match_dist, &cur_match_len); } if (((cur_match_len == TDEFL_MIN_MATCH_LEN) && (cur_match_dist >= 8U*1024U)) || (cur_pos == cur_match_dist) || ((d->m_flags & TDEFL_FILTER_MATCHES) && (cur_match_len <= 5))) { cur_match_dist = cur_match_len = 0; } if (d->m_saved_match_len) { if (cur_match_len > d->m_saved_match_len) { tdefl_record_literal(d, (mz_uint8)d->m_saved_lit); if (cur_match_len >= 128) { tdefl_record_match(d, cur_match_len, cur_match_dist); d->m_saved_match_len = 0; len_to_move = cur_match_len; } else { d->m_saved_lit = d->m_dict[cur_pos]; d->m_saved_match_dist = cur_match_dist; d->m_saved_match_len = cur_match_len; } } else { tdefl_record_match(d, d->m_saved_match_len, d->m_saved_match_dist); len_to_move = d->m_saved_match_len - 1; d->m_saved_match_len = 0; } } else if (!cur_match_dist) tdefl_record_literal(d, d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]); else if ((d->m_greedy_parsing) || (d->m_flags & TDEFL_RLE_MATCHES) || (cur_match_len >= 128)) { tdefl_record_match(d, cur_match_len, cur_match_dist); len_to_move = cur_match_len; } else { d->m_saved_lit = d->m_dict[MZ_MIN(cur_pos, sizeof(d->m_dict) - 1)]; d->m_saved_match_dist = cur_match_dist; d->m_saved_match_len = cur_match_len; } // Move the lookahead forward by len_to_move bytes. d->m_lookahead_pos += len_to_move; MZ_ASSERT(d->m_lookahead_size >= len_to_move); d->m_lookahead_size -= len_to_move; d->m_dict_size = MZ_MIN(d->m_dict_size + len_to_move, TDEFL_LZ_DICT_SIZE); // Check if it's time to flush the current LZ codes to the internal output buffer. if ((d->m_pLZ_code_buf > &d->m_lz_code_buf[TDEFL_LZ_CODE_BUF_SIZE - 8]) || ((d->m_total_lz_bytes > 31*1024) && (((((mz_uint)(d->m_pLZ_code_buf - d->m_lz_code_buf) * 115) >> 7) >= d->m_total_lz_bytes) || (d->m_flags & TDEFL_FORCE_ALL_RAW_BLOCKS)))) { int n; d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left; if ((n = tdefl_flush_block(d, 0)) != 0) return (n < 0) ? MZ_FALSE : MZ_TRUE; } } d->m_pSrc = pSrc; d->m_src_buf_left = src_buf_left; return MZ_TRUE; } static tdefl_status tdefl_flush_output_buffer(tdefl_compressor *d) { if (d->m_pIn_buf_size) { *d->m_pIn_buf_size = d->m_pSrc - (const mz_uint8 *)d->m_pIn_buf; } if (d->m_pOut_buf_size) { size_t n = MZ_MIN(*d->m_pOut_buf_size - d->m_out_buf_ofs, d->m_output_flush_remaining); memcpy((mz_uint8 *)d->m_pOut_buf + d->m_out_buf_ofs, d->m_output_buf + d->m_output_flush_ofs, n); d->m_output_flush_ofs += (mz_uint)n; d->m_output_flush_remaining -= (mz_uint)n; d->m_out_buf_ofs += n; *d->m_pOut_buf_size = d->m_out_buf_ofs; } return (d->m_finished && !d->m_output_flush_remaining) ? TDEFL_STATUS_DONE : TDEFL_STATUS_OKAY; } tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush) { if (!d) { if (pIn_buf_size) *pIn_buf_size = 0; if (pOut_buf_size) *pOut_buf_size = 0; return TDEFL_STATUS_BAD_PARAM; } d->m_pIn_buf = pIn_buf; d->m_pIn_buf_size = pIn_buf_size; d->m_pOut_buf = pOut_buf; d->m_pOut_buf_size = pOut_buf_size; d->m_pSrc = (const mz_uint8 *)(pIn_buf); d->m_src_buf_left = pIn_buf_size ? *pIn_buf_size : 0; d->m_out_buf_ofs = 0; d->m_flush = flush; if (((d->m_pPut_buf_func != NULL) == ((pOut_buf != NULL) || (pOut_buf_size != NULL))) || (d->m_prev_return_status != TDEFL_STATUS_OKAY) || (d->m_wants_to_finish && (flush != TDEFL_FINISH)) || (pIn_buf_size && *pIn_buf_size && !pIn_buf) || (pOut_buf_size && *pOut_buf_size && !pOut_buf)) { if (pIn_buf_size) *pIn_buf_size = 0; if (pOut_buf_size) *pOut_buf_size = 0; return (d->m_prev_return_status = TDEFL_STATUS_BAD_PARAM); } d->m_wants_to_finish |= (flush == TDEFL_FINISH); if ((d->m_output_flush_remaining) || (d->m_finished)) return (d->m_prev_return_status = tdefl_flush_output_buffer(d)); #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN if (((d->m_flags & TDEFL_MAX_PROBES_MASK) == 1) && ((d->m_flags & TDEFL_GREEDY_PARSING_FLAG) != 0) && ((d->m_flags & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS | TDEFL_RLE_MATCHES)) == 0)) { if (!tdefl_compress_fast(d)) return d->m_prev_return_status; } else #endif // #if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN { if (!tdefl_compress_normal(d)) return d->m_prev_return_status; } if ((d->m_flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32)) && (pIn_buf)) d->m_adler32 = (mz_uint32)mz_adler32(d->m_adler32, (const mz_uint8 *)pIn_buf, d->m_pSrc - (const mz_uint8 *)pIn_buf); if ((flush) && (!d->m_lookahead_size) && (!d->m_src_buf_left) && (!d->m_output_flush_remaining)) { if (tdefl_flush_block(d, flush) < 0) return d->m_prev_return_status; d->m_finished = (flush == TDEFL_FINISH); if (flush == TDEFL_FULL_FLUSH) { MZ_CLEAR_OBJ(d->m_hash); MZ_CLEAR_OBJ(d->m_next); d->m_dict_size = 0; } } return (d->m_prev_return_status = tdefl_flush_output_buffer(d)); } tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush) { MZ_ASSERT(d->m_pPut_buf_func); return tdefl_compress(d, pIn_buf, &in_buf_size, NULL, NULL, flush); } tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags) { d->m_pPut_buf_func = pPut_buf_func; d->m_pPut_buf_user = pPut_buf_user; d->m_flags = (mz_uint)(flags); d->m_max_probes[0] = 1 + ((flags & 0xFFF) + 2) / 3; d->m_greedy_parsing = (flags & TDEFL_GREEDY_PARSING_FLAG) != 0; d->m_max_probes[1] = 1 + (((flags & 0xFFF) >> 2) + 2) / 3; if (!(flags & TDEFL_NONDETERMINISTIC_PARSING_FLAG)) MZ_CLEAR_OBJ(d->m_hash); d->m_lookahead_pos = d->m_lookahead_size = d->m_dict_size = d->m_total_lz_bytes = d->m_lz_code_buf_dict_pos = d->m_bits_in = 0; d->m_output_flush_ofs = d->m_output_flush_remaining = d->m_finished = d->m_block_index = d->m_bit_buffer = d->m_wants_to_finish = 0; d->m_pLZ_code_buf = d->m_lz_code_buf + 1; d->m_pLZ_flags = d->m_lz_code_buf; d->m_num_flags_left = 8; d->m_pOutput_buf = d->m_output_buf; d->m_pOutput_buf_end = d->m_output_buf; d->m_prev_return_status = TDEFL_STATUS_OKAY; d->m_saved_match_dist = d->m_saved_match_len = d->m_saved_lit = 0; d->m_adler32 = 1; d->m_pIn_buf = NULL; d->m_pOut_buf = NULL; d->m_pIn_buf_size = NULL; d->m_pOut_buf_size = NULL; d->m_flush = TDEFL_NO_FLUSH; d->m_pSrc = NULL; d->m_src_buf_left = 0; d->m_out_buf_ofs = 0; memset(&d->m_huff_count[0][0], 0, sizeof(d->m_huff_count[0][0]) * TDEFL_MAX_HUFF_SYMBOLS_0); memset(&d->m_huff_count[1][0], 0, sizeof(d->m_huff_count[1][0]) * TDEFL_MAX_HUFF_SYMBOLS_1); return TDEFL_STATUS_OKAY; } tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d) { return d->m_prev_return_status; } mz_uint32 tdefl_get_adler32(tdefl_compressor *d) { return d->m_adler32; } mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags) { tdefl_compressor *pComp; mz_bool succeeded; if (((buf_len) && (!pBuf)) || (!pPut_buf_func)) return MZ_FALSE; pComp = (tdefl_compressor*)MZ_MALLOC(sizeof(tdefl_compressor)); if (!pComp) return MZ_FALSE; succeeded = (tdefl_init(pComp, pPut_buf_func, pPut_buf_user, flags) == TDEFL_STATUS_OKAY); succeeded = succeeded && (tdefl_compress_buffer(pComp, pBuf, buf_len, TDEFL_FINISH) == TDEFL_STATUS_DONE); MZ_FREE(pComp); return succeeded; } typedef struct { size_t m_size, m_capacity; mz_uint8 *m_pBuf; mz_bool m_expandable; } tdefl_output_buffer; static mz_bool tdefl_output_buffer_putter(const void *pBuf, int len, void *pUser) { tdefl_output_buffer *p = (tdefl_output_buffer *)pUser; size_t new_size = p->m_size + len; if (new_size > p->m_capacity) { size_t new_capacity = p->m_capacity; mz_uint8 *pNew_buf; if (!p->m_expandable) return MZ_FALSE; do { new_capacity = MZ_MAX(128U, new_capacity << 1U); } while (new_size > new_capacity); pNew_buf = (mz_uint8*)MZ_REALLOC(p->m_pBuf, new_capacity); if (!pNew_buf) return MZ_FALSE; p->m_pBuf = pNew_buf; p->m_capacity = new_capacity; } memcpy((mz_uint8*)p->m_pBuf + p->m_size, pBuf, len); p->m_size = new_size; return MZ_TRUE; } void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags) { tdefl_output_buffer out_buf; MZ_CLEAR_OBJ(out_buf); if (!pOut_len) return MZ_FALSE; else *pOut_len = 0; out_buf.m_expandable = MZ_TRUE; if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return NULL; *pOut_len = out_buf.m_size; return out_buf.m_pBuf; } size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags) { tdefl_output_buffer out_buf; MZ_CLEAR_OBJ(out_buf); if (!pOut_buf) return 0; out_buf.m_pBuf = (mz_uint8*)pOut_buf; out_buf.m_capacity = out_buf_len; if (!tdefl_compress_mem_to_output(pSrc_buf, src_buf_len, tdefl_output_buffer_putter, &out_buf, flags)) return 0; return out_buf.m_size; } #ifndef MINIZ_NO_ZLIB_APIS static const mz_uint s_tdefl_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 }; // level may actually range from [0,10] (10 is a "hidden" max level, where we want a bit more compression and it's fine if throughput to fall off a cliff on some files). mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy) { mz_uint comp_flags = s_tdefl_num_probes[(level >= 0) ? MZ_MIN(10, level) : MZ_DEFAULT_LEVEL] | ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0); if (window_bits > 0) comp_flags |= TDEFL_WRITE_ZLIB_HEADER; if (!level) comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS; else if (strategy == MZ_FILTERED) comp_flags |= TDEFL_FILTER_MATCHES; else if (strategy == MZ_HUFFMAN_ONLY) comp_flags &= ~TDEFL_MAX_PROBES_MASK; else if (strategy == MZ_FIXED) comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS; else if (strategy == MZ_RLE) comp_flags |= TDEFL_RLE_MATCHES; return comp_flags; } #endif //MINIZ_NO_ZLIB_APIS #ifdef _MSC_VER #pragma warning (push) #pragma warning (disable:4204) // nonstandard extension used : non-constant aggregate initializer (also supported by GNU C and C99, so no big deal) #endif // Simple PNG writer function by Alex Evans, 2011. Released into the public domain: https://gist.github.com/908299, more context at // http://altdevblogaday.org/2011/04/06/a-smaller-jpg-encoder/. void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out) { tdefl_compressor *pComp = (tdefl_compressor *)MZ_MALLOC(sizeof(tdefl_compressor)); tdefl_output_buffer out_buf; int i, bpl = w * num_chans, y, z; mz_uint32 c; *pLen_out = 0; if (!pComp) return NULL; MZ_CLEAR_OBJ(out_buf); out_buf.m_expandable = MZ_TRUE; out_buf.m_capacity = 57+MZ_MAX(64, (1+bpl)*h); if (NULL == (out_buf.m_pBuf = (mz_uint8*)MZ_MALLOC(out_buf.m_capacity))) { MZ_FREE(pComp); return NULL; } // write dummy header for (z = 41; z; --z) tdefl_output_buffer_putter(&z, 1, &out_buf); // compress image data tdefl_init(pComp, tdefl_output_buffer_putter, &out_buf, TDEFL_DEFAULT_MAX_PROBES | TDEFL_WRITE_ZLIB_HEADER); for (y = 0; y < h; ++y) { tdefl_compress_buffer(pComp, &z, 1, TDEFL_NO_FLUSH); tdefl_compress_buffer(pComp, (mz_uint8*)pImage + y * bpl, bpl, TDEFL_NO_FLUSH); } if (tdefl_compress_buffer(pComp, NULL, 0, TDEFL_FINISH) != TDEFL_STATUS_DONE) { MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; } // write real header *pLen_out = out_buf.m_size-41; { mz_uint8 pnghdr[41]= {0x89,0x50,0x4e,0x47,0x0d,0x0a,0x1a,0x0a,0x00,0x00,0x00,0x0d,0x49,0x48,0x44,0x52, 0,0,(mz_uint8)(w>>8),(mz_uint8)w,0,0,(mz_uint8)(h>>8),(mz_uint8)h,8,"\0\0\04\02\06"[num_chans],0,0,0,0,0,0,0, (mz_uint8)(*pLen_out>>24),(mz_uint8)(*pLen_out>>16),(mz_uint8)(*pLen_out>>8),(mz_uint8)*pLen_out,0x49,0x44,0x41,0x54 }; c=(mz_uint32)mz_crc32(MZ_CRC32_INIT,pnghdr+12,17); for (i=0; i<4; ++i, c<<=8)((mz_uint8*)(pnghdr+29))[i]=(mz_uint8)(c>>24); memcpy(out_buf.m_pBuf, pnghdr, 41); } // write footer (IDAT CRC-32, followed by IEND chunk) if (!tdefl_output_buffer_putter("\0\0\0\0\0\0\0\0\x49\x45\x4e\x44\xae\x42\x60\x82", 16, &out_buf)) { *pLen_out = 0; MZ_FREE(pComp); MZ_FREE(out_buf.m_pBuf); return NULL; } c = (mz_uint32)mz_crc32(MZ_CRC32_INIT,out_buf.m_pBuf+41-4, *pLen_out+4); for (i=0; i<4; ++i, c<<=8)(out_buf.m_pBuf+out_buf.m_size-16)[i] = (mz_uint8)(c >> 24); // compute final size of file, grab compressed data buffer and return *pLen_out += 57; MZ_FREE(pComp); return out_buf.m_pBuf; } #ifdef _MSC_VER #pragma warning (pop) #endif // ------------------- .ZIP archive reading #ifndef MINIZ_NO_ARCHIVE_APIS #ifdef MINIZ_NO_STDIO #define MZ_FILE void * #else #include #include #if defined(_MSC_VER) static FILE *mz_fopen(const char *pFilename, const char *pMode) { FILE* pFile = NULL; fopen_s(&pFile, pFilename, pMode); return pFile; } static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream) { FILE* pFile = NULL; if (freopen_s(&pFile, pPath, pMode, pStream)) return NULL; return pFile; } #else static FILE *mz_fopen(const char *pFilename, const char *pMode) { return fopen(pFilename, pMode); } static FILE *mz_freopen(const char *pPath, const char *pMode, FILE *pStream) { return freopen(pPath, pMode, pStream); } #endif // #if defined(_MSC_VER) #if defined(_MSC_VER) || defined(__MINGW64__) #ifndef MINIZ_NO_TIME #include #endif #define MZ_FILE FILE #define MZ_FOPEN mz_fopen #define MZ_FCLOSE fclose #define MZ_FREAD fread #define MZ_FWRITE fwrite #define MZ_FTELL64 _ftelli64 #define MZ_FSEEK64 _fseeki64 #define MZ_FILE_STAT_STRUCT _stat #define MZ_FILE_STAT _stat #define MZ_FFLUSH fflush #define MZ_FREOPEN mz_freopen #define MZ_DELETE_FILE remove #elif defined(__MINGW32__) #ifndef MINIZ_NO_TIME #include #endif #define MZ_FILE FILE #define MZ_FOPEN mz_fopen #define MZ_FCLOSE fclose #define MZ_FREAD fread #define MZ_FWRITE fwrite #define MZ_FTELL64 ftello64 #define MZ_FSEEK64 fseeko64 #define MZ_FILE_STAT_STRUCT _stat #define MZ_FILE_STAT _stat #define MZ_FFLUSH fflush #define MZ_FREOPEN mz_freopen #define MZ_DELETE_FILE remove #elif defined(__TINYC__) #ifndef MINIZ_NO_TIME #include #endif #define MZ_FILE FILE #define MZ_FOPEN mz_fopen #define MZ_FCLOSE fclose #define MZ_FREAD fread #define MZ_FWRITE fwrite #define MZ_FTELL64 ftell #define MZ_FSEEK64 fseek #define MZ_FILE_STAT_STRUCT stat #define MZ_FILE_STAT stat #define MZ_FFLUSH fflush #define MZ_FREOPEN mz_freopen #define MZ_DELETE_FILE remove #else #ifndef MINIZ_NO_TIME #include #endif #define MZ_FILE FILE #define MZ_FOPEN mz_fopen #define MZ_FCLOSE fclose #define MZ_FREAD fread #define MZ_FWRITE fwrite #define MZ_FTELL64 ftello #define MZ_FSEEK64 fseeko #define MZ_FILE_STAT_STRUCT stat #define MZ_FILE_STAT stat #define MZ_FFLUSH fflush #define MZ_FREOPEN mz_freopen #define MZ_DELETE_FILE remove #endif // #ifdef _MSC_VER #endif // #ifdef MINIZ_NO_STDIO #define MZ_TOLOWER(c) ((((c) >= 'A') && ((c) <= 'Z')) ? ((c) - 'A' + 'a') : (c)) // Various ZIP archive enums. To completely avoid cross platform compiler alignment and platform endian issues, miniz.c doesn't use structs for any of this stuff. enum { // ZIP archive identifiers and record sizes MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG = 0x06054b50, MZ_ZIP_CENTRAL_DIR_HEADER_SIG = 0x02014b50, MZ_ZIP_LOCAL_DIR_HEADER_SIG = 0x04034b50, MZ_ZIP_LOCAL_DIR_HEADER_SIZE = 30, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE = 46, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE = 22, // Central directory header record offsets MZ_ZIP_CDH_SIG_OFS = 0, MZ_ZIP_CDH_VERSION_MADE_BY_OFS = 4, MZ_ZIP_CDH_VERSION_NEEDED_OFS = 6, MZ_ZIP_CDH_BIT_FLAG_OFS = 8, MZ_ZIP_CDH_METHOD_OFS = 10, MZ_ZIP_CDH_FILE_TIME_OFS = 12, MZ_ZIP_CDH_FILE_DATE_OFS = 14, MZ_ZIP_CDH_CRC32_OFS = 16, MZ_ZIP_CDH_COMPRESSED_SIZE_OFS = 20, MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS = 24, MZ_ZIP_CDH_FILENAME_LEN_OFS = 28, MZ_ZIP_CDH_EXTRA_LEN_OFS = 30, MZ_ZIP_CDH_COMMENT_LEN_OFS = 32, MZ_ZIP_CDH_DISK_START_OFS = 34, MZ_ZIP_CDH_INTERNAL_ATTR_OFS = 36, MZ_ZIP_CDH_EXTERNAL_ATTR_OFS = 38, MZ_ZIP_CDH_LOCAL_HEADER_OFS = 42, // Local directory header offsets MZ_ZIP_LDH_SIG_OFS = 0, MZ_ZIP_LDH_VERSION_NEEDED_OFS = 4, MZ_ZIP_LDH_BIT_FLAG_OFS = 6, MZ_ZIP_LDH_METHOD_OFS = 8, MZ_ZIP_LDH_FILE_TIME_OFS = 10, MZ_ZIP_LDH_FILE_DATE_OFS = 12, MZ_ZIP_LDH_CRC32_OFS = 14, MZ_ZIP_LDH_COMPRESSED_SIZE_OFS = 18, MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS = 22, MZ_ZIP_LDH_FILENAME_LEN_OFS = 26, MZ_ZIP_LDH_EXTRA_LEN_OFS = 28, // End of central directory offsets MZ_ZIP_ECDH_SIG_OFS = 0, MZ_ZIP_ECDH_NUM_THIS_DISK_OFS = 4, MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS = 6, MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS = 8, MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS = 10, MZ_ZIP_ECDH_CDIR_SIZE_OFS = 12, MZ_ZIP_ECDH_CDIR_OFS_OFS = 16, MZ_ZIP_ECDH_COMMENT_SIZE_OFS = 20, }; typedef struct { void *m_p; size_t m_size, m_capacity; mz_uint m_element_size; } mz_zip_array; struct mz_zip_internal_state_tag { mz_zip_array m_central_dir; mz_zip_array m_central_dir_offsets; mz_zip_array m_sorted_central_dir_offsets; MZ_FILE *m_pFile; void *m_pMem; size_t m_mem_size; size_t m_mem_capacity; }; #define MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(array_ptr, element_size) (array_ptr)->m_element_size = element_size #define MZ_ZIP_ARRAY_ELEMENT(array_ptr, element_type, index) ((element_type *)((array_ptr)->m_p))[index] static MZ_FORCEINLINE void mz_zip_array_clear(mz_zip_archive *pZip, mz_zip_array *pArray) { pZip->m_pFree(pZip->m_pAlloc_opaque, pArray->m_p); memset(pArray, 0, sizeof(mz_zip_array)); } static mz_bool mz_zip_array_ensure_capacity(mz_zip_archive *pZip, mz_zip_array *pArray, size_t min_new_capacity, mz_uint growing) { void *pNew_p; size_t new_capacity = min_new_capacity; MZ_ASSERT(pArray->m_element_size); if (pArray->m_capacity >= min_new_capacity) return MZ_TRUE; if (growing) { new_capacity = MZ_MAX(1, pArray->m_capacity); while (new_capacity < min_new_capacity) new_capacity *= 2; } if (NULL == (pNew_p = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pArray->m_p, pArray->m_element_size, new_capacity))) return MZ_FALSE; pArray->m_p = pNew_p; pArray->m_capacity = new_capacity; return MZ_TRUE; } static MZ_FORCEINLINE mz_bool mz_zip_array_reserve(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_capacity, mz_uint growing) { if (new_capacity > pArray->m_capacity) { if (!mz_zip_array_ensure_capacity(pZip, pArray, new_capacity, growing)) return MZ_FALSE; } return MZ_TRUE; } static MZ_FORCEINLINE mz_bool mz_zip_array_resize(mz_zip_archive *pZip, mz_zip_array *pArray, size_t new_size, mz_uint growing) { if (new_size > pArray->m_capacity) { if (!mz_zip_array_ensure_capacity(pZip, pArray, new_size, growing)) return MZ_FALSE; } pArray->m_size = new_size; return MZ_TRUE; } static MZ_FORCEINLINE mz_bool mz_zip_array_ensure_room(mz_zip_archive *pZip, mz_zip_array *pArray, size_t n) { return mz_zip_array_reserve(pZip, pArray, pArray->m_size + n, MZ_TRUE); } static MZ_FORCEINLINE mz_bool mz_zip_array_push_back(mz_zip_archive *pZip, mz_zip_array *pArray, const void *pElements, size_t n) { size_t orig_size = pArray->m_size; if (!mz_zip_array_resize(pZip, pArray, orig_size + n, MZ_TRUE)) return MZ_FALSE; memcpy((mz_uint8*)pArray->m_p + orig_size * pArray->m_element_size, pElements, n * pArray->m_element_size); return MZ_TRUE; } #ifndef MINIZ_NO_TIME static time_t mz_zip_dos_to_time_t(int dos_time, int dos_date) { struct tm tm; memset(&tm, 0, sizeof(tm)); tm.tm_isdst = -1; tm.tm_year = ((dos_date >> 9) & 127) + 1980 - 1900; tm.tm_mon = ((dos_date >> 5) & 15) - 1; tm.tm_mday = dos_date & 31; tm.tm_hour = (dos_time >> 11) & 31; tm.tm_min = (dos_time >> 5) & 63; tm.tm_sec = (dos_time << 1) & 62; return mktime(&tm); } static void mz_zip_time_to_dos_time(time_t time, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date) { #ifdef _MSC_VER struct tm tm_struct; struct tm *tm = &tm_struct; errno_t err = localtime_s(tm, &time); if (err) { *pDOS_date = 0; *pDOS_time = 0; return; } #else struct tm *tm = localtime(&time); #endif *pDOS_time = (mz_uint16)(((tm->tm_hour) << 11) + ((tm->tm_min) << 5) + ((tm->tm_sec) >> 1)); *pDOS_date = (mz_uint16)(((tm->tm_year + 1900 - 1980) << 9) + ((tm->tm_mon + 1) << 5) + tm->tm_mday); } #endif #ifndef MINIZ_NO_STDIO static mz_bool mz_zip_get_file_modified_time(const char *pFilename, mz_uint16 *pDOS_time, mz_uint16 *pDOS_date) { #ifdef MINIZ_NO_TIME (void)pFilename; *pDOS_date = *pDOS_time = 0; #else struct MZ_FILE_STAT_STRUCT file_stat; if (MZ_FILE_STAT(pFilename, &file_stat) != 0) return MZ_FALSE; mz_zip_time_to_dos_time(file_stat.st_mtime, pDOS_time, pDOS_date); #endif // #ifdef MINIZ_NO_TIME return MZ_TRUE; } static mz_bool mz_zip_set_file_times(const char *pFilename, time_t access_time, time_t modified_time) { #ifndef MINIZ_NO_TIME struct utimbuf t; t.actime = access_time; t.modtime = modified_time; return !utime(pFilename, &t); #else (void)pFilename, (void)access_time, (void)modified_time; return MZ_TRUE; #endif // #ifndef MINIZ_NO_TIME } #endif static mz_bool mz_zip_reader_init_internal(mz_zip_archive *pZip, mz_uint32 flags) { (void)flags; if ((!pZip) || (pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID)) return MZ_FALSE; if (!pZip->m_pAlloc) pZip->m_pAlloc = def_alloc_func; if (!pZip->m_pFree) pZip->m_pFree = def_free_func; if (!pZip->m_pRealloc) pZip->m_pRealloc = def_realloc_func; pZip->m_zip_mode = MZ_ZIP_MODE_READING; pZip->m_archive_size = 0; pZip->m_central_directory_file_ofs = 0; pZip->m_total_files = 0; if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state)))) return MZ_FALSE; memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state)); MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8)); MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32)); MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32)); return MZ_TRUE; } static MZ_FORCEINLINE mz_bool mz_zip_reader_filename_less(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, mz_uint r_index) { const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE; const mz_uint8 *pR = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, r_index)); mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS), r_len = MZ_READ_LE16(pR + MZ_ZIP_CDH_FILENAME_LEN_OFS); mz_uint8 l = 0, r = 0; pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; pR += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; pE = pL + MZ_MIN(l_len, r_len); while (pL < pE) { if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR))) break; pL++; pR++; } return (pL == pE) ? (l_len < r_len) : (l < r); } #define MZ_SWAP_UINT32(a, b) do { mz_uint32 t = a; a = b; b = t; } MZ_MACRO_END // Heap sort of lowercased filenames, used to help accelerate plain central directory searches by mz_zip_reader_locate_file(). (Could also use qsort(), but it could allocate memory.) static void mz_zip_reader_sort_central_dir_offsets_by_filename(mz_zip_archive *pZip) { mz_zip_internal_state *pState = pZip->m_pState; const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets; const mz_zip_array *pCentral_dir = &pState->m_central_dir; mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0); const int size = pZip->m_total_files; int start = (size - 2) >> 1, end; while (start >= 0) { int child, root = start; for (; ;) { if ((child = (root << 1) + 1) >= size) break; child += (((child + 1) < size) && (mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1]))); if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child])) break; MZ_SWAP_UINT32(pIndices[root], pIndices[child]); root = child; } start--; } end = size - 1; while (end > 0) { int child, root = 0; MZ_SWAP_UINT32(pIndices[end], pIndices[0]); for (; ;) { if ((child = (root << 1) + 1) >= end) break; child += (((child + 1) < end) && mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[child], pIndices[child + 1])); if (!mz_zip_reader_filename_less(pCentral_dir, pCentral_dir_offsets, pIndices[root], pIndices[child])) break; MZ_SWAP_UINT32(pIndices[root], pIndices[child]); root = child; } end--; } } static mz_bool mz_zip_reader_read_central_dir(mz_zip_archive *pZip, mz_uint32 flags) { mz_uint cdir_size, num_this_disk, cdir_disk_index; mz_uint64 cdir_ofs; mz_int64 cur_file_ofs; const mz_uint8 *p; mz_uint32 buf_u32[4096 / sizeof(mz_uint32)]; mz_uint8 *pBuf = (mz_uint8 *)buf_u32; // Basic sanity checks - reject files which are too small, and check the first 4 bytes of the file to make sure a local header is there. if (pZip->m_archive_size < MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) return MZ_FALSE; // Find the end of central directory record by scanning the file from the end towards the beginning. cur_file_ofs = MZ_MAX((mz_int64)pZip->m_archive_size - (mz_int64)sizeof(buf_u32), 0); for (; ;) { int i, n = (int)MZ_MIN(sizeof(buf_u32), pZip->m_archive_size - cur_file_ofs); if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, n) != (mz_uint)n) return MZ_FALSE; for (i = n - 4; i >= 0; --i) if (MZ_READ_LE32(pBuf + i) == MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) break; if (i >= 0) { cur_file_ofs += i; break; } if ((!cur_file_ofs) || ((pZip->m_archive_size - cur_file_ofs) >= (0xFFFF + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE))) return MZ_FALSE; cur_file_ofs = MZ_MAX(cur_file_ofs - (sizeof(buf_u32) - 3), 0); } // Read and verify the end of central directory record. if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) return MZ_FALSE; if ((MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_SIG_OFS) != MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG) || ((pZip->m_total_files = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS)) != MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS))) return MZ_FALSE; num_this_disk = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_THIS_DISK_OFS); cdir_disk_index = MZ_READ_LE16(pBuf + MZ_ZIP_ECDH_NUM_DISK_CDIR_OFS); if (((num_this_disk | cdir_disk_index) != 0) && ((num_this_disk != 1) || (cdir_disk_index != 1))) return MZ_FALSE; if ((cdir_size = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_SIZE_OFS)) < pZip->m_total_files * MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) return MZ_FALSE; cdir_ofs = MZ_READ_LE32(pBuf + MZ_ZIP_ECDH_CDIR_OFS_OFS); if ((cdir_ofs + (mz_uint64)cdir_size) > pZip->m_archive_size) return MZ_FALSE; pZip->m_central_directory_file_ofs = cdir_ofs; if (pZip->m_total_files) { mz_uint i, n; // Read the entire central directory into a heap block, and allocate another heap block to hold the unsorted central dir file record offsets, and another to hold the sorted indices. if ((!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir, cdir_size, MZ_FALSE)) || (!mz_zip_array_resize(pZip, &pZip->m_pState->m_central_dir_offsets, pZip->m_total_files, MZ_FALSE)) || (!mz_zip_array_resize(pZip, &pZip->m_pState->m_sorted_central_dir_offsets, pZip->m_total_files, MZ_FALSE))) return MZ_FALSE; if (pZip->m_pRead(pZip->m_pIO_opaque, cdir_ofs, pZip->m_pState->m_central_dir.m_p, cdir_size) != cdir_size) return MZ_FALSE; // Now create an index into the central directory file records, do some basic sanity checking on each record, and check for zip64 entries (which are not yet supported). p = (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p; for (n = cdir_size, i = 0; i < pZip->m_total_files; ++i) { mz_uint total_header_size, comp_size, decomp_size, disk_index; if ((n < MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) || (MZ_READ_LE32(p) != MZ_ZIP_CENTRAL_DIR_HEADER_SIG)) return MZ_FALSE; MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, i) = (mz_uint32)(p - (const mz_uint8 *)pZip->m_pState->m_central_dir.m_p); MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_sorted_central_dir_offsets, mz_uint32, i) = i; comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); decomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); if (((!MZ_READ_LE32(p + MZ_ZIP_CDH_METHOD_OFS)) && (decomp_size != comp_size)) || (decomp_size && !comp_size) || (decomp_size == 0xFFFFFFFF) || (comp_size == 0xFFFFFFFF)) return MZ_FALSE; disk_index = MZ_READ_LE16(p + MZ_ZIP_CDH_DISK_START_OFS); if ((disk_index != num_this_disk) && (disk_index != 1)) return MZ_FALSE; if (((mz_uint64)MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS) + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + comp_size) > pZip->m_archive_size) return MZ_FALSE; if ((total_header_size = MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS)) > n) return MZ_FALSE; n -= total_header_size; p += total_header_size; } } if ((flags & MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY) == 0) mz_zip_reader_sort_central_dir_offsets_by_filename(pZip); return MZ_TRUE; } mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint32 flags) { if ((!pZip) || (!pZip->m_pRead)) return MZ_FALSE; if (!mz_zip_reader_init_internal(pZip, flags)) return MZ_FALSE; pZip->m_archive_size = size; if (!mz_zip_reader_read_central_dir(pZip, flags)) { mz_zip_reader_end(pZip); return MZ_FALSE; } return MZ_TRUE; } static size_t mz_zip_mem_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n) { mz_zip_archive *pZip = (mz_zip_archive *)pOpaque; size_t s = (file_ofs >= pZip->m_archive_size) ? 0 : (size_t)MZ_MIN(pZip->m_archive_size - file_ofs, n); memcpy(pBuf, (const mz_uint8 *)pZip->m_pState->m_pMem + file_ofs, s); return s; } mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint32 flags) { if (!mz_zip_reader_init_internal(pZip, flags)) return MZ_FALSE; pZip->m_archive_size = size; pZip->m_pRead = mz_zip_mem_read_func; pZip->m_pIO_opaque = pZip; pZip->m_pState->m_pMem = (void *)pMem; pZip->m_pState->m_mem_size = size; if (!mz_zip_reader_read_central_dir(pZip, flags)) { mz_zip_reader_end(pZip); return MZ_FALSE; } return MZ_TRUE; } #ifndef MINIZ_NO_STDIO static size_t mz_zip_file_read_func(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n) { mz_zip_archive *pZip = (mz_zip_archive *)pOpaque; mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile); if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET)))) return 0; return MZ_FREAD(pBuf, 1, n, pZip->m_pState->m_pFile); } mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags) { mz_uint64 file_size; MZ_FILE *pFile = MZ_FOPEN(pFilename, "rb"); if (!pFile) return MZ_FALSE; if (MZ_FSEEK64(pFile, 0, SEEK_END)) return MZ_FALSE; file_size = MZ_FTELL64(pFile); if (!mz_zip_reader_init_internal(pZip, flags)) { MZ_FCLOSE(pFile); return MZ_FALSE; } pZip->m_pRead = mz_zip_file_read_func; pZip->m_pIO_opaque = pZip; pZip->m_pState->m_pFile = pFile; pZip->m_archive_size = file_size; if (!mz_zip_reader_read_central_dir(pZip, flags)) { mz_zip_reader_end(pZip); return MZ_FALSE; } return MZ_TRUE; } #endif // #ifndef MINIZ_NO_STDIO mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip) { return pZip ? pZip->m_total_files : 0; } static MZ_FORCEINLINE const mz_uint8 *mz_zip_reader_get_cdh(mz_zip_archive *pZip, mz_uint file_index) { if ((!pZip) || (!pZip->m_pState) || (file_index >= pZip->m_total_files) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) return NULL; return &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index)); } mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index) { mz_uint m_bit_flag; const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index); if (!p) return MZ_FALSE; m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS); return (m_bit_flag & 1); } mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index) { mz_uint filename_len, internal_attr, external_attr; const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index); if (!p) return MZ_FALSE; internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS); external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS); if ((!internal_attr) && ((external_attr & 0x10) != 0)) return MZ_TRUE; filename_len = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); if (filename_len) { if (*(p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_len - 1) == '/') return MZ_TRUE; } return MZ_FALSE; } mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat) { mz_uint n; const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index); if ((!p) || (!pStat)) return MZ_FALSE; // Unpack the central directory record. pStat->m_file_index = file_index; pStat->m_central_dir_ofs = MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index); pStat->m_version_made_by = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_MADE_BY_OFS); pStat->m_version_needed = MZ_READ_LE16(p + MZ_ZIP_CDH_VERSION_NEEDED_OFS); pStat->m_bit_flag = MZ_READ_LE16(p + MZ_ZIP_CDH_BIT_FLAG_OFS); pStat->m_method = MZ_READ_LE16(p + MZ_ZIP_CDH_METHOD_OFS); #ifndef MINIZ_NO_TIME pStat->m_time = mz_zip_dos_to_time_t(MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_TIME_OFS), MZ_READ_LE16(p + MZ_ZIP_CDH_FILE_DATE_OFS)); #endif pStat->m_crc32 = MZ_READ_LE32(p + MZ_ZIP_CDH_CRC32_OFS); pStat->m_comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); pStat->m_uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); pStat->m_internal_attr = MZ_READ_LE16(p + MZ_ZIP_CDH_INTERNAL_ATTR_OFS); pStat->m_external_attr = MZ_READ_LE32(p + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS); pStat->m_local_header_ofs = MZ_READ_LE32(p + MZ_ZIP_CDH_LOCAL_HEADER_OFS); // Copy as much of the filename and comment as possible. n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILENAME_SIZE - 1); memcpy(pStat->m_filename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n); pStat->m_filename[n] = '\0'; n = MZ_READ_LE16(p + MZ_ZIP_CDH_COMMENT_LEN_OFS); n = MZ_MIN(n, MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE - 1); pStat->m_comment_size = n; memcpy(pStat->m_comment, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(p + MZ_ZIP_CDH_EXTRA_LEN_OFS), n); pStat->m_comment[n] = '\0'; return MZ_TRUE; } mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size) { mz_uint n; const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index); if (!p) { if (filename_buf_size) pFilename[0] = '\0'; return 0; } n = MZ_READ_LE16(p + MZ_ZIP_CDH_FILENAME_LEN_OFS); if (filename_buf_size) { n = MZ_MIN(n, filename_buf_size - 1); memcpy(pFilename, p + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n); pFilename[n] = '\0'; } return n + 1; } static MZ_FORCEINLINE mz_bool mz_zip_reader_string_equal(const char *pA, const char *pB, mz_uint len, mz_uint flags) { mz_uint i; if (flags & MZ_ZIP_FLAG_CASE_SENSITIVE) return 0 == memcmp(pA, pB, len); for (i = 0; i < len; ++i) if (MZ_TOLOWER(pA[i]) != MZ_TOLOWER(pB[i])) return MZ_FALSE; return MZ_TRUE; } static MZ_FORCEINLINE int mz_zip_reader_filename_compare(const mz_zip_array *pCentral_dir_array, const mz_zip_array *pCentral_dir_offsets, mz_uint l_index, const char *pR, mz_uint r_len) { const mz_uint8 *pL = &MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_array, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(pCentral_dir_offsets, mz_uint32, l_index)), *pE; mz_uint l_len = MZ_READ_LE16(pL + MZ_ZIP_CDH_FILENAME_LEN_OFS); mz_uint8 l = 0, r = 0; pL += MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; pE = pL + MZ_MIN(l_len, r_len); while (pL < pE) { if ((l = MZ_TOLOWER(*pL)) != (r = MZ_TOLOWER(*pR))) break; pL++; pR++; } return (pL == pE) ? (int)(l_len - r_len) : (l - r); } static int mz_zip_reader_locate_file_binary_search(mz_zip_archive *pZip, const char *pFilename) { mz_zip_internal_state *pState = pZip->m_pState; const mz_zip_array *pCentral_dir_offsets = &pState->m_central_dir_offsets; const mz_zip_array *pCentral_dir = &pState->m_central_dir; mz_uint32 *pIndices = &MZ_ZIP_ARRAY_ELEMENT(&pState->m_sorted_central_dir_offsets, mz_uint32, 0); const int size = pZip->m_total_files; const mz_uint filename_len = (mz_uint)strlen(pFilename); int l = 0, h = size - 1; while (l <= h) { int m = (l + h) >> 1, file_index = pIndices[m], comp = mz_zip_reader_filename_compare(pCentral_dir, pCentral_dir_offsets, file_index, pFilename, filename_len); if (!comp) return file_index; else if (comp < 0) l = m + 1; else h = m - 1; } return -1; } int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags) { mz_uint file_index; size_t name_len, comment_len; if ((!pZip) || (!pZip->m_pState) || (!pName) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) return -1; if (((flags & (MZ_ZIP_FLAG_IGNORE_PATH | MZ_ZIP_FLAG_CASE_SENSITIVE)) == 0) && (!pComment) && (pZip->m_pState->m_sorted_central_dir_offsets.m_p)) return mz_zip_reader_locate_file_binary_search(pZip, pName); name_len = strlen(pName); if (name_len > 0xFFFF) return -1; comment_len = pComment ? strlen(pComment) : 0; if (comment_len > 0xFFFF) return -1; for (file_index = 0; file_index < pZip->m_total_files; file_index++) { const mz_uint8 *pHeader = &MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir, mz_uint8, MZ_ZIP_ARRAY_ELEMENT(&pZip->m_pState->m_central_dir_offsets, mz_uint32, file_index)); mz_uint filename_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_FILENAME_LEN_OFS); const char *pFilename = (const char *)pHeader + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE; if (filename_len < name_len) continue; if (comment_len) { mz_uint file_extra_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_EXTRA_LEN_OFS), file_comment_len = MZ_READ_LE16(pHeader + MZ_ZIP_CDH_COMMENT_LEN_OFS); const char *pFile_comment = pFilename + filename_len + file_extra_len; if ((file_comment_len != comment_len) || (!mz_zip_reader_string_equal(pComment, pFile_comment, file_comment_len, flags))) continue; } if ((flags & MZ_ZIP_FLAG_IGNORE_PATH) && (filename_len)) { int ofs = filename_len - 1; do { if ((pFilename[ofs] == '/') || (pFilename[ofs] == '\\') || (pFilename[ofs] == ':')) break; } while (--ofs >= 0); ofs++; pFilename += ofs; filename_len -= ofs; } if ((filename_len == name_len) && (mz_zip_reader_string_equal(pName, pFilename, filename_len, flags))) return file_index; } return -1; } mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size) { int status = TINFL_STATUS_DONE; mz_uint64 needed_size, cur_file_ofs, comp_remaining, out_buf_ofs = 0, read_buf_size, read_buf_ofs = 0, read_buf_avail; mz_zip_archive_file_stat file_stat; void *pRead_buf; mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32; tinfl_decompressor inflator; if ((buf_size) && (!pBuf)) return MZ_FALSE; if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) return MZ_FALSE; if (!file_stat.m_comp_size) return MZ_TRUE; // Encryption and patch files are not supported. if (file_stat.m_bit_flag & (1 | 32)) return MZ_FALSE; // This function only supports stored and deflate. if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED)) return MZ_FALSE; // Ensure supplied output buffer is large enough. needed_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? file_stat.m_comp_size : file_stat.m_uncomp_size; if (buf_size < needed_size) return MZ_FALSE; // Read and parse the local directory entry. cur_file_ofs = file_stat.m_local_header_ofs; if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) return MZ_FALSE; if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) return MZ_FALSE; cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size) return MZ_FALSE; if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) { // The file is stored or the caller has requested the compressed data. if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pBuf, (size_t)needed_size) != needed_size) return MZ_FALSE; return ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) != 0) || (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) == file_stat.m_crc32); } // Decompress the file either directly from memory or from a file input buffer. tinfl_init(&inflator); if (pZip->m_pState->m_pMem) { // Read directly from the archive in memory. pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs; read_buf_size = read_buf_avail = file_stat.m_comp_size; comp_remaining = 0; } else if (pUser_read_buf) { // Use a user provided read buffer. if (!user_read_buf_size) return MZ_FALSE; pRead_buf = (mz_uint8 *)pUser_read_buf; read_buf_size = user_read_buf_size; read_buf_avail = 0; comp_remaining = file_stat.m_uncomp_size; } else { // Temporarily allocate a read buffer. read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE); #ifdef _MSC_VER if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF)) #else if (((sizeof(size_t) == sizeof(mz_uint32))) && (read_buf_size > 0x7FFFFFFF)) #endif return MZ_FALSE; if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size))) return MZ_FALSE; read_buf_avail = 0; comp_remaining = file_stat.m_comp_size; } do { size_t in_buf_size, out_buf_size = (size_t)(file_stat.m_uncomp_size - out_buf_ofs); if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) { read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) { status = TINFL_STATUS_FAILED; break; } cur_file_ofs += read_buf_avail; comp_remaining -= read_buf_avail; read_buf_ofs = 0; } in_buf_size = (size_t)read_buf_avail; status = tinfl_decompress(&inflator, (mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pBuf, (mz_uint8 *)pBuf + out_buf_ofs, &out_buf_size, TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF | (comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0)); read_buf_avail -= in_buf_size; read_buf_ofs += in_buf_size; out_buf_ofs += out_buf_size; } while (status == TINFL_STATUS_NEEDS_MORE_INPUT); if (status == TINFL_STATUS_DONE) { // Make sure the entire file was decompressed, and check its CRC. if ((out_buf_ofs != file_stat.m_uncomp_size) || (mz_crc32(MZ_CRC32_INIT, (const mz_uint8 *)pBuf, (size_t)file_stat.m_uncomp_size) != file_stat.m_crc32)) status = TINFL_STATUS_FAILED; } if ((!pZip->m_pState->m_pMem) && (!pUser_read_buf)) pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); return status == TINFL_STATUS_DONE; } mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size) { int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags); if (file_index < 0) return MZ_FALSE; return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, pUser_read_buf, user_read_buf_size); } mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags) { return mz_zip_reader_extract_to_mem_no_alloc(pZip, file_index, pBuf, buf_size, flags, NULL, 0); } mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags) { return mz_zip_reader_extract_file_to_mem_no_alloc(pZip, pFilename, pBuf, buf_size, flags, NULL, 0); } void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags) { mz_uint64 comp_size, uncomp_size, alloc_size; const mz_uint8 *p = mz_zip_reader_get_cdh(pZip, file_index); void *pBuf; if (pSize) *pSize = 0; if (!p) return NULL; comp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); uncomp_size = MZ_READ_LE32(p + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS); alloc_size = (flags & MZ_ZIP_FLAG_COMPRESSED_DATA) ? comp_size : uncomp_size; #ifdef _MSC_VER if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF)) #else if (((sizeof(size_t) == sizeof(mz_uint32))) && (alloc_size > 0x7FFFFFFF)) #endif return NULL; if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)alloc_size))) return NULL; if (!mz_zip_reader_extract_to_mem(pZip, file_index, pBuf, (size_t)alloc_size, flags)) { pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); return NULL; } if (pSize) *pSize = (size_t)alloc_size; return pBuf; } void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags) { int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags); if (file_index < 0) { if (pSize) *pSize = 0; return MZ_FALSE; } return mz_zip_reader_extract_to_heap(pZip, file_index, pSize, flags); } mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags) { int status = TINFL_STATUS_DONE; mz_uint file_crc32 = MZ_CRC32_INIT; mz_uint64 read_buf_size, read_buf_ofs = 0, read_buf_avail, comp_remaining, out_buf_ofs = 0, cur_file_ofs; mz_zip_archive_file_stat file_stat; void *pRead_buf = NULL; void *pWrite_buf = NULL; mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32; if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) return MZ_FALSE; if (!file_stat.m_comp_size) return MZ_TRUE; // Encryption and patch files are not supported. if (file_stat.m_bit_flag & (1 | 32)) return MZ_FALSE; // This function only supports stored and deflate. if ((!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (file_stat.m_method != 0) && (file_stat.m_method != MZ_DEFLATED)) return MZ_FALSE; // Read and parse the local directory entry. cur_file_ofs = file_stat.m_local_header_ofs; if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) return MZ_FALSE; if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) return MZ_FALSE; cur_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); if ((cur_file_ofs + file_stat.m_comp_size) > pZip->m_archive_size) return MZ_FALSE; // Decompress the file either directly from memory or from a file input buffer. if (pZip->m_pState->m_pMem) { pRead_buf = (mz_uint8 *)pZip->m_pState->m_pMem + cur_file_ofs; read_buf_size = read_buf_avail = file_stat.m_comp_size; comp_remaining = 0; } else { read_buf_size = MZ_MIN(file_stat.m_comp_size, MZ_ZIP_MAX_IO_BUF_SIZE); if (NULL == (pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)read_buf_size))) return MZ_FALSE; read_buf_avail = 0; comp_remaining = file_stat.m_comp_size; } if ((flags & MZ_ZIP_FLAG_COMPRESSED_DATA) || (!file_stat.m_method)) { // The file is stored or the caller has requested the compressed data. if (pZip->m_pState->m_pMem) { #ifdef _MSC_VER if (((0, sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > 0xFFFFFFFF)) #else if (((sizeof(size_t) == sizeof(mz_uint32))) && (file_stat.m_comp_size > 0xFFFFFFFF)) #endif return MZ_FALSE; if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)file_stat.m_comp_size) != file_stat.m_comp_size) status = TINFL_STATUS_FAILED; else if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)file_stat.m_comp_size); cur_file_ofs += file_stat.m_comp_size; out_buf_ofs += file_stat.m_comp_size; comp_remaining = 0; } else { while (comp_remaining) { read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) { status = TINFL_STATUS_FAILED; break; } if (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) file_crc32 = (mz_uint32)mz_crc32(file_crc32, (const mz_uint8 *)pRead_buf, (size_t)read_buf_avail); if (pCallback(pOpaque, out_buf_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) { status = TINFL_STATUS_FAILED; break; } cur_file_ofs += read_buf_avail; out_buf_ofs += read_buf_avail; comp_remaining -= read_buf_avail; } } } else { tinfl_decompressor inflator; tinfl_init(&inflator); if (NULL == (pWrite_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, TINFL_LZ_DICT_SIZE))) status = TINFL_STATUS_FAILED; else { do { mz_uint8 *pWrite_buf_cur = (mz_uint8 *)pWrite_buf + (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1)); size_t in_buf_size, out_buf_size = TINFL_LZ_DICT_SIZE - (out_buf_ofs & (TINFL_LZ_DICT_SIZE - 1)); if ((!read_buf_avail) && (!pZip->m_pState->m_pMem)) { read_buf_avail = MZ_MIN(read_buf_size, comp_remaining); if (pZip->m_pRead(pZip->m_pIO_opaque, cur_file_ofs, pRead_buf, (size_t)read_buf_avail) != read_buf_avail) { status = TINFL_STATUS_FAILED; break; } cur_file_ofs += read_buf_avail; comp_remaining -= read_buf_avail; read_buf_ofs = 0; } in_buf_size = (size_t)read_buf_avail; status = tinfl_decompress(&inflator, (const mz_uint8 *)pRead_buf + read_buf_ofs, &in_buf_size, (mz_uint8 *)pWrite_buf, pWrite_buf_cur, &out_buf_size, comp_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0); read_buf_avail -= in_buf_size; read_buf_ofs += in_buf_size; if (out_buf_size) { if (pCallback(pOpaque, out_buf_ofs, pWrite_buf_cur, out_buf_size) != out_buf_size) { status = TINFL_STATUS_FAILED; break; } file_crc32 = (mz_uint32)mz_crc32(file_crc32, pWrite_buf_cur, out_buf_size); if ((out_buf_ofs += out_buf_size) > file_stat.m_uncomp_size) { status = TINFL_STATUS_FAILED; break; } } } while ((status == TINFL_STATUS_NEEDS_MORE_INPUT) || (status == TINFL_STATUS_HAS_MORE_OUTPUT)); } } if ((status == TINFL_STATUS_DONE) && (!(flags & MZ_ZIP_FLAG_COMPRESSED_DATA))) { // Make sure the entire file was decompressed, and check its CRC. if ((out_buf_ofs != file_stat.m_uncomp_size) || (file_crc32 != file_stat.m_crc32)) status = TINFL_STATUS_FAILED; } if (!pZip->m_pState->m_pMem) pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); if (pWrite_buf) pZip->m_pFree(pZip->m_pAlloc_opaque, pWrite_buf); return status == TINFL_STATUS_DONE; } mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags) { int file_index = mz_zip_reader_locate_file(pZip, pFilename, NULL, flags); if (file_index < 0) return MZ_FALSE; return mz_zip_reader_extract_to_callback(pZip, file_index, pCallback, pOpaque, flags); } #ifndef MINIZ_NO_STDIO static size_t mz_zip_file_write_callback(void *pOpaque, mz_uint64 ofs, const void *pBuf, size_t n) { (void)ofs; return MZ_FWRITE(pBuf, 1, n, (MZ_FILE*)pOpaque); } mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags) { mz_bool status; mz_zip_archive_file_stat file_stat; MZ_FILE *pFile; if (!mz_zip_reader_file_stat(pZip, file_index, &file_stat)) return MZ_FALSE; pFile = MZ_FOPEN(pDst_filename, "wb"); if (!pFile) return MZ_FALSE; status = mz_zip_reader_extract_to_callback(pZip, file_index, mz_zip_file_write_callback, pFile, flags); if (MZ_FCLOSE(pFile) == EOF) return MZ_FALSE; #ifndef MINIZ_NO_TIME if (status) mz_zip_set_file_times(pDst_filename, file_stat.m_time, file_stat.m_time); #endif return status; } #endif // #ifndef MINIZ_NO_STDIO mz_bool mz_zip_reader_end(mz_zip_archive *pZip) { if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) return MZ_FALSE; if (pZip->m_pState) { mz_zip_internal_state *pState = pZip->m_pState; pZip->m_pState = NULL; mz_zip_array_clear(pZip, &pState->m_central_dir); mz_zip_array_clear(pZip, &pState->m_central_dir_offsets); mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets); #ifndef MINIZ_NO_STDIO if (pState->m_pFile) { MZ_FCLOSE(pState->m_pFile); pState->m_pFile = NULL; } #endif // #ifndef MINIZ_NO_STDIO pZip->m_pFree(pZip->m_pAlloc_opaque, pState); } pZip->m_zip_mode = MZ_ZIP_MODE_INVALID; return MZ_TRUE; } #ifndef MINIZ_NO_STDIO mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags) { int file_index = mz_zip_reader_locate_file(pZip, pArchive_filename, NULL, flags); if (file_index < 0) return MZ_FALSE; return mz_zip_reader_extract_to_file(pZip, file_index, pDst_filename, flags); } #endif // ------------------- .ZIP archive writing #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS static void mz_write_le16(mz_uint8 *p, mz_uint16 v) { p[0] = (mz_uint8)v; p[1] = (mz_uint8)(v >> 8); } static void mz_write_le32(mz_uint8 *p, mz_uint32 v) { p[0] = (mz_uint8)v; p[1] = (mz_uint8)(v >> 8); p[2] = (mz_uint8)(v >> 16); p[3] = (mz_uint8)(v >> 24); } #define MZ_WRITE_LE16(p, v) mz_write_le16((mz_uint8 *)(p), (mz_uint16)(v)) #define MZ_WRITE_LE32(p, v) mz_write_le32((mz_uint8 *)(p), (mz_uint32)(v)) mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size) { if ((!pZip) || (pZip->m_pState) || (!pZip->m_pWrite) || (pZip->m_zip_mode != MZ_ZIP_MODE_INVALID)) return MZ_FALSE; if (pZip->m_file_offset_alignment) { // Ensure user specified file offset alignment is a power of 2. if (pZip->m_file_offset_alignment & (pZip->m_file_offset_alignment - 1)) return MZ_FALSE; } if (!pZip->m_pAlloc) pZip->m_pAlloc = def_alloc_func; if (!pZip->m_pFree) pZip->m_pFree = def_free_func; if (!pZip->m_pRealloc) pZip->m_pRealloc = def_realloc_func; pZip->m_zip_mode = MZ_ZIP_MODE_WRITING; pZip->m_archive_size = existing_size; pZip->m_central_directory_file_ofs = 0; pZip->m_total_files = 0; if (NULL == (pZip->m_pState = (mz_zip_internal_state *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(mz_zip_internal_state)))) return MZ_FALSE; memset(pZip->m_pState, 0, sizeof(mz_zip_internal_state)); MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir, sizeof(mz_uint8)); MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_central_dir_offsets, sizeof(mz_uint32)); MZ_ZIP_ARRAY_SET_ELEMENT_SIZE(&pZip->m_pState->m_sorted_central_dir_offsets, sizeof(mz_uint32)); return MZ_TRUE; } static size_t mz_zip_heap_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n) { mz_zip_archive *pZip = (mz_zip_archive *)pOpaque; mz_zip_internal_state *pState = pZip->m_pState; mz_uint64 new_size = MZ_MAX(file_ofs + n, pState->m_mem_size); #ifdef _MSC_VER if ((!n) || ((0, sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF))) #else if ((!n) || ((sizeof(size_t) == sizeof(mz_uint32)) && (new_size > 0x7FFFFFFF))) #endif return 0; if (new_size > pState->m_mem_capacity) { void *pNew_block; size_t new_capacity = MZ_MAX(64, pState->m_mem_capacity); while (new_capacity < new_size) new_capacity *= 2; if (NULL == (pNew_block = pZip->m_pRealloc(pZip->m_pAlloc_opaque, pState->m_pMem, 1, new_capacity))) return 0; pState->m_pMem = pNew_block; pState->m_mem_capacity = new_capacity; } memcpy((mz_uint8 *)pState->m_pMem + file_ofs, pBuf, n); pState->m_mem_size = (size_t)new_size; return n; } mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size) { pZip->m_pWrite = mz_zip_heap_write_func; pZip->m_pIO_opaque = pZip; if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning)) return MZ_FALSE; if (0 != (initial_allocation_size = MZ_MAX(initial_allocation_size, size_to_reserve_at_beginning))) { if (NULL == (pZip->m_pState->m_pMem = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, initial_allocation_size))) { mz_zip_writer_end(pZip); return MZ_FALSE; } pZip->m_pState->m_mem_capacity = initial_allocation_size; } return MZ_TRUE; } #ifndef MINIZ_NO_STDIO static size_t mz_zip_file_write_func(void *pOpaque, mz_uint64 file_ofs, const void *pBuf, size_t n) { mz_zip_archive *pZip = (mz_zip_archive *)pOpaque; mz_int64 cur_ofs = MZ_FTELL64(pZip->m_pState->m_pFile); if (((mz_int64)file_ofs < 0) || (((cur_ofs != (mz_int64)file_ofs)) && (MZ_FSEEK64(pZip->m_pState->m_pFile, (mz_int64)file_ofs, SEEK_SET)))) return 0; return MZ_FWRITE(pBuf, 1, n, pZip->m_pState->m_pFile); } mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning) { MZ_FILE *pFile; pZip->m_pWrite = mz_zip_file_write_func; pZip->m_pIO_opaque = pZip; if (!mz_zip_writer_init(pZip, size_to_reserve_at_beginning)) return MZ_FALSE; if (NULL == (pFile = MZ_FOPEN(pFilename, "wb"))) { mz_zip_writer_end(pZip); return MZ_FALSE; } pZip->m_pState->m_pFile = pFile; if (size_to_reserve_at_beginning) { mz_uint64 cur_ofs = 0; char buf[4096]; MZ_CLEAR_OBJ(buf); do { size_t n = (size_t)MZ_MIN(sizeof(buf), size_to_reserve_at_beginning); if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_ofs, buf, n) != n) { mz_zip_writer_end(pZip); return MZ_FALSE; } cur_ofs += n; size_to_reserve_at_beginning -= n; } while (size_to_reserve_at_beginning); } return MZ_TRUE; } #endif // #ifndef MINIZ_NO_STDIO mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename) { mz_zip_internal_state *pState; if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_READING)) return MZ_FALSE; // No sense in trying to write to an archive that's already at the support max size if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + MZ_ZIP_LOCAL_DIR_HEADER_SIZE) > 0xFFFFFFFF)) return MZ_FALSE; pState = pZip->m_pState; if (pState->m_pFile) { #ifdef MINIZ_NO_STDIO pFilename; return MZ_FALSE; #else // Archive is being read from stdio - try to reopen as writable. if (pZip->m_pIO_opaque != pZip) return MZ_FALSE; if (!pFilename) return MZ_FALSE; pZip->m_pWrite = mz_zip_file_write_func; if (NULL == (pState->m_pFile = MZ_FREOPEN(pFilename, "r+b", pState->m_pFile))) { // The mz_zip_archive is now in a bogus state because pState->m_pFile is NULL, so just close it. mz_zip_reader_end(pZip); return MZ_FALSE; } #endif // #ifdef MINIZ_NO_STDIO } else if (pState->m_pMem) { // Archive lives in a memory block. Assume it's from the heap that we can resize using the realloc callback. if (pZip->m_pIO_opaque != pZip) return MZ_FALSE; pState->m_mem_capacity = pState->m_mem_size; pZip->m_pWrite = mz_zip_heap_write_func; } // Archive is being read via a user provided read function - make sure the user has specified a write function too. else if (!pZip->m_pWrite) return MZ_FALSE; // Start writing new files at the archive's current central directory location. pZip->m_archive_size = pZip->m_central_directory_file_ofs; pZip->m_zip_mode = MZ_ZIP_MODE_WRITING; pZip->m_central_directory_file_ofs = 0; return MZ_TRUE; } mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags) { return mz_zip_writer_add_mem_ex(pZip, pArchive_name, pBuf, buf_size, NULL, 0, level_and_flags, 0, 0); } typedef struct { mz_zip_archive *m_pZip; mz_uint64 m_cur_archive_file_ofs; mz_uint64 m_comp_size; } mz_zip_writer_add_state; static mz_bool mz_zip_writer_add_put_buf_callback(const void* pBuf, int len, void *pUser) { mz_zip_writer_add_state *pState = (mz_zip_writer_add_state *)pUser; if ((int)pState->m_pZip->m_pWrite(pState->m_pZip->m_pIO_opaque, pState->m_cur_archive_file_ofs, pBuf, len) != len) return MZ_FALSE; pState->m_cur_archive_file_ofs += len; pState->m_comp_size += len; return MZ_TRUE; } static mz_bool mz_zip_writer_create_local_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date) { (void)pZip; memset(pDst, 0, MZ_ZIP_LOCAL_DIR_HEADER_SIZE); MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_SIG_OFS, MZ_ZIP_LOCAL_DIR_HEADER_SIG); MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_VERSION_NEEDED_OFS, method ? 20 : 0); MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_BIT_FLAG_OFS, bit_flags); MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_METHOD_OFS, method); MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_TIME_OFS, dos_time); MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILE_DATE_OFS, dos_date); MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_CRC32_OFS, uncomp_crc32); MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_COMPRESSED_SIZE_OFS, comp_size); MZ_WRITE_LE32(pDst + MZ_ZIP_LDH_DECOMPRESSED_SIZE_OFS, uncomp_size); MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_FILENAME_LEN_OFS, filename_size); MZ_WRITE_LE16(pDst + MZ_ZIP_LDH_EXTRA_LEN_OFS, extra_size); return MZ_TRUE; } static mz_bool mz_zip_writer_create_central_dir_header(mz_zip_archive *pZip, mz_uint8 *pDst, mz_uint16 filename_size, mz_uint16 extra_size, mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs, mz_uint32 ext_attributes) { (void)pZip; memset(pDst, 0, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE); MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_SIG_OFS, MZ_ZIP_CENTRAL_DIR_HEADER_SIG); MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_VERSION_NEEDED_OFS, method ? 20 : 0); MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_BIT_FLAG_OFS, bit_flags); MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_METHOD_OFS, method); MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_TIME_OFS, dos_time); MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILE_DATE_OFS, dos_date); MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_CRC32_OFS, uncomp_crc32); MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS, comp_size); MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_DECOMPRESSED_SIZE_OFS, uncomp_size); MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_FILENAME_LEN_OFS, filename_size); MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_EXTRA_LEN_OFS, extra_size); MZ_WRITE_LE16(pDst + MZ_ZIP_CDH_COMMENT_LEN_OFS, comment_size); MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_EXTERNAL_ATTR_OFS, ext_attributes); MZ_WRITE_LE32(pDst + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_header_ofs); return MZ_TRUE; } static mz_bool mz_zip_writer_add_to_central_dir(mz_zip_archive *pZip, const char *pFilename, mz_uint16 filename_size, const void *pExtra, mz_uint16 extra_size, const void *pComment, mz_uint16 comment_size, mz_uint64 uncomp_size, mz_uint64 comp_size, mz_uint32 uncomp_crc32, mz_uint16 method, mz_uint16 bit_flags, mz_uint16 dos_time, mz_uint16 dos_date, mz_uint64 local_header_ofs, mz_uint32 ext_attributes) { mz_zip_internal_state *pState = pZip->m_pState; mz_uint32 central_dir_ofs = (mz_uint32)pState->m_central_dir.m_size; size_t orig_central_dir_size = pState->m_central_dir.m_size; mz_uint8 central_dir_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE]; // No zip64 support yet if ((local_header_ofs > 0xFFFFFFFF) || (((mz_uint64)pState->m_central_dir.m_size + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + filename_size + extra_size + comment_size) > 0xFFFFFFFF)) return MZ_FALSE; if (!mz_zip_writer_create_central_dir_header(pZip, central_dir_header, filename_size, extra_size, comment_size, uncomp_size, comp_size, uncomp_crc32, method, bit_flags, dos_time, dos_date, local_header_ofs, ext_attributes)) return MZ_FALSE; if ((!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_dir_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) || (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pFilename, filename_size)) || (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pExtra, extra_size)) || (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pComment, comment_size)) || (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, ¢ral_dir_ofs, 1))) { // Try to push the central directory array back into its original state. mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); return MZ_FALSE; } return MZ_TRUE; } static mz_bool mz_zip_writer_validate_archive_name(const char *pArchive_name) { // Basic ZIP archive filename validity checks: Valid filenames cannot start with a forward slash, cannot contain a drive letter, and cannot use DOS-style backward slashes. if (*pArchive_name == '/') return MZ_FALSE; while (*pArchive_name) { if ((*pArchive_name == '\\') || (*pArchive_name == ':')) return MZ_FALSE; pArchive_name++; } return MZ_TRUE; } static mz_uint mz_zip_writer_compute_padding_needed_for_file_alignment(mz_zip_archive *pZip) { mz_uint32 n; if (!pZip->m_file_offset_alignment) return 0; n = (mz_uint32)(pZip->m_archive_size & (pZip->m_file_offset_alignment - 1)); return (pZip->m_file_offset_alignment - n) & (pZip->m_file_offset_alignment - 1); } static mz_bool mz_zip_writer_write_zeros(mz_zip_archive *pZip, mz_uint64 cur_file_ofs, mz_uint32 n) { char buf[4096]; memset(buf, 0, MZ_MIN(sizeof(buf), n)); while (n) { mz_uint32 s = MZ_MIN(sizeof(buf), n); if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_file_ofs, buf, s) != s) return MZ_FALSE; cur_file_ofs += s; n -= s; } return MZ_TRUE; } mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_uint64 uncomp_size, mz_uint32 uncomp_crc32) { mz_uint16 method = 0, dos_time = 0, dos_date = 0; mz_uint level, ext_attributes = 0, num_alignment_padding_bytes; mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, comp_size = 0; size_t archive_name_size; mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE]; tdefl_compressor *pComp = NULL; mz_bool store_data_uncompressed; mz_zip_internal_state *pState; if ((int)level_and_flags < 0) level_and_flags = MZ_DEFAULT_LEVEL; level = level_and_flags & 0xF; store_data_uncompressed = ((!level) || (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)); if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || ((buf_size) && (!pBuf)) || (!pArchive_name) || ((comment_size) && (!pComment)) || (pZip->m_total_files == 0xFFFF) || (level > MZ_UBER_COMPRESSION)) return MZ_FALSE; pState = pZip->m_pState; if ((!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) && (uncomp_size)) return MZ_FALSE; // No zip64 support yet if ((buf_size > 0xFFFFFFFF) || (uncomp_size > 0xFFFFFFFF)) return MZ_FALSE; if (!mz_zip_writer_validate_archive_name(pArchive_name)) return MZ_FALSE; #ifndef MINIZ_NO_TIME { time_t cur_time; time(&cur_time); mz_zip_time_to_dos_time(cur_time, &dos_time, &dos_date); } #endif // #ifndef MINIZ_NO_TIME archive_name_size = strlen(pArchive_name); if (archive_name_size > 0xFFFF) return MZ_FALSE; num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); // no zip64 support yet if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + comment_size + archive_name_size) > 0xFFFFFFFF)) return MZ_FALSE; if ((archive_name_size) && (pArchive_name[archive_name_size - 1] == '/')) { // Set DOS Subdirectory attribute bit. ext_attributes |= 0x10; // Subdirectories cannot contain data. if ((buf_size) || (uncomp_size)) return MZ_FALSE; } // Try to do any allocations before writing to the archive, so if an allocation fails the file remains unmodified. (A good idea if we're doing an in-place modification.) if ((!mz_zip_array_ensure_room(pZip, &pState->m_central_dir, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + archive_name_size + comment_size)) || (!mz_zip_array_ensure_room(pZip, &pState->m_central_dir_offsets, 1))) return MZ_FALSE; if ((!store_data_uncompressed) && (buf_size)) { if (NULL == (pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor)))) return MZ_FALSE; } if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes + sizeof(local_dir_header))) { pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); return MZ_FALSE; } local_dir_header_ofs += num_alignment_padding_bytes; if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); } cur_archive_file_ofs += num_alignment_padding_bytes + sizeof(local_dir_header); MZ_CLEAR_OBJ(local_dir_header); if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size) { pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); return MZ_FALSE; } cur_archive_file_ofs += archive_name_size; if (!(level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA)) { uncomp_crc32 = (mz_uint32)mz_crc32(MZ_CRC32_INIT, (const mz_uint8*)pBuf, buf_size); uncomp_size = buf_size; if (uncomp_size <= 3) { level = 0; store_data_uncompressed = MZ_TRUE; } } if (store_data_uncompressed) { if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pBuf, buf_size) != buf_size) { pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); return MZ_FALSE; } cur_archive_file_ofs += buf_size; comp_size = buf_size; if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA) method = MZ_DEFLATED; } else if (buf_size) { mz_zip_writer_add_state state; state.m_pZip = pZip; state.m_cur_archive_file_ofs = cur_archive_file_ofs; state.m_comp_size = 0; if ((tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) || (tdefl_compress_buffer(pComp, pBuf, buf_size, TDEFL_FINISH) != TDEFL_STATUS_DONE)) { pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); return MZ_FALSE; } comp_size = state.m_comp_size; cur_archive_file_ofs = state.m_cur_archive_file_ofs; method = MZ_DEFLATED; } pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); pComp = NULL; // no zip64 support yet if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF)) return MZ_FALSE; if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date)) return MZ_FALSE; if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) return MZ_FALSE; if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment, comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date, local_dir_header_ofs, ext_attributes)) return MZ_FALSE; pZip->m_total_files++; pZip->m_archive_size = cur_archive_file_ofs; return MZ_TRUE; } #ifndef MINIZ_NO_STDIO mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags) { mz_uint uncomp_crc32 = MZ_CRC32_INIT, level, num_alignment_padding_bytes; mz_uint16 method = 0, dos_time = 0, dos_date = 0, ext_attributes = 0; mz_uint64 local_dir_header_ofs = pZip->m_archive_size, cur_archive_file_ofs = pZip->m_archive_size, uncomp_size = 0, comp_size = 0; size_t archive_name_size; mz_uint8 local_dir_header[MZ_ZIP_LOCAL_DIR_HEADER_SIZE]; MZ_FILE *pSrc_file = NULL; if ((int)level_and_flags < 0) level_and_flags = MZ_DEFAULT_LEVEL; level = level_and_flags & 0xF; if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) || (!pArchive_name) || ((comment_size) && (!pComment)) || (level > MZ_UBER_COMPRESSION)) return MZ_FALSE; if (level_and_flags & MZ_ZIP_FLAG_COMPRESSED_DATA) return MZ_FALSE; if (!mz_zip_writer_validate_archive_name(pArchive_name)) return MZ_FALSE; archive_name_size = strlen(pArchive_name); if (archive_name_size > 0xFFFF) return MZ_FALSE; num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); // no zip64 support yet if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE + comment_size + archive_name_size) > 0xFFFFFFFF)) return MZ_FALSE; if (!mz_zip_get_file_modified_time(pSrc_filename, &dos_time, &dos_date)) return MZ_FALSE; pSrc_file = MZ_FOPEN(pSrc_filename, "rb"); if (!pSrc_file) return MZ_FALSE; MZ_FSEEK64(pSrc_file, 0, SEEK_END); uncomp_size = MZ_FTELL64(pSrc_file); MZ_FSEEK64(pSrc_file, 0, SEEK_SET); if (uncomp_size > 0xFFFFFFFF) { // No zip64 support yet MZ_FCLOSE(pSrc_file); return MZ_FALSE; } if (uncomp_size <= 3) level = 0; if (!mz_zip_writer_write_zeros(pZip, cur_archive_file_ofs, num_alignment_padding_bytes + sizeof(local_dir_header))) return MZ_FALSE; local_dir_header_ofs += num_alignment_padding_bytes; if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); } cur_archive_file_ofs += num_alignment_padding_bytes + sizeof(local_dir_header); MZ_CLEAR_OBJ(local_dir_header); if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pArchive_name, archive_name_size) != archive_name_size) { MZ_FCLOSE(pSrc_file); return MZ_FALSE; } cur_archive_file_ofs += archive_name_size; if (uncomp_size) { mz_uint64 uncomp_remaining = uncomp_size; void *pRead_buf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, MZ_ZIP_MAX_IO_BUF_SIZE); if (!pRead_buf) { MZ_FCLOSE(pSrc_file); return MZ_FALSE; } if (!level) { while (uncomp_remaining) { mz_uint n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, uncomp_remaining); if ((MZ_FREAD(pRead_buf, 1, n, pSrc_file) != n) || (pZip->m_pWrite(pZip->m_pIO_opaque, cur_archive_file_ofs, pRead_buf, n) != n)) { pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); MZ_FCLOSE(pSrc_file); return MZ_FALSE; } uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, n); uncomp_remaining -= n; cur_archive_file_ofs += n; } comp_size = uncomp_size; } else { mz_bool result = MZ_FALSE; mz_zip_writer_add_state state; tdefl_compressor *pComp = (tdefl_compressor *)pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, sizeof(tdefl_compressor)); if (!pComp) { pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); MZ_FCLOSE(pSrc_file); return MZ_FALSE; } state.m_pZip = pZip; state.m_cur_archive_file_ofs = cur_archive_file_ofs; state.m_comp_size = 0; if (tdefl_init(pComp, mz_zip_writer_add_put_buf_callback, &state, tdefl_create_comp_flags_from_zip_params(level, -15, MZ_DEFAULT_STRATEGY)) != TDEFL_STATUS_OKAY) { pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); MZ_FCLOSE(pSrc_file); return MZ_FALSE; } for (; ;) { size_t in_buf_size = (mz_uint32)MZ_MIN(uncomp_remaining, MZ_ZIP_MAX_IO_BUF_SIZE); tdefl_status status; if (MZ_FREAD(pRead_buf, 1, in_buf_size, pSrc_file) != in_buf_size) break; uncomp_crc32 = (mz_uint32)mz_crc32(uncomp_crc32, (const mz_uint8 *)pRead_buf, in_buf_size); uncomp_remaining -= in_buf_size; status = tdefl_compress_buffer(pComp, pRead_buf, in_buf_size, uncomp_remaining ? TDEFL_NO_FLUSH : TDEFL_FINISH); if (status == TDEFL_STATUS_DONE) { result = MZ_TRUE; break; } else if (status != TDEFL_STATUS_OKAY) break; } pZip->m_pFree(pZip->m_pAlloc_opaque, pComp); if (!result) { pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); MZ_FCLOSE(pSrc_file); return MZ_FALSE; } comp_size = state.m_comp_size; cur_archive_file_ofs = state.m_cur_archive_file_ofs; method = MZ_DEFLATED; } pZip->m_pFree(pZip->m_pAlloc_opaque, pRead_buf); } MZ_FCLOSE(pSrc_file); pSrc_file = NULL; // no zip64 support yet if ((comp_size > 0xFFFFFFFF) || (cur_archive_file_ofs > 0xFFFFFFFF)) return MZ_FALSE; if (!mz_zip_writer_create_local_dir_header(pZip, local_dir_header, (mz_uint16)archive_name_size, 0, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date)) return MZ_FALSE; if (pZip->m_pWrite(pZip->m_pIO_opaque, local_dir_header_ofs, local_dir_header, sizeof(local_dir_header)) != sizeof(local_dir_header)) return MZ_FALSE; if (!mz_zip_writer_add_to_central_dir(pZip, pArchive_name, (mz_uint16)archive_name_size, NULL, 0, pComment, comment_size, uncomp_size, comp_size, uncomp_crc32, method, 0, dos_time, dos_date, local_dir_header_ofs, ext_attributes)) return MZ_FALSE; pZip->m_total_files++; pZip->m_archive_size = cur_archive_file_ofs; return MZ_TRUE; } #endif // #ifndef MINIZ_NO_STDIO mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint file_index) { mz_uint n, bit_flags, num_alignment_padding_bytes; mz_uint64 comp_bytes_remaining, local_dir_header_ofs; mz_uint64 cur_src_file_ofs, cur_dst_file_ofs; mz_uint32 local_header_u32[(MZ_ZIP_LOCAL_DIR_HEADER_SIZE + sizeof(mz_uint32) - 1) / sizeof(mz_uint32)]; mz_uint8 *pLocal_header = (mz_uint8 *)local_header_u32; mz_uint8 central_header[MZ_ZIP_CENTRAL_DIR_HEADER_SIZE]; size_t orig_central_dir_size; mz_zip_internal_state *pState; void *pBuf; const mz_uint8 *pSrc_central_header; if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING)) return MZ_FALSE; if (NULL == (pSrc_central_header = mz_zip_reader_get_cdh(pSource_zip, file_index))) return MZ_FALSE; pState = pZip->m_pState; num_alignment_padding_bytes = mz_zip_writer_compute_padding_needed_for_file_alignment(pZip); // no zip64 support yet if ((pZip->m_total_files == 0xFFFF) || ((pZip->m_archive_size + num_alignment_padding_bytes + MZ_ZIP_LOCAL_DIR_HEADER_SIZE + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF)) return MZ_FALSE; cur_src_file_ofs = MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS); cur_dst_file_ofs = pZip->m_archive_size; if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) return MZ_FALSE; if (MZ_READ_LE32(pLocal_header) != MZ_ZIP_LOCAL_DIR_HEADER_SIG) return MZ_FALSE; cur_src_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE; if (!mz_zip_writer_write_zeros(pZip, cur_dst_file_ofs, num_alignment_padding_bytes)) return MZ_FALSE; cur_dst_file_ofs += num_alignment_padding_bytes; local_dir_header_ofs = cur_dst_file_ofs; if (pZip->m_file_offset_alignment) { MZ_ASSERT((local_dir_header_ofs & (pZip->m_file_offset_alignment - 1)) == 0); } if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pLocal_header, MZ_ZIP_LOCAL_DIR_HEADER_SIZE) != MZ_ZIP_LOCAL_DIR_HEADER_SIZE) return MZ_FALSE; cur_dst_file_ofs += MZ_ZIP_LOCAL_DIR_HEADER_SIZE; n = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_EXTRA_LEN_OFS); comp_bytes_remaining = n + MZ_READ_LE32(pSrc_central_header + MZ_ZIP_CDH_COMPRESSED_SIZE_OFS); if (NULL == (pBuf = pZip->m_pAlloc(pZip->m_pAlloc_opaque, 1, (size_t)MZ_MAX(sizeof(mz_uint32) * 4, MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining))))) return MZ_FALSE; while (comp_bytes_remaining) { n = (mz_uint)MZ_MIN(MZ_ZIP_MAX_IO_BUF_SIZE, comp_bytes_remaining); if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, n) != n) { pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); return MZ_FALSE; } cur_src_file_ofs += n; if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) { pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); return MZ_FALSE; } cur_dst_file_ofs += n; comp_bytes_remaining -= n; } bit_flags = MZ_READ_LE16(pLocal_header + MZ_ZIP_LDH_BIT_FLAG_OFS); if (bit_flags & 8) { // Copy data descriptor if (pSource_zip->m_pRead(pSource_zip->m_pIO_opaque, cur_src_file_ofs, pBuf, sizeof(mz_uint32) * 4) != sizeof(mz_uint32) * 4) { pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); return MZ_FALSE; } n = sizeof(mz_uint32) * ((MZ_READ_LE32(pBuf) == 0x08074b50) ? 4 : 3); if (pZip->m_pWrite(pZip->m_pIO_opaque, cur_dst_file_ofs, pBuf, n) != n) { pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); return MZ_FALSE; } cur_src_file_ofs += n; cur_dst_file_ofs += n; } pZip->m_pFree(pZip->m_pAlloc_opaque, pBuf); // no zip64 support yet if (cur_dst_file_ofs > 0xFFFFFFFF) return MZ_FALSE; orig_central_dir_size = pState->m_central_dir.m_size; memcpy(central_header, pSrc_central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE); MZ_WRITE_LE32(central_header + MZ_ZIP_CDH_LOCAL_HEADER_OFS, local_dir_header_ofs); if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, central_header, MZ_ZIP_CENTRAL_DIR_HEADER_SIZE)) return MZ_FALSE; n = MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_FILENAME_LEN_OFS) + MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_EXTRA_LEN_OFS) + MZ_READ_LE16(pSrc_central_header + MZ_ZIP_CDH_COMMENT_LEN_OFS); if (!mz_zip_array_push_back(pZip, &pState->m_central_dir, pSrc_central_header + MZ_ZIP_CENTRAL_DIR_HEADER_SIZE, n)) { mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); return MZ_FALSE; } if (pState->m_central_dir.m_size > 0xFFFFFFFF) return MZ_FALSE; n = (mz_uint32)pState->m_central_dir.m_size; if (!mz_zip_array_push_back(pZip, &pState->m_central_dir_offsets, &n, 1)) { mz_zip_array_resize(pZip, &pState->m_central_dir, orig_central_dir_size, MZ_FALSE); return MZ_FALSE; } pZip->m_total_files++; pZip->m_archive_size = cur_dst_file_ofs; return MZ_TRUE; } mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip) { mz_zip_internal_state *pState; mz_uint64 central_dir_ofs, central_dir_size; mz_uint8 hdr[MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE]; if ((!pZip) || (!pZip->m_pState) || (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING)) return MZ_FALSE; pState = pZip->m_pState; // no zip64 support yet if ((pZip->m_total_files > 0xFFFF) || ((pZip->m_archive_size + pState->m_central_dir.m_size + MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIZE) > 0xFFFFFFFF)) return MZ_FALSE; central_dir_ofs = 0; central_dir_size = 0; if (pZip->m_total_files) { // Write central directory central_dir_ofs = pZip->m_archive_size; central_dir_size = pState->m_central_dir.m_size; pZip->m_central_directory_file_ofs = central_dir_ofs; if (pZip->m_pWrite(pZip->m_pIO_opaque, central_dir_ofs, pState->m_central_dir.m_p, (size_t)central_dir_size) != central_dir_size) return MZ_FALSE; pZip->m_archive_size += central_dir_size; } // Write end of central directory record MZ_CLEAR_OBJ(hdr); MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_SIG_OFS, MZ_ZIP_END_OF_CENTRAL_DIR_HEADER_SIG); MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_NUM_ENTRIES_ON_DISK_OFS, pZip->m_total_files); MZ_WRITE_LE16(hdr + MZ_ZIP_ECDH_CDIR_TOTAL_ENTRIES_OFS, pZip->m_total_files); MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_SIZE_OFS, central_dir_size); MZ_WRITE_LE32(hdr + MZ_ZIP_ECDH_CDIR_OFS_OFS, central_dir_ofs); if (pZip->m_pWrite(pZip->m_pIO_opaque, pZip->m_archive_size, hdr, sizeof(hdr)) != sizeof(hdr)) return MZ_FALSE; #ifndef MINIZ_NO_STDIO if ((pState->m_pFile) && (MZ_FFLUSH(pState->m_pFile) == EOF)) return MZ_FALSE; #endif // #ifndef MINIZ_NO_STDIO pZip->m_archive_size += sizeof(hdr); pZip->m_zip_mode = MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED; return MZ_TRUE; } mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **pBuf, size_t *pSize) { if ((!pZip) || (!pZip->m_pState) || (!pBuf) || (!pSize)) return MZ_FALSE; if (pZip->m_pWrite != mz_zip_heap_write_func) return MZ_FALSE; if (!mz_zip_writer_finalize_archive(pZip)) return MZ_FALSE; *pBuf = pZip->m_pState->m_pMem; *pSize = pZip->m_pState->m_mem_size; pZip->m_pState->m_pMem = NULL; pZip->m_pState->m_mem_size = pZip->m_pState->m_mem_capacity = 0; return MZ_TRUE; } mz_bool mz_zip_writer_end(mz_zip_archive *pZip) { mz_zip_internal_state *pState; mz_bool status = MZ_TRUE; if ((!pZip) || (!pZip->m_pState) || (!pZip->m_pAlloc) || (!pZip->m_pFree) || ((pZip->m_zip_mode != MZ_ZIP_MODE_WRITING) && (pZip->m_zip_mode != MZ_ZIP_MODE_WRITING_HAS_BEEN_FINALIZED))) return MZ_FALSE; pState = pZip->m_pState; pZip->m_pState = NULL; mz_zip_array_clear(pZip, &pState->m_central_dir); mz_zip_array_clear(pZip, &pState->m_central_dir_offsets); mz_zip_array_clear(pZip, &pState->m_sorted_central_dir_offsets); #ifndef MINIZ_NO_STDIO if (pState->m_pFile) { MZ_FCLOSE(pState->m_pFile); pState->m_pFile = NULL; } #endif // #ifndef MINIZ_NO_STDIO if ((pZip->m_pWrite == mz_zip_heap_write_func) && (pState->m_pMem)) { pZip->m_pFree(pZip->m_pAlloc_opaque, pState->m_pMem); pState->m_pMem = NULL; } pZip->m_pFree(pZip->m_pAlloc_opaque, pState); pZip->m_zip_mode = MZ_ZIP_MODE_INVALID; return status; } #ifndef MINIZ_NO_STDIO mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags) { mz_bool status, created_new_archive = MZ_FALSE; mz_zip_archive zip_archive; struct MZ_FILE_STAT_STRUCT file_stat; MZ_CLEAR_OBJ(zip_archive); if ((int)level_and_flags < 0) level_and_flags = MZ_DEFAULT_LEVEL; if ((!pZip_filename) || (!pArchive_name) || ((buf_size) && (!pBuf)) || ((comment_size) && (!pComment)) || ((level_and_flags & 0xF) > MZ_UBER_COMPRESSION)) return MZ_FALSE; if (!mz_zip_writer_validate_archive_name(pArchive_name)) return MZ_FALSE; if (MZ_FILE_STAT(pZip_filename, &file_stat) != 0) { // Create a new archive. if (!mz_zip_writer_init_file(&zip_archive, pZip_filename, 0)) return MZ_FALSE; created_new_archive = MZ_TRUE; } else { // Append to an existing archive. if (!mz_zip_reader_init_file(&zip_archive, pZip_filename, level_and_flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY)) return MZ_FALSE; if (!mz_zip_writer_init_from_reader(&zip_archive, pZip_filename)) { mz_zip_reader_end(&zip_archive); return MZ_FALSE; } } status = mz_zip_writer_add_mem_ex(&zip_archive, pArchive_name, pBuf, buf_size, pComment, comment_size, level_and_flags, 0, 0); // Always finalize, even if adding failed for some reason, so we have a valid central directory. (This may not always succeed, but we can try.) if (!mz_zip_writer_finalize_archive(&zip_archive)) status = MZ_FALSE; if (!mz_zip_writer_end(&zip_archive)) status = MZ_FALSE; if ((!status) && (created_new_archive)) { // It's a new archive and something went wrong, so just delete it. int ignoredStatus = MZ_DELETE_FILE(pZip_filename); (void)ignoredStatus; } return status; } void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint flags) { int file_index; mz_zip_archive zip_archive; void *p = NULL; if (pSize) *pSize = 0; if ((!pZip_filename) || (!pArchive_name)) return NULL; MZ_CLEAR_OBJ(zip_archive); if (!mz_zip_reader_init_file(&zip_archive, pZip_filename, flags | MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY)) return NULL; if ((file_index = mz_zip_reader_locate_file(&zip_archive, pArchive_name, NULL, flags)) >= 0) p = mz_zip_reader_extract_to_heap(&zip_archive, file_index, pSize, flags); mz_zip_reader_end(&zip_archive); return p; } #endif // #ifndef MINIZ_NO_STDIO #endif // #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS #endif // #ifndef MINIZ_NO_ARCHIVE_APIS #ifdef __cplusplus } #endif #endif // MINIZ_HEADER_FILE_ONLY /* This is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. For more information, please refer to */ cppcheck-1.61/htdocs/archive/renamefile.c000066400000000000000000000050541217722632100204100ustar00rootroot00000000000000#include #include #include #include #include "webarchive.h" const char *validate(const char *data) { int i; // name1 if (strncmp(data,"name1=",6) != 0) return "invalid query string: must start with 'name1='"; i = 6; while (isalnum(data[i])) i++; if (i == 6) return "invalid query string: no name1"; if (i > 36) return "invalid query string: max name1 size is 30"; // name2 const int i1 = i; if (strncmp(data+i,"&name2=",7) != 0) return "invalid query string: no name2"; i += 7; if (!isalnum(data[i])) return "invalid query string: empty name2"; while (isalnum(data[i])) i++; if (i - i1 > 37) return "invalid query string: max name2 size is 30"; if (data[i] != '\0') return "invalid query string: invalid char in name2"; return NULL; } int main() { const char *query_string = getenv("QUERY_STRING"); if (query_string == NULL) { generatepage("Internal error: empty/invalid data"); } else if (NULL != validate(query_string)) { generatepage(validate(query_string)); } else { char *data[MAX_RECORDS] = {0}; if (!readdata(data, MAX_RECORDS)) { generatepage("access failed, try again"); return EXIT_SUCCESS; } sortdata(data, MAX_RECORDS); // Get name1 and name2.. char buf[strlen(query_string)]; strcpy(buf, query_string); const char * const name1 = strstr(buf, "name1=") + 6; const char * const name2 = strstr(buf, "name2=") + 6; for (int i = 0; buf[i] != '\0'; i++) { if (buf[i] == '&') buf[i] = '\0'; } int index = -1; for (int i = 0; i < MAX_RECORDS && data[i]; i++) { if (strcmp(name1, getname(data[i])) == 0) { index = i; break; } } if (index == -1) { generatepage("file not found"); return EXIT_SUCCESS; } FILE *f = fopen("data.txt", "wt"); if (f == NULL) { generatepage("failed to rename file (access denied), try again"); return EXIT_SUCCESS; } for (int i = 0; i < MAX_RECORDS && data[i]; i++) { if (i == index) fprintf(f, "name=%s%s\n", name2, data[i]+5+strlen(name1)); else fprintf(f, "%s\n", data[i]); } fclose(f); generatepage("file renamed"); } return EXIT_SUCCESS; } cppcheck-1.61/htdocs/archive/report.c000066400000000000000000000042011217722632100176050ustar00rootroot00000000000000#include #include #include #include #include "webarchive.h" #define MAX_RECORDS 1000 void listAll(char **data) { puts("Content-type: text/html\r\n\r\n"); puts(""); puts("
"); for (int i = 0; i < MAX_RECORDS && data[i]; i++) { const char *name = getname(data[i]); int version = getversion(data[i]); if (version < 0) version = time(0); if (i > 0) printf(""); printf("", name); printf("", name, version); printf("\n"); } puts("
%s", name, version); printf("", name, version); printf(" 
"); } void listOne(char **data, const char name[]) { int index = -1; for (int i = 0; i < MAX_RECORDS && data[i]; i++) { if (strcmp(getname(data[i]), name)==0) { index = i; break; } } puts("Content-type: text/plain\r\n\r\n"); puts((index == -1) ? "Not found" : data[index]); } int main() { char *data[MAX_RECORDS] = {0}; // read if (!readdata(data, MAX_RECORDS)) { puts("Content-type: text/html\r\n\r\n"); puts("Internal error: failed to load data"); return 0; } // sort sortdata(data,MAX_RECORDS); const char *query_string = getenv("QUERY_STRING"); if (query_string == NULL || *query_string == '\0') { listAll(data); } else if (strncmp(query_string, "name=", 5) == 0 && getname(query_string) != NULL) { char name[MAX_NAME_LEN] = {0}; strcpy(name, getname(query_string)); listOne(data,name); } else { puts("Content-type: text/plain\r\n\r\n"); puts("Invalid query"); } return 0; } cppcheck-1.61/htdocs/archive/setfiledata.c000066400000000000000000000033311217722632100205620ustar00rootroot00000000000000#include #include #include #include #include "webarchive.h" int main() { const char *query_string = getenv("QUERY_STRING"); if (query_string == NULL) { generatepage("Internal error: invalid request"); return EXIT_SUCCESS; } if (NULL != validate_name_version_data(query_string)) { generatepage(validate_name_version_data(query_string)); return EXIT_SUCCESS; } char *data[MAX_RECORDS] = {0}; if (!readdata(data, MAX_RECORDS)) { generatepage("Failed to read file data"); return EXIT_SUCCESS; } char name[MAX_NAME_LEN] = {0}; strcpy(name, getname(query_string)); int index = -1; for (int i = 0; i < MAX_RECORDS && data[i]; i++) { if (strcmp(name, getname(data[i])) == 0) { index = i; break; } } if (index == -1) { generatepage("File not found"); return EXIT_SUCCESS; } // cleanup data... char str[MAX_LINE_LEN] = {0}; char *dst = str; for (const char *src = query_string; *src; src++) { *dst = *src; dst++; if (strncmp(src, "%25", 3) == 0 && isxdigit(src[3]) && isxdigit(src[4])) src += 2; } data[index] = str; sortdata(data, MAX_RECORDS); FILE *f = fopen("data.txt", "wt"); if (f == NULL) { generatepage("Failed to add file (access denied). Try again."); return EXIT_SUCCESS; } for (int i = 0; i < MAX_RECORDS && data[i]; i++) fprintf(f, "%s\n", data[i]); fclose(f); generatepage("saved."); f = fopen("setfiledata.log", "at"); if (f) { fprintf(f,"%s\n",str); fclose(f); } return EXIT_SUCCESS; } cppcheck-1.61/htdocs/archive/validatexml.c000066400000000000000000000076621217722632100206220ustar00rootroot00000000000000#include #include #include #include "validatexml.h" void skipspaces(const char xmldata[], int *pos, int *linenr) { const char *p = &xmldata[*pos]; while (isspace(*p) || *p == '\r' || *p == '\n') { if (strncmp(p,"\r\n",2)==0) ++p; if (*p == '\r' || *p == '\n') ++(*linenr); ++p; } *pos = p - xmldata; } int validatexml(const char xmldata[]) { if (strncmp(xmldata,"",21)!=0) return 1; int linenr = 1; char elementNames[10][64]; // only 10 element levels handled int level = 0; for (int pos = 21; xmldata[pos]; pos++) { if (strncmp(&xmldata[pos], "\r\n", 2)==0) { ++linenr; ++pos; } else if (xmldata[pos]=='\r' || xmldata[pos]=='\n') { ++linenr; } else if (xmldata[pos] == '<') { // found a element, validate it ++pos; skipspaces(xmldata,&pos,&linenr); // is this a end-element? if (xmldata[pos] == '/') { // end element without any previous start element if (level <= 0) { return linenr; } --level; // compare name of end element with name of start element int len = strlen(elementNames[level]); if (strncmp(&xmldata[pos+1],elementNames[level],len)!=0 || xmldata[pos+1+len]!='>') return linenr; pos += 1 + len; } else { // this validator allows max 8 element levels if (level > 8) return linenr; if (!isalpha(xmldata[pos])) return linenr; // add element name to elementNames so it can be compared later against the end element memset(elementNames[level], 0, 64); for (int i = 0; i < 64; i++) { if ((xmldata[pos+i]>='a' && xmldata[pos+i]<='z') || xmldata[pos+i] == '-') elementNames[level][i] = xmldata[pos+i]; else { pos += i; break; } } if (!strchr("/> \r\n", xmldata[pos])) return linenr; level++; // validate all attributes while (xmldata[pos] != '/' && xmldata[pos] != '>') { // validate one attribute skipspaces(xmldata,&pos,&linenr); if ((xmldata[pos] >= 'a') && xmldata[pos] <= 'z') { // attribute name while (((xmldata[pos] >= 'a') && xmldata[pos] <= 'z') || xmldata[pos] == '-') ++pos; if (xmldata[pos++] != '=') return linenr; if (xmldata[pos++] != '\"') return linenr; // attribute value while (isalnum(xmldata[pos]) || strchr(":-.,_",xmldata[pos])) ++pos; if (xmldata[pos++] != '\"') return linenr; if (!strchr("> \r\n", xmldata[pos])) return linenr; } else if (xmldata[pos] != '/' && xmldata[pos] != '>') { return linenr; } } // no end element.. if (xmldata[pos] == '/') { --level; ++pos; skipspaces(xmldata,&pos,&linenr); if (xmldata[pos] != '>') return linenr; } } } else if (xmldata[pos] == '>') { return linenr; } } if (level != 0) return linenr; return -1; } cppcheck-1.61/htdocs/archive/validatexml.h000066400000000000000000000001631217722632100206140ustar00rootroot00000000000000#ifndef VALIDATEXMLH #define VALIDATEXMLH /** validate xml data */ int validatexml(const char xmldata[]); #endif cppcheck-1.61/htdocs/archive/webarchive.h000066400000000000000000000115761217722632100204330ustar00rootroot00000000000000#include "validatexml.h" #include #include #include #include #define MAX_RECORDS 1000 #define MAX_LINE_LEN 0xffff #define MAX_NAME_LEN 32 static void unencode(const char *src, char *dest) { for (; *src; src++, dest++) { if (*src == '+') *dest = ' '; else if (*src == '%') { int code; if (sscanf(src+1, "%2x", &code) != 1) code = '?'; if (code == '%' && isxdigit(src[3]) && isxdigit(src[4])) { src += 2; sscanf(src+1, "%2x", &code); } *dest = code; src += 2; } else *dest = *src; } *dest = '\0'; } int readdata(char * * const data, int sz) { FILE *f = fopen("data.txt", "rt"); if (!f) return 0; // failed char line[MAX_LINE_LEN] = {0}; int i = 0; while (i < sz && fgets(line,sizeof(line)-2,f)) { if (strncmp(line, "name=", 5) == 0) { int len = strlen(line); while (line[len-1] == '\n' || line[len-1] == '\r' || line[len-1] == '\t' || line[len-1] == ' ') line[--len] = '\0'; data[i] = malloc(len); strcpy(data[i], line); i++; } } fclose(f); return 1; // success } const char * getname(const char *data) { static char name[32]; if (strncmp(data,"name=",5) != 0) return NULL; int i = 0; while (i < sizeof(name) && data[i+5] && data[i+5] != '&') { name[i] = data[i+5]; i++; } if (i >= sizeof(name)) return NULL; while (i < sizeof(name)) name[i++] = 0; return name; } int getversion(const char *data) { const char *name = getname(data); if (name == NULL) return 0; // invalid string => 0 data = data + strlen("name=") + strlen(name); if (strncmp(data,"&version=",9) != 0) return 1; // no version => 1 data = data + 9; int ret = 0; while (isdigit(*data)) { ret = ret * 10 + *data - '0'; data++; } if (*data != '\0' && *data != '&') return -1; // invalid version => -1 return ret; } void sortdata(char * * const data, int sz) { for (int i = 1; i < sz && data[i]; i++) { if (strcmp(data[i-1], data[i]) > 0) { char *p = data[i-1]; data[i-1] = data[i]; data[i] = p; if (i >= 2) i -= 2; } } } void generatepage(const char msg[]) { puts("Content-type: text/html\r\n\r\n"); puts(""); puts(""); puts(""); puts(msg); puts("
"); } const char *validate_name_version(const char *data) { int i = 0; // name if (strncmp(data,"name=",5) != 0) return "invalid query string: must start with 'name='"; i += 5; if (!isalnum(data[i])) return "invalid query string: no name / invalid character in name"; while (isalnum(data[i])) i++; if (i > 35) return "invalid query string: max name size is 32"; // version if (strncmp(&data[i], "&version=", 9) != 0) return "invalid query string: 'version=' not seen at the expected location"; i += strlen("&version="); if (!isdigit(data[i])) return "invalid query string: version must consist of digits 0-9"; while (isdigit(data[i])) i++; // end if (data[i] != '\0') return "invalid query"; return NULL; } const char *validate_name_version_data(const char *data) { int i = 0; // name if (strncmp(data,"name=",5) != 0) return "invalid query string: must start with 'name='"; i += 5; if (!isalnum(data[i])) return "invalid query string: no name / invalid character in name"; while (isalnum(data[i])) i++; if (i > 35) return "invalid query string: max name size is 32"; // version if (strncmp(&data[i], "&version=", 9) != 0) return "invalid query string: 'version=' not seen at the expected location"; i += strlen("&version="); if (!isdigit(data[i])) return "invalid query string: version must consist of digits 0-9"; while (isdigit(data[i])) i++; // filedata if (strncmp(data+i, "&data=", 6) != 0) return "invalid query string: 'data=' not seen at the expected location"; i += 6; // validate xml char xmldata[strlen(data+i)]; memset(xmldata, 0, strlen(data+i)); unencode(data+i, xmldata); const int badline = validatexml(xmldata); if (badline >= 1) { static char buf[256]; sprintf(buf, "Invalid query: Invalid XML at line %i\n", badline); return buf; } // No error return NULL; } cppcheck-1.61/htdocs/demo/000077500000000000000000000000001217722632100154345ustar00rootroot00000000000000cppcheck-1.61/htdocs/demo/index.php000066400000000000000000000124001217722632100172510ustar00rootroot00000000000000 Online Demo - Cppcheck

Online Demo

(max 1024 characters)

Examples

This code can be copied and pasted in the edit box above.

NULL pointers

void f1(struct fred_t *p)
{
    // dereference p and then check if it's NULL
    int x = p->x;
    if (p)
        do_something(x);
}

void f2()
{
    const char *p = NULL;
    for (int i = 0; str[i] != '\0'; i++)
    {
        if (str[i] == ' ')
        {
            p = str + i;
            break;
        }
    }

    // p is NULL if str doesn't have a space. If str always has a
    // a space then the condition (str[i] != '\0') would be redundant
    return p[1];
}

void f3(int a)
{
    struct fred_t *p = NULL;
    if (a == 1)
        p = fred1;

    // if a is not 1 then p is NULL
    p->x = 0;
}
cppcheck-1.61/htdocs/demo/report/000077500000000000000000000000001217722632100167475ustar00rootroot00000000000000cppcheck-1.61/htdocs/demo/report/index.php000066400000000000000000000132321217722632100205700ustar00rootroot00000000000000 $code ) ); $opts = array('http' => array( 'method' => 'POST', 'header' => 'Content-type: application/x-www-form-urlencoded', 'content' => $postdata ) ); $context = stream_context_create($opts); return @file_get_contents('http://cppcheck.sourceforge.net/cgi-bin/democlient.cgi', false, $context); } function cut_string($string, $length = 1024) { if (strlen($string) > $length) { return substr($string, 0, $length); } return $string; } //-------------------------------------------------------------------------------- // XML output... //-------------------------------------------------------------------------------- if ($isXmlOutput) { //if XML output... header('Content-Type: text/xml'); if (!$isCodePosted) { //if NO code posted... echo "\n\n"; exit; } $output = get_democlient_output(cut_string($_POST['code'])); if ($output === false) { //if NO demo client output... echo "\n\n"; exit; } echo $output; exit; } //-------------------------------------------------------------------------------- ?> Online Demo Report - Cppcheck

Online Demo Report

errors->error as $error) { //for all errors... $severity = (string)$error->attributes()->severity; $msg = (string)$error->attributes()->msg; $line = (string)$error->location->attributes()->line; if (!empty($severity) && !empty($msg) && !empty($line)) { //if complete error... $parsed[] = array('severity' => $severity, 'msg' => $msg, 'line' => $line); } } return $parsed; } catch (Exception $ex) { return array(); } } if ($isCodePosted) { //if code posted... include_once '../../site/geshi/geshi.php'; $code = cut_string($_POST['code']); $geshi = new GeSHi($code, 'cpp'); $geshi->enable_classes(); $geshi->set_header_type(GESHI_HEADER_PRE_TABLE); $geshi->enable_line_numbers(GESHI_NORMAL_LINE_NUMBERS); $geshi->set_overall_class('geshicode'); echo "

Input

\n"; echo $geshi->parse_code(); echo "

Output

\n"; $output = get_democlient_output($code); if (!$output === false) { $results = parse_democlient_output($output); if (!empty($results)) { echo "\n"; echo "\n"; echo " \n"; echo "\n"; echo "\n"; foreach ($results as $result) { //for each result... echo " \n"; } echo "\n"; echo "
LineSeverityMessage
" . htmlspecialchars($result['line']) . "" . htmlspecialchars($result['severity']) . "" . htmlspecialchars($result['msg']) . "
\n"; } else { echo "

No errors found.

\n"; } } else { echo "

Problem with demo client. Please try again.

\n"; } } else { //if NO code posted... echo "

Use the online demo page to create the report.

\n"; } ?>
cppcheck-1.61/htdocs/devinfo/000077500000000000000000000000001217722632100161425ustar00rootroot00000000000000cppcheck-1.61/htdocs/devinfo/index.php000066400000000000000000000123711217722632100177660ustar00rootroot00000000000000 Developer Information - Cppcheck

Source Code

Latest version can be found in the cppcheck git repository.

To get the source code using git:

git clone git://github.com/danmar/cppcheck.git

To get the source code using subversion:

svn checkout https://github.com/danmar/cppcheck/trunk

You can also download the latest sources in a zip or tgz archive from the github website.

Recent Commits

View all commits…

Trac Timeline

set_feed_url('http://sourceforge.net/apps/trac/cppcheck/timeline?changeset=on&ticket=on&milestone=on&wiki=on&max=10&daysback=90&format=rss'); $feed->set_cache_location('../site/simplepie/cache'); $feed->init(); print("
    \n"); foreach ($feed->get_items() as $item) { //for the last timeline items... $author = $item->get_author(); print("
  • get_link()."\">".$item->get_title()." by ".$author->get_name()." on ".$item->get_date('Y-m-d')."
  • \n"); } print("
\n"); ?>

View complete Trac timeline…

Active Forum Topics

\n"); foreach ($activetopics->getTopics(0, 10) as $topic) { //for all active topics... $lastPostLine = ''; if ($topic->getLastPost() != null) { $lastPost = $topic->getLastPost(); $lastPostLine = sprintf('last post by %1$s at %2$s', $lastPost->getUser(), $lastPost->getDate('Y-m-d H:i')); } print("
  • getLink()."\">".$topic->getTitle()." ".$lastPostLine."
  • \n"); } print("\n"); ?>

    View all active topics…

    Doxygen

    Other

    cppcheck-1.61/htdocs/favicon.ico000066400000000000000000000021761217722632100166370ustar00rootroot00000000000000 h(  +$ kU<0>SBs[~ezahS-$*hQA*!?<J;aN} &%-$w $PPbb~JJrCCtwP?aO//?ggT}dcP ]77|II@%%yW_886 V` C((%]L--yGG$ f<##wL@&&VvFF&aa||vEES00<## F))sI++q銊j??wFF7 E))&[N..'7 }9"") H yY44ԀKKKKc::/?U]]cppcheck-1.61/htdocs/index.php000066400000000000000000000175271217722632100163440ustar00rootroot00000000000000 Cppcheck - A tool for static C/C++ code analysis

    Cppcheck is a static analysis tool for C/C++ code. Unlike C/C++ compilers and many other analysis tools it does not detect syntax errors in the code. Cppcheck primarily detects the types of bugs that the compilers normally do not detect. The goal is to detect only real errors in the code (i.e. have zero false positives).

    Download

    Download Now! Version 1.60.1 for Windows

    You can download the standalone Cppcheck from our project page or add it as a plugin for your favorite IDE:

    There is no plugin for Visual Studio, but it is possible to add Cppcheck as an external tool. You can also try the proprietary PVS-Studio (there is a free trial), which is oriented for this environment. A comparison of Cppcheck and PVS-Studio can be found here and we believe it's a good and honest comparison.

    Features

    • Out of bounds checking
    • Check the code for each class
    • Checking exception safety
    • Memory leaks checking
    • Warn if obsolete functions are used
    • Check for invalid usage of STL
    • Check for uninitialized variables and unused functions

    News

    set_feed_url('http://sourceforge.net/p/cppcheck/news/feed'); $feed->set_cache_location('./site/simplepie/cache'); $feed->init(); print("\n"); ?>

    View all news…

    Documentation

    You can read the manual or download some articles.

    Support

    Contribute

    You are welcome to contribute. Help is needed.

    Testing
    Pick a project and test it's source with latest version. Write tickets to Trac about issues you find from Cppcheck. If you test open source projects and write bug reports to them, check the issues in the “Found bugs” wiki section, and write links to the bug reports you have created e.g. to our forum, so we can keep a track about them.
    Developing
    Pick a ticket from Trac, write a test case for it (and write a comment to the ticket that test case has been created). Or pick a test case that fails and try to fix it. Make a patch and submit it to Trac either inline if it is small, or attach it as a file.
    Marketing
    Write articles, reviews or tell your friends about us. The more users we have, the more people we have testing and the better we can become.
    Design
    Invent new good checks and create tickets to Trac about them.
    Integration
    Write a plugin to your favorite IDE or create a package for your distribution or operating system.
    Technical Writer
    Write better documentation for the bugs we find. Currently only a few bugs have any documentation at all.
    cppcheck-1.61/htdocs/site/000077500000000000000000000000001217722632100154545ustar00rootroot00000000000000cppcheck-1.61/htdocs/site/.jshintrc000066400000000000000000000005471217722632100173070ustar00rootroot00000000000000{ "bitwise": true, "boss": true, "browser": false, "camelcase": true, "curly": true, "eqeqeq": true, "indent": 4, "latedef": true, "multistr": true, "noarg": true, "node": true, "noempty": true, "plusplus": false, "quotmark": "double", "regexp": true, "shelljs": true, "strict": false, "trailing": true, "unused": true } cppcheck-1.61/htdocs/site/Readme.md000066400000000000000000000005231217722632100171730ustar00rootroot00000000000000Getting started --------------- * Install [node.js](http://nodejs.org/download/) * Install the node.js dependencies: `npm install` * Run `node make` or `node make minify` You can run `npm run check` or `npm run lint` to run [JSHint](https://github.com/jshint/jshint) and [csslint](https://github.com/stubbornella/csslint) for our files. cppcheck-1.61/htdocs/site/activetopics.php000066400000000000000000000135441217722632100206710ustar00rootroot00000000000000_forumHome = $forumHome; $this->_topics = array(); $this->update(); } /** * ... * @param int $start ... * @param int $end ... * @return array ... */ public function getTopics($start = 0, $end = 0) { if ($end == 0) { return array_slice($this->_topics, $start); } else { return array_slice($this->_topics, $start, $end); } //return $this->_topics; } /** * ... * @param int $days ... */ public function update($days = 30) { $this->_topics = array(); $html = file_get_contents($this->_forumHome . 'search.php?st=' . $days . '&search_id=active_topics'); $html = strip_tags($html, '
    '); $html = preg_replace(array('#\t#', '#&sid=[a-z0-9]+#'), '', $html); if (preg_match_all('#(.*?)#im', $html, $matches)) { $lastPosts = array(); if (preg_match_all('#
    \nby (.*?) ([A-Za-z0-9,: ]+) \n
    #i', $html, $lastPostMatches)) { $lastPostUserLinks = $lastPostMatches[1]; $lastPostUserNames = $lastPostMatches[2]; $lastPostTimes = $lastPostMatches[3]; for ($i = 0; $i < count($lastPostUserLinks); $i++) { //for all users... $link = $this->_forumHome . $lastPostUserLinks[$i]; $name = $lastPostUserNames[$i]; $timestamp = strtotime($lastPostTimes[$i]); if ($timestamp === false || $timestamp === -1) { $timestamp = 0; } $lastPosts[] = new Forum_LastPost(new Forum_User($link, $name), $timestamp); } } $links = $matches[1]; $titles = $matches[2]; for ($i = 0; $i < count($links); $i++) { //for all topics... $link = $this->_forumHome . $links[$i]; $title = $titles[$i]; $lastPost = $lastPosts[$i]; $this->_topics[] = new Forum_Topic($link, $title, $lastPost); } } } } class Forum_Topic { /** * ... * @var string ... */ private $_link; /** * ... * @var string ... */ private $_title; /** * ... * @var Forum_LastPost ... */ private $_lastPost; /** * ... * @param string $link ... * @param string $title ... * @param Forum_LastPost $lastPost ... */ public function __construct($link, $title, $lastPost = null) { $this->_link = $link; $this->_title = $title; $this->_lastPost = $lastPost; } /** * ... * @return string ... */ public function getLink() { return $this->_link; } /** * ... * @return string ... */ public function getTitle() { return $this->_title; } /** * ... * @return Forum_LastPost ... */ public function getLastPost() { return $this->_lastPost; } /** * ... * @return Forum_User ... * @deprecated */ public function getLastPostUser() { if (!empty($this->_lastPost)) { return $this->_lastPost->getUser(); } return null; } /** * ... * @return integer ... * @deprecated */ public function getLastPostTimestamp() { if (!empty($this->_lastPost)) { return $this->_lastPost->getTimestamp(); } return 0; } } class Forum_User { /** * ... * @var string ... */ private $_link; /** * ... * @var string ... */ private $_name; /** * ... * @param string $link ... * @param string $name ... */ public function __construct($link, $name) { $this->_link = $link; $this->_name = $name; } /** * ... * @return string ... */ public function getLink() { return $this->_link; } /** * ... * @return string ... */ public function getName() { return $this->_name; } /** * ... */ public function __toString() { return $this->_name; } } class Forum_LastPost { /** * ... * @var Forum_User ... */ private $_user; /** * ... * @var integer ... */ private $_timestamp; /** * ... * @param Forum_User $user ... * @param integer $timestamp ... */ public function __construct($user, $timestamp) { $this->_user = $user; $this->_timestamp = $timestamp; } /** * ... * @return Forum_User ... */ public function getUser() { return $this->_user; } /** * ... * @return integer ... */ public function getTimestamp() { return $this->_timestamp; } /** * ... * @return string ... */ public function getDate($format) { return date($format, $this->_timestamp); } } ?> cppcheck-1.61/htdocs/site/css/000077500000000000000000000000001217722632100162445ustar00rootroot00000000000000cppcheck-1.61/htdocs/site/css/all.css000066400000000000000000000057541217722632100175410ustar00rootroot00000000000000/*csslint box-sizing: false, ids: false, qualified-headings: false*/ body { margin: 0; padding: 0; font: 16px Calibri, Verdana, sans-serif; color: black; background-color: #eee; } dt { font-weight: bold; } /* Default link style */ a:hover { -webkit-transition: all 0.20s ease-in-out; -moz-transition: all 0.20s ease-in-out; -o-transition: all 0.20s ease-in-out; transition: all 0.20s ease-in-out; } a:link, a:visited { color: #036; text-decoration: underline; } a:active, a:focus, a:hover, a:visited { color: #369; } /* Header */ #header { color: #69c; background-color: #036; } #header a { color: inherit; text-decoration: none; } #header h1 { margin: 0; padding: 0; font-family: Orbitron; } #header p { margin: 0; padding: 0; font-size: larger; } /* Tabs */ #tabs { color: #eee; background-color: #369; border-top: 1px solid black; border-bottom: 1px solid black; } #tabs ul { margin: 0; padding: 0; list-style-type: none; font-size: larger; } #tabs li { display: inline; padding: 0 .5em; border-right: 1px solid black; } #tabs li:first-child { padding-left: 0; } #tabs li:last-child { border: none; } #tabs a:link, #tabs a:visited { color: #eee; text-decoration: none; } #tabs a:focus, #tabs a:hover, #tabs a:active { color: white; text-decoration: underline; } /* Anchors */ #anchors ul { margin: 0; padding: .5em 0; list-style-type: none; font-size: smaller; } #anchors li { display: inline; padding: 0 .5em; } #anchors li:first-child { padding-left: 0; } #anchors .wrap { padding: 0; } /* Wrap */ .wrap { width: 50em; margin: 0 auto; padding: .5em; -webkit-box-sizing: content-box; -moz-box-sizing: content-box; box-sizing: content-box; } /* RSS feed items */ .rssfeeditems em { margin-left: .5em; color: #888; font-size: smaller; } a.author:link, a.author:visited, a.author:link:hover, a.author:visited:hover, a.author:focus, a.author:active { color: #888; } /* "Download Now!" link */ a.downloadnow { display: block; width: 12em; margin: 0; padding: 5px; text-align: center; text-decoration: none; color: white; background-color: #060; border: 1px solid #003D00; -webkit-border-radius: 0.5em; -khtml-border-radius: 0.5em; -moz-border-radius: 0.5em; border-radius: 0.5em; -webkit-box-sizing: content-box; -moz-box-sizing: content-box; box-sizing: content-box; } a.downloadnow:focus, a.downloadnow:hover { background-color: #090; } .downButtonText { display: block; font-size: larger; font-weight: bold; } .downButtonVersion { display: block; font-size: smaller; } /* Command */ .cmd { padding: .5em; background-color: #f7f7f7; border: 1px solid silver; border-left: 10px solid silver; } /* Printing */ @media print { #header { color: black; border-bottom: 1px solid black; } #tabs { display: none; } #resultsTable th, #resultsTable td { background-color: white; border: 1px solid black; } } cppcheck-1.61/htdocs/site/css/demo.css000066400000000000000000000045131217722632100177050ustar00rootroot00000000000000/* Source Code */ .geshicode { padding: .5em; background: #f7f7f7; border: 1px solid #e2e2e2; } /* Results table */ #resultsTable { border-collapse: collapse; } #resultsTable th { padding: .25em; text-align: left; background: #e2e2e2; border: 1px solid #e2e2e2; } #resultsTable td { padding: .25em; background: #f7f7f7; border: 1px solid #e2e2e2; } #resultsTable .center { text-align: center; } /* Max characters */ .maxChars { margin-left: 2em; color: #888; font-size: smaller; font-style: italic; } /** * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann * (http://qbnz.com/highlighter/ and http://geshi.org/) */ .cpp.geshicode .de1, .cpp.geshicode .de2 {font:normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;} .cpp.geshicode {font-family:monospace;} .cpp.geshicode .imp {font-weight:bold; color:red;} .cpp.geshicode li, .cpp.geshicode .li1 {font-weight:normal; vertical-align:top;} .cpp.geshicode .ln {width:1px; text-align:right; margin:0; padding:0 2px; vertical-align:top; color:#999999;} .cpp.geshicode .kw1 {color:#0000ff;} .cpp.geshicode .kw2 {color:#0000ff;} .cpp.geshicode .kw3 {color:#0000dd;} .cpp.geshicode .kw4 {color:#0000ff;} .cpp.geshicode .co1 {color:#666666;} .cpp.geshicode .co2 {color:#339900;} .cpp.geshicode .coMULTI {color:#ff0000; font-style:italic;} .cpp.geshicode .es0 {color:#000099; font-weight:bold;} .cpp.geshicode .es1 {color:#000099; font-weight:bold;} .cpp.geshicode .es2 {color:#660099; font-weight:bold;} .cpp.geshicode .es3 {color:#660099; font-weight:bold;} .cpp.geshicode .es4 {color:#660099; font-weight:bold;} .cpp.geshicode .es5 {color:#006699; font-weight:bold;} .cpp.geshicode .br0 {color:#008000;} .cpp.geshicode .sy0 {color:#008000;} .cpp.geshicode .sy1 {color:#000080;} .cpp.geshicode .sy2 {color:#000040;} .cpp.geshicode .sy3 {color:#000040;} .cpp.geshicode .sy4 {color:#008080;} .cpp.geshicode .st0 {color:#ff0000;} .cpp.geshicode .nu0 {color:#0000dd;} .cpp.geshicode .nu6 {color:#208080;} .cpp.geshicode .nu8 {color:#208080;} .cpp.geshicode .nu12 {color:#208080;} .cpp.geshicode .nu16 {color:#800080;} .cpp.geshicode .nu17 {color:#800080;} .cpp.geshicode .nu18 {color:#800080;} .cpp.geshicode .nu19 {color:#800080;} .cpp.geshicode .me1 {color:#007788;} .cpp.geshicode .me2 {color:#007788;} .cpp.geshicode span.xtra {display:block;} cppcheck-1.61/htdocs/site/css/normalize.css000066400000000000000000000165641217722632100207720ustar00rootroot00000000000000/*! normalize.css v2.1.2 | MIT License | git.io/normalize */ /* ========================================================================== HTML5 display definitions ========================================================================== */ /** * Correct `block` display not defined in IE 8/9. */ article, aside, details, figcaption, figure, footer, header, hgroup, main, nav, section, summary { display: block; } /** * Correct `inline-block` display not defined in IE 8/9. */ audio, canvas, video { display: inline-block; } /** * Prevent modern browsers from displaying `audio` without controls. * Remove excess height in iOS 5 devices. */ audio:not([controls]) { display: none; height: 0; } /** * Address `[hidden]` styling not present in IE 8/9. * Hide the `template` element in IE, Safari, and Firefox < 22. */ [hidden], template { display: none; } /* ========================================================================== Base ========================================================================== */ /** * 1. Set default font family to sans-serif. * 2. Prevent iOS text size adjust after orientation change, without disabling * user zoom. */ html { font-family: sans-serif; /* 1 */ -ms-text-size-adjust: 100%; /* 2 */ -webkit-text-size-adjust: 100%; /* 2 */ } /** * Remove default margin. */ body { margin: 0; } /* ========================================================================== Links ========================================================================== */ /** * Remove the gray background color from active links in IE 10. */ a { background: transparent; } /** * Address `outline` inconsistency between Chrome and other browsers. */ a:focus { outline: thin dotted; } /** * Improve readability when focused and also mouse hovered in all browsers. */ a:active, a:hover { outline: 0; } /* ========================================================================== Typography ========================================================================== */ /** * Address variable `h1` font-size and margin within `section` and `article` * contexts in Firefox 4+, Safari 5, and Chrome. */ h1 { font-size: 2em; margin: 0.67em 0; } /** * Address styling not present in IE 8/9, Safari 5, and Chrome. */ abbr[title] { border-bottom: 1px dotted; } /** * Address style set to `bolder` in Firefox 4+, Safari 5, and Chrome. */ b, strong { font-weight: bold; } /** * Address styling not present in Safari 5 and Chrome. */ dfn { font-style: italic; } /** * Address differences between Firefox and other browsers. */ hr { -moz-box-sizing: content-box; box-sizing: content-box; height: 0; } /** * Address styling not present in IE 8/9. */ mark { background: #ff0; color: #000; } /** * Correct font family set oddly in Safari 5 and Chrome. */ code, kbd, pre, samp { font-family: monospace, serif; font-size: 1em; } /** * Improve readability of pre-formatted text in all browsers. */ pre { white-space: pre-wrap; } /** * Set consistent quote types. */ q { quotes: "\201C" "\201D" "\2018" "\2019"; } /** * Address inconsistent and variable font size in all browsers. */ small { font-size: 80%; } /** * Prevent `sub` and `sup` affecting `line-height` in all browsers. */ sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } sup { top: -0.5em; } sub { bottom: -0.25em; } /* ========================================================================== Embedded content ========================================================================== */ /** * Remove border when inside `a` element in IE 8/9. */ img { border: 0; } /** * Correct overflow displayed oddly in IE 9. */ svg:not(:root) { overflow: hidden; } /* ========================================================================== Figures ========================================================================== */ /** * Address margin not present in IE 8/9 and Safari 5. */ figure { margin: 0; } /* ========================================================================== Forms ========================================================================== */ /** * Define consistent border, margin, and padding. */ fieldset { border: 1px solid #c0c0c0; margin: 0 2px; padding: 0.35em 0.625em 0.75em; } /** * 1. Correct `color` not being inherited in IE 8/9. * 2. Remove padding so people aren't caught out if they zero out fieldsets. */ legend { border: 0; /* 1 */ padding: 0; /* 2 */ } /** * 1. Correct font family not being inherited in all browsers. * 2. Correct font size not being inherited in all browsers. * 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome. */ button, input, select, textarea { font-family: inherit; /* 1 */ font-size: 100%; /* 2 */ margin: 0; /* 3 */ } /** * Address Firefox 4+ setting `line-height` on `input` using `!important` in * the UA stylesheet. */ button, input { line-height: normal; } /** * Address inconsistent `text-transform` inheritance for `button` and `select`. * All other form control elements do not inherit `text-transform` values. * Correct `button` style inheritance in Chrome, Safari 5+, and IE 8+. * Correct `select` style inheritance in Firefox 4+ and Opera. */ button, select { text-transform: none; } /** * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` * and `video` controls. * 2. Correct inability to style clickable `input` types in iOS. * 3. Improve usability and consistency of cursor style between image-type * `input` and others. */ button, html input[type="button"], /* 1 */ input[type="reset"], input[type="submit"] { -webkit-appearance: button; /* 2 */ cursor: pointer; /* 3 */ } /** * Re-set default cursor for disabled elements. */ button[disabled], html input[disabled] { cursor: default; } /** * 1. Address box sizing set to `content-box` in IE 8/9. * 2. Remove excess padding in IE 8/9. */ input[type="checkbox"], input[type="radio"] { box-sizing: border-box; /* 1 */ padding: 0; /* 2 */ } /** * 1. Address `appearance` set to `searchfield` in Safari 5 and Chrome. * 2. Address `box-sizing` set to `border-box` in Safari 5 and Chrome * (include `-moz` to future-proof). */ input[type="search"] { -webkit-appearance: textfield; /* 1 */ -moz-box-sizing: content-box; -webkit-box-sizing: content-box; /* 2 */ box-sizing: content-box; } /** * Remove inner padding and search cancel button in Safari 5 and Chrome * on OS X. */ input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { -webkit-appearance: none; } /** * Remove inner padding and border in Firefox 4+. */ button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; } /** * 1. Remove default vertical scrollbar in IE 8/9. * 2. Improve readability and alignment in all browsers. */ textarea { overflow: auto; /* 1 */ vertical-align: top; /* 2 */ } /* ========================================================================== Tables ========================================================================== */ /** * Remove most spacing between table cells. */ table { border-collapse: collapse; border-spacing: 0; } cppcheck-1.61/htdocs/site/css/pack.css000066400000000000000000000134271217722632100177030ustar00rootroot00000000000000body{margin:0;padding:0;font:16px Calibri,Verdana,sans-serif;color:#000;background-color:#eee}dt{font-weight:700}a:hover{-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}a:link,a:visited{color:#036;text-decoration:underline}a:active,a:focus,a:hover,a:visited{color:#369}#header{color:#69c;background-color:#036}#header a{color:inherit;text-decoration:none}#header h1{margin:0;padding:0;font-family:Orbitron}#header p{margin:0;padding:0;font-size:larger}#tabs{color:#eee;background-color:#369;border-top:1px solid #000;border-bottom:1px solid #000}#tabs ul{margin:0;padding:0;list-style-type:none;font-size:larger}#tabs li{display:inline;padding:0 .5em;border-right:1px solid #000}#tabs li:first-child{padding-left:0}#tabs li:last-child{border:0}#tabs a:link,#tabs a:visited{color:#eee;text-decoration:none}#tabs a:focus,#tabs a:hover,#tabs a:active{color:#fff;text-decoration:underline}#anchors ul{margin:0;padding:.5em 0;list-style-type:none;font-size:smaller}#anchors li{display:inline;padding:0 .5em}#anchors li:first-child{padding-left:0}#anchors .wrap{padding:0}.wrap{width:50em;margin:0 auto;padding:.5em;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}.rssfeeditems em{margin-left:.5em;color:#888;font-size:smaller}a.author:link,a.author:visited,a.author:link:hover,a.author:visited:hover,a.author:focus,a.author:active{color:#888}a.downloadnow{display:block;width:12em;margin:0;padding:5px;text-align:center;text-decoration:none;color:#fff;background-color:#060;border:1px solid #003D00;-webkit-border-radius:.5em;-khtml-border-radius:.5em;-moz-border-radius:.5em;border-radius:.5em;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box}a.downloadnow:focus,a.downloadnow:hover{background-color:#090}.downButtonText{display:block;font-size:larger;font-weight:700}.downButtonVersion{display:block;font-size:smaller}.cmd{padding:.5em;background-color:#f7f7f7;border:1px solid silver;border-left:10px solid silver}@media print{#header{color:#000;border-bottom:1px solid #000}#tabs{display:none}#resultsTable th,#resultsTable td{background-color:#fff;border:1px solid #000}}.geshicode{padding:.5em;background:#f7f7f7;border:1px solid #e2e2e2}#resultsTable{border-collapse:collapse}#resultsTable th{padding:.25em;text-align:left;background:#e2e2e2;border:1px solid #e2e2e2}#resultsTable td{padding:.25em;background:#f7f7f7;border:1px solid #e2e2e2}#resultsTable .center{text-align:center}.maxChars{margin-left:2em;color:#888;font-size:smaller;font-style:italic}.cpp.geshicode .de1,.cpp.geshicode .de2{font:400 normal 1em/1.2em monospace;margin:0;padding:0;background:0;vertical-align:top}.cpp.geshicode{font-family:monospace}.cpp.geshicode .imp{font-weight:700;color:red}.cpp.geshicode li,.cpp.geshicode .li1{font-weight:400;vertical-align:top}.cpp.geshicode .ln{width:1px;text-align:right;margin:0;padding:0 2px;vertical-align:top;color:#999}.cpp.geshicode .kw1{color:#00f}.cpp.geshicode .kw2{color:#00f}.cpp.geshicode .kw3{color:#00d}.cpp.geshicode .kw4{color:#00f}.cpp.geshicode .co1{color:#666}.cpp.geshicode .co2{color:#390}.cpp.geshicode .coMULTI{color:red;font-style:italic}.cpp.geshicode .es0{color:#009;font-weight:700}.cpp.geshicode .es1{color:#009;font-weight:700}.cpp.geshicode .es2{color:#609;font-weight:700}.cpp.geshicode .es3{color:#609;font-weight:700}.cpp.geshicode .es4{color:#609;font-weight:700}.cpp.geshicode .es5{color:#069;font-weight:700}.cpp.geshicode .br0{color:green}.cpp.geshicode .sy0{color:green}.cpp.geshicode .sy1{color:navy}.cpp.geshicode .sy2{color:#000040}.cpp.geshicode .sy3{color:#000040}.cpp.geshicode .sy4{color:teal}.cpp.geshicode .st0{color:red}.cpp.geshicode .nu0{color:#00d}.cpp.geshicode .nu6{color:#208080}.cpp.geshicode .nu8{color:#208080}.cpp.geshicode .nu12{color:#208080}.cpp.geshicode .nu16{color:purple}.cpp.geshicode .nu17{color:purple}.cpp.geshicode .nu18{color:purple}.cpp.geshicode .nu19{color:purple}.cpp.geshicode .me1{color:#078}.cpp.geshicode .me2{color:#078}.cpp.geshicode span.xtra{display:block}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,video{display:inline-block}audio:not([controls]){display:none;height:0}[hidden],template{display:none}html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}a{background:transparent}a:focus{outline:thin dotted}a:active,a:hover{outline:0}h1{font-size:2em;margin:.67em 0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}mark{background:#ff0;color:#000}code,kbd,pre,samp{font-family:monospace,serif;font-size:1em}pre{white-space:pre-wrap}q{quotes:"\201C" "\201D" "\2018" "\2019"}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:0}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}button,input{line-height:normal}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}textarea{overflow:auto;vertical-align:top}table{border-collapse:collapse;border-spacing:0}cppcheck-1.61/htdocs/site/geshi/000077500000000000000000000000001217722632100165535ustar00rootroot00000000000000cppcheck-1.61/htdocs/site/geshi/geshi.php000066400000000000000000006174401217722632100203770ustar00rootroot00000000000000, Benny Baumann * @copyright (C) 2004 - 2007 Nigel McNie, (C) 2007 - 2008 Benny Baumann * @license http://gnu.org/copyleft/gpl.html GNU GPL * */ // // GeSHi Constants // You should use these constant names in your programs instead of // their values - you never know when a value may change in a future // version // /** The version of this GeSHi file */ define('GESHI_VERSION', '1.0.8.11'); // Define the root directory for the GeSHi code tree if (!defined('GESHI_ROOT')) { /** The root directory for GeSHi */ define('GESHI_ROOT', dirname(__FILE__) . DIRECTORY_SEPARATOR); } /** The language file directory for GeSHi @access private */ define('GESHI_LANG_ROOT', GESHI_ROOT . 'geshi' . DIRECTORY_SEPARATOR); // Define if GeSHi should be paranoid about security if (!defined('GESHI_SECURITY_PARANOID')) { /** Tells GeSHi to be paranoid about security settings */ define('GESHI_SECURITY_PARANOID', false); } // Line numbers - use with enable_line_numbers() /** Use no line numbers when building the result */ define('GESHI_NO_LINE_NUMBERS', 0); /** Use normal line numbers when building the result */ define('GESHI_NORMAL_LINE_NUMBERS', 1); /** Use fancy line numbers when building the result */ define('GESHI_FANCY_LINE_NUMBERS', 2); // Container HTML type /** Use nothing to surround the source */ define('GESHI_HEADER_NONE', 0); /** Use a "div" to surround the source */ define('GESHI_HEADER_DIV', 1); /** Use a "pre" to surround the source */ define('GESHI_HEADER_PRE', 2); /** Use a pre to wrap lines when line numbers are enabled or to wrap the whole code. */ define('GESHI_HEADER_PRE_VALID', 3); /** * Use a "table" to surround the source: * * * * * *
    $header
    $linenumbers
    $code>
    $footer
    * * this is essentially only a workaround for Firefox, see sf#1651996 or take a look at * https://bugzilla.mozilla.org/show_bug.cgi?id=365805 * @note when linenumbers are disabled this is essentially the same as GESHI_HEADER_PRE */ define('GESHI_HEADER_PRE_TABLE', 4); // Capatalisation constants /** Lowercase keywords found */ define('GESHI_CAPS_NO_CHANGE', 0); /** Uppercase keywords found */ define('GESHI_CAPS_UPPER', 1); /** Leave keywords found as the case that they are */ define('GESHI_CAPS_LOWER', 2); // Link style constants /** Links in the source in the :link state */ define('GESHI_LINK', 0); /** Links in the source in the :hover state */ define('GESHI_HOVER', 1); /** Links in the source in the :active state */ define('GESHI_ACTIVE', 2); /** Links in the source in the :visited state */ define('GESHI_VISITED', 3); // Important string starter/finisher // Note that if you change these, they should be as-is: i.e., don't // write them as if they had been run through htmlentities() /** The starter for important parts of the source */ define('GESHI_START_IMPORTANT', ''); /** The ender for important parts of the source */ define('GESHI_END_IMPORTANT', ''); /**#@+ * @access private */ // When strict mode applies for a language /** Strict mode never applies (this is the most common) */ define('GESHI_NEVER', 0); /** Strict mode *might* apply, and can be enabled or disabled by {@link GeSHi->enable_strict_mode()} */ define('GESHI_MAYBE', 1); /** Strict mode always applies */ define('GESHI_ALWAYS', 2); // Advanced regexp handling constants, used in language files /** The key of the regex array defining what to search for */ define('GESHI_SEARCH', 0); /** The key of the regex array defining what bracket group in a matched search to use as a replacement */ define('GESHI_REPLACE', 1); /** The key of the regex array defining any modifiers to the regular expression */ define('GESHI_MODIFIERS', 2); /** The key of the regex array defining what bracket group in a matched search to put before the replacement */ define('GESHI_BEFORE', 3); /** The key of the regex array defining what bracket group in a matched search to put after the replacement */ define('GESHI_AFTER', 4); /** The key of the regex array defining a custom keyword to use for this regexp's html tag class */ define('GESHI_CLASS', 5); /** Used in language files to mark comments */ define('GESHI_COMMENTS', 0); /** Used to work around missing PHP features **/ define('GESHI_PHP_PRE_433', !(version_compare(PHP_VERSION, '4.3.3') === 1)); /** make sure we can call stripos **/ if (!function_exists('stripos')) { // the offset param of preg_match is not supported below PHP 4.3.3 if (GESHI_PHP_PRE_433) { /** * @ignore */ function stripos($haystack, $needle, $offset = null) { if (!is_null($offset)) { $haystack = substr($haystack, $offset); } if (preg_match('/'. preg_quote($needle, '/') . '/', $haystack, $match, PREG_OFFSET_CAPTURE)) { return $match[0][1]; } return false; } } else { /** * @ignore */ function stripos($haystack, $needle, $offset = null) { if (preg_match('/'. preg_quote($needle, '/') . '/', $haystack, $match, PREG_OFFSET_CAPTURE, $offset)) { return $match[0][1]; } return false; } } } /** some old PHP / PCRE subpatterns only support up to xxx subpatterns in regular expressions. Set this to false if your PCRE lib is up to date @see GeSHi->optimize_regexp_list() **/ define('GESHI_MAX_PCRE_SUBPATTERNS', 500); /** it's also important not to generate too long regular expressions be generous here... but keep in mind, that when reaching this limit we still have to close open patterns. 12k should do just fine on a 16k limit. @see GeSHi->optimize_regexp_list() **/ define('GESHI_MAX_PCRE_LENGTH', 12288); //Number format specification /** Basic number format for integers */ define('GESHI_NUMBER_INT_BASIC', 1); //Default integers \d+ /** Enhanced number format for integers like seen in C */ define('GESHI_NUMBER_INT_CSTYLE', 2); //Default C-Style \d+[lL]? /** Number format to highlight binary numbers with a suffix "b" */ define('GESHI_NUMBER_BIN_SUFFIX', 16); //[01]+[bB] /** Number format to highlight binary numbers with a prefix % */ define('GESHI_NUMBER_BIN_PREFIX_PERCENT', 32); //%[01]+ /** Number format to highlight binary numbers with a prefix 0b (C) */ define('GESHI_NUMBER_BIN_PREFIX_0B', 64); //0b[01]+ /** Number format to highlight octal numbers with a leading zero */ define('GESHI_NUMBER_OCT_PREFIX', 256); //0[0-7]+ /** Number format to highlight octal numbers with a prefix 0o (logtalk) */ define('GESHI_NUMBER_OCT_PREFIX_0O', 512); //0[0-7]+ /** Number format to highlight octal numbers with a leading @ (Used in HiSofts Devpac series). */ define('GESHI_NUMBER_OCT_PREFIX_AT', 1024); //@[0-7]+ /** Number format to highlight octal numbers with a suffix of o */ define('GESHI_NUMBER_OCT_SUFFIX', 2048); //[0-7]+[oO] /** Number format to highlight hex numbers with a prefix 0x */ define('GESHI_NUMBER_HEX_PREFIX', 4096); //0x[0-9a-fA-F]+ /** Number format to highlight hex numbers with a prefix $ */ define('GESHI_NUMBER_HEX_PREFIX_DOLLAR', 8192); //$[0-9a-fA-F]+ /** Number format to highlight hex numbers with a suffix of h */ define('GESHI_NUMBER_HEX_SUFFIX', 16384); //[0-9][0-9a-fA-F]*h /** Number format to highlight floating-point numbers without support for scientific notation */ define('GESHI_NUMBER_FLT_NONSCI', 65536); //\d+\.\d+ /** Number format to highlight floating-point numbers without support for scientific notation */ define('GESHI_NUMBER_FLT_NONSCI_F', 131072); //\d+(\.\d+)?f /** Number format to highlight floating-point numbers with support for scientific notation (E) and optional leading zero */ define('GESHI_NUMBER_FLT_SCI_SHORT', 262144); //\.\d+e\d+ /** Number format to highlight floating-point numbers with support for scientific notation (E) and required leading digit */ define('GESHI_NUMBER_FLT_SCI_ZERO', 524288); //\d+(\.\d+)?e\d+ //Custom formats are passed by RX array // Error detection - use these to analyse faults /** No sourcecode to highlight was specified * @deprecated */ define('GESHI_ERROR_NO_INPUT', 1); /** The language specified does not exist */ define('GESHI_ERROR_NO_SUCH_LANG', 2); /** GeSHi could not open a file for reading (generally a language file) */ define('GESHI_ERROR_FILE_NOT_READABLE', 3); /** The header type passed to {@link GeSHi->set_header_type()} was invalid */ define('GESHI_ERROR_INVALID_HEADER_TYPE', 4); /** The line number type passed to {@link GeSHi->enable_line_numbers()} was invalid */ define('GESHI_ERROR_INVALID_LINE_NUMBER_TYPE', 5); /**#@-*/ /** * The GeSHi Class. * * Please refer to the documentation for GeSHi 1.0.X that is available * at http://qbnz.com/highlighter/documentation.php for more information * about how to use this class. * * @package geshi * @author Nigel McNie , Benny Baumann * @copyright (C) 2004 - 2007 Nigel McNie, (C) 2007 - 2008 Benny Baumann */ class GeSHi { /**#@+ * @access private */ /** * The source code to highlight * @var string */ var $source = ''; /** * The language to use when highlighting * @var string */ var $language = ''; /** * The data for the language used * @var array */ var $language_data = array(); /** * The path to the language files * @var string */ var $language_path = GESHI_LANG_ROOT; /** * The error message associated with an error * @var string * @todo check err reporting works */ var $error = false; /** * Possible error messages * @var array */ var $error_messages = array( GESHI_ERROR_NO_SUCH_LANG => 'GeSHi could not find the language {LANGUAGE} (using path {PATH})', GESHI_ERROR_FILE_NOT_READABLE => 'The file specified for load_from_file was not readable', GESHI_ERROR_INVALID_HEADER_TYPE => 'The header type specified is invalid', GESHI_ERROR_INVALID_LINE_NUMBER_TYPE => 'The line number type specified is invalid' ); /** * Whether highlighting is strict or not * @var boolean */ var $strict_mode = false; /** * Whether to use CSS classes in output * @var boolean */ var $use_classes = false; /** * The type of header to use. Can be one of the following * values: * * - GESHI_HEADER_PRE: Source is outputted in a "pre" HTML element. * - GESHI_HEADER_DIV: Source is outputted in a "div" HTML element. * - GESHI_HEADER_NONE: No header is outputted. * * @var int */ var $header_type = GESHI_HEADER_PRE; /** * Array of permissions for which lexics should be highlighted * @var array */ var $lexic_permissions = array( 'KEYWORDS' => array(), 'COMMENTS' => array('MULTI' => true), 'REGEXPS' => array(), 'ESCAPE_CHAR' => true, 'BRACKETS' => true, 'SYMBOLS' => false, 'STRINGS' => true, 'NUMBERS' => true, 'METHODS' => true, 'SCRIPT' => true ); /** * The time it took to parse the code * @var double */ var $time = 0; /** * The content of the header block * @var string */ var $header_content = ''; /** * The content of the footer block * @var string */ var $footer_content = ''; /** * The style of the header block * @var string */ var $header_content_style = ''; /** * The style of the footer block * @var string */ var $footer_content_style = ''; /** * Tells if a block around the highlighted source should be forced * if not using line numbering * @var boolean */ var $force_code_block = false; /** * The styles for hyperlinks in the code * @var array */ var $link_styles = array(); /** * Whether important blocks should be recognised or not * @var boolean * @deprecated * @todo REMOVE THIS FUNCTIONALITY! */ var $enable_important_blocks = false; /** * Styles for important parts of the code * @var string * @deprecated * @todo As above - rethink the whole idea of important blocks as it is buggy and * will be hard to implement in 1.2 */ var $important_styles = 'font-weight: bold; color: red;'; // Styles for important parts of the code /** * Whether CSS IDs should be added to the code * @var boolean */ var $add_ids = false; /** * Lines that should be highlighted extra * @var array */ var $highlight_extra_lines = array(); /** * Styles of lines that should be highlighted extra * @var array */ var $highlight_extra_lines_styles = array(); /** * Styles of extra-highlighted lines * @var string */ var $highlight_extra_lines_style = 'background-color: #ffc;'; /** * The line ending * If null, nl2br() will be used on the result string. * Otherwise, all instances of \n will be replaced with $line_ending * @var string */ var $line_ending = null; /** * Number at which line numbers should start at * @var int */ var $line_numbers_start = 1; /** * The overall style for this code block * @var string */ var $overall_style = 'font-family:monospace;'; /** * The style for the actual code * @var string */ var $code_style = 'font: normal normal 1em/1.2em monospace; margin:0; padding:0; background:none; vertical-align:top;'; /** * The overall class for this code block * @var string */ var $overall_class = ''; /** * The overall ID for this code block * @var string */ var $overall_id = ''; /** * Line number styles * @var string */ var $line_style1 = 'font-weight: normal; vertical-align:top;'; /** * Line number styles for fancy lines * @var string */ var $line_style2 = 'font-weight: bold; vertical-align:top;'; /** * Style for line numbers when GESHI_HEADER_PRE_TABLE is chosen * @var string */ var $table_linenumber_style = 'width:1px;text-align:right;margin:0;padding:0 2px;vertical-align:top;'; /** * Flag for how line numbers are displayed * @var boolean */ var $line_numbers = GESHI_NO_LINE_NUMBERS; /** * Flag to decide if multi line spans are allowed. Set it to false to make sure * each tag is closed before and reopened after each linefeed. * @var boolean */ var $allow_multiline_span = true; /** * The "nth" value for fancy line highlighting * @var int */ var $line_nth_row = 0; /** * The size of tab stops * @var int */ var $tab_width = 8; /** * Should we use language-defined tab stop widths? * @var int */ var $use_language_tab_width = false; /** * Default target for keyword links * @var string */ var $link_target = ''; /** * The encoding to use for entity encoding * NOTE: Used with Escape Char Sequences to fix UTF-8 handling (cf. SF#2037598) * @var string */ var $encoding = 'utf-8'; /** * Should keywords be linked? * @var boolean */ var $keyword_links = true; /** * Currently loaded language file * @var string * @since 1.0.7.22 */ var $loaded_language = ''; /** * Wether the caches needed for parsing are built or not * * @var bool * @since 1.0.8 */ var $parse_cache_built = false; /** * Work around for Suhosin Patch with disabled /e modifier * * Note from suhosins author in config file: *
    * The /e modifier inside preg_replace() allows code execution. * Often it is the cause for remote code execution exploits. It is wise to * deactivate this feature and test where in the application it is used. * The developer using the /e modifier should be made aware that he should * use preg_replace_callback() instead *
    * * @var array * @since 1.0.8 */ var $_kw_replace_group = 0; var $_rx_key = 0; /** * some "callback parameters" for handle_multiline_regexps * * @since 1.0.8 * @access private * @var string */ var $_hmr_before = ''; var $_hmr_replace = ''; var $_hmr_after = ''; var $_hmr_key = 0; /**#@-*/ /** * Creates a new GeSHi object, with source and language * * @param string The source code to highlight * @param string The language to highlight the source with * @param string The path to the language file directory. This * is deprecated! I've backported the auto path * detection from the 1.1.X dev branch, so now it * should be automatically set correctly. If you have * renamed the language directory however, you will * still need to set the path using this parameter or * {@link GeSHi->set_language_path()} * @since 1.0.0 */ function GeSHi($source = '', $language = '', $path = '') { if (!empty($source)) { $this->set_source($source); } if (!empty($language)) { $this->set_language($language); } $this->set_language_path($path); } /** * Returns the version of GeSHi * * @return string * @since 1 0.8.11 */ function get_version() { return GESHI_VERSION; } /** * Returns an error message associated with the last GeSHi operation, * or false if no error has occured * * @return string|false An error message if there has been an error, else false * @since 1.0.0 */ function error() { if ($this->error) { //Put some template variables for debugging here ... $debug_tpl_vars = array( '{LANGUAGE}' => $this->language, '{PATH}' => $this->language_path ); $msg = str_replace( array_keys($debug_tpl_vars), array_values($debug_tpl_vars), $this->error_messages[$this->error]); return "
    GeSHi Error: $msg (code {$this->error})
    "; } return false; } /** * Gets a human-readable language name (thanks to Simon Patterson * for the idea :)) * * @return string The name for the current language * @since 1.0.2 */ function get_language_name() { if (GESHI_ERROR_NO_SUCH_LANG == $this->error) { return $this->language_data['LANG_NAME'] . ' (Unknown Language)'; } return $this->language_data['LANG_NAME']; } /** * Sets the source code for this object * * @param string The source code to highlight * @since 1.0.0 */ function set_source($source) { $this->source = $source; $this->highlight_extra_lines = array(); } /** * Sets the language for this object * * @note since 1.0.8 this function won't reset language-settings by default anymore! * if you need this set $force_reset = true * * @param string The name of the language to use * @since 1.0.0 */ function set_language($language, $force_reset = false) { if ($force_reset) { $this->loaded_language = false; } //Clean up the language name to prevent malicious code injection $language = preg_replace('#[^a-zA-Z0-9\-_]#', '', $language); $language = strtolower($language); //Retreive the full filename $file_name = $this->language_path . $language . '.php'; if ($file_name == $this->loaded_language) { // this language is already loaded! return; } $this->language = $language; $this->error = false; $this->strict_mode = GESHI_NEVER; //Check if we can read the desired file if (!is_readable($file_name)) { $this->error = GESHI_ERROR_NO_SUCH_LANG; return; } // Load the language for parsing $this->load_language($file_name); } /** * Sets the path to the directory containing the language files. Note * that this path is relative to the directory of the script that included * geshi.php, NOT geshi.php itself. * * @param string The path to the language directory * @since 1.0.0 * @deprecated The path to the language files should now be automatically * detected, so this method should no longer be needed. The * 1.1.X branch handles manual setting of the path differently * so this method will disappear in 1.2.0. */ function set_language_path($path) { if(strpos($path,':')) { //Security Fix to prevent external directories using fopen wrappers. if(DIRECTORY_SEPARATOR == "\\") { if(!preg_match('#^[a-zA-Z]:#', $path) || false !== strpos($path, ':', 2)) { return; } } else { return; } } if(preg_match('#[^/a-zA-Z0-9_\.\-\\\s:]#', $path)) { //Security Fix to prevent external directories using fopen wrappers. return; } if(GESHI_SECURITY_PARANOID && false !== strpos($path, '/.')) { //Security Fix to prevent external directories using fopen wrappers. return; } if(GESHI_SECURITY_PARANOID && false !== strpos($path, '..')) { //Security Fix to prevent external directories using fopen wrappers. return; } if ($path) { $this->language_path = ('/' == $path[strlen($path) - 1]) ? $path : $path . '/'; $this->set_language($this->language); // otherwise set_language_path has no effect } } /** * Get supported langs or an associative array lang=>full_name. * @param boolean $longnames * @return array */ function get_supported_languages($full_names=false) { // return array $back = array(); // we walk the lang root $dir = dir($this->language_path); // foreach entry while (false !== ($entry = $dir->read())) { $full_path = $this->language_path.$entry; // Skip all dirs if (is_dir($full_path)) { continue; } // we only want lang.php files if (!preg_match('/^([^.]+)\.php$/', $entry, $matches)) { continue; } // Raw lang name is here $langname = $matches[1]; // We want the fullname too? if ($full_names === true) { if (false !== ($fullname = $this->get_language_fullname($langname))) { $back[$langname] = $fullname; // we go associative } } else { // just store raw langname $back[] = $langname; } } $dir->close(); return $back; } /** * Get full_name for a lang or false. * @param string $language short langname (html4strict for example) * @return mixed */ function get_language_fullname($language) { //Clean up the language name to prevent malicious code injection $language = preg_replace('#[^a-zA-Z0-9\-_]#', '', $language); $language = strtolower($language); // get fullpath-filename for a langname $fullpath = $this->language_path.$language.'.php'; // we need to get contents :S if (false === ($data = file_get_contents($fullpath))) { $this->error = sprintf('Geshi::get_lang_fullname() Unknown Language: %s', $language); return false; } // match the langname if (!preg_match('/\'LANG_NAME\'\s*=>\s*\'((?:[^\']|\\\')+?)\'/', $data, $matches)) { $this->error = sprintf('Geshi::get_lang_fullname(%s): Regex can not detect language', $language); return false; } // return fullname for langname return stripcslashes($matches[1]); } /** * Sets the type of header to be used. * * If GESHI_HEADER_DIV is used, the code is surrounded in a "div".This * means more source code but more control over tab width and line-wrapping. * GESHI_HEADER_PRE means that a "pre" is used - less source, but less * control. Default is GESHI_HEADER_PRE. * * From 1.0.7.2, you can use GESHI_HEADER_NONE to specify that no header code * should be outputted. * * @param int The type of header to be used * @since 1.0.0 */ function set_header_type($type) { //Check if we got a valid header type if (!in_array($type, array(GESHI_HEADER_NONE, GESHI_HEADER_DIV, GESHI_HEADER_PRE, GESHI_HEADER_PRE_VALID, GESHI_HEADER_PRE_TABLE))) { $this->error = GESHI_ERROR_INVALID_HEADER_TYPE; return; } //Set that new header type $this->header_type = $type; } /** * Sets the styles for the code that will be outputted * when this object is parsed. The style should be a * string of valid stylesheet declarations * * @param string The overall style for the outputted code block * @param boolean Whether to merge the styles with the current styles or not * @since 1.0.0 */ function set_overall_style($style, $preserve_defaults = false) { if (!$preserve_defaults) { $this->overall_style = $style; } else { $this->overall_style .= $style; } } /** * Sets the overall classname for this block of code. This * class can then be used in a stylesheet to style this object's * output * * @param string The class name to use for this block of code * @since 1.0.0 */ function set_overall_class($class) { $this->overall_class = $class; } /** * Sets the overall id for this block of code. This id can then * be used in a stylesheet to style this object's output * * @param string The ID to use for this block of code * @since 1.0.0 */ function set_overall_id($id) { $this->overall_id = $id; } /** * Sets whether CSS classes should be used to highlight the source. Default * is off, calling this method with no arguments will turn it on * * @param boolean Whether to turn classes on or not * @since 1.0.0 */ function enable_classes($flag = true) { $this->use_classes = ($flag) ? true : false; } /** * Sets the style for the actual code. This should be a string * containing valid stylesheet declarations. If $preserve_defaults is * true, then styles are merged with the default styles, with the * user defined styles having priority * * Note: Use this method to override any style changes you made to * the line numbers if you are using line numbers, else the line of * code will have the same style as the line number! Consult the * GeSHi documentation for more information about this. * * @param string The style to use for actual code * @param boolean Whether to merge the current styles with the new styles * @since 1.0.2 */ function set_code_style($style, $preserve_defaults = false) { if (!$preserve_defaults) { $this->code_style = $style; } else { $this->code_style .= $style; } } /** * Sets the styles for the line numbers. * * @param string The style for the line numbers that are "normal" * @param string|boolean If a string, this is the style of the line * numbers that are "fancy", otherwise if boolean then this * defines whether the normal styles should be merged with the * new normal styles or not * @param boolean If set, is the flag for whether to merge the "fancy" * styles with the current styles or not * @since 1.0.2 */ function set_line_style($style1, $style2 = '', $preserve_defaults = false) { //Check if we got 2 or three parameters if (is_bool($style2)) { $preserve_defaults = $style2; $style2 = ''; } //Actually set the new styles if (!$preserve_defaults) { $this->line_style1 = $style1; $this->line_style2 = $style2; } else { $this->line_style1 .= $style1; $this->line_style2 .= $style2; } } /** * Sets whether line numbers should be displayed. * * Valid values for the first parameter are: * * - GESHI_NO_LINE_NUMBERS: Line numbers will not be displayed * - GESHI_NORMAL_LINE_NUMBERS: Line numbers will be displayed * - GESHI_FANCY_LINE_NUMBERS: Fancy line numbers will be displayed * * For fancy line numbers, the second parameter is used to signal which lines * are to be fancy. For example, if the value of this parameter is 5 then every * 5th line will be fancy. * * @param int How line numbers should be displayed * @param int Defines which lines are fancy * @since 1.0.0 */ function enable_line_numbers($flag, $nth_row = 5) { if (GESHI_NO_LINE_NUMBERS != $flag && GESHI_NORMAL_LINE_NUMBERS != $flag && GESHI_FANCY_LINE_NUMBERS != $flag) { $this->error = GESHI_ERROR_INVALID_LINE_NUMBER_TYPE; } $this->line_numbers = $flag; $this->line_nth_row = $nth_row; } /** * Sets wether spans and other HTML markup generated by GeSHi can * span over multiple lines or not. Defaults to true to reduce overhead. * Set it to false if you want to manipulate the output or manually display * the code in an ordered list. * * @param boolean Wether multiline spans are allowed or not * @since 1.0.7.22 */ function enable_multiline_span($flag) { $this->allow_multiline_span = (bool) $flag; } /** * Get current setting for multiline spans, see GeSHi->enable_multiline_span(). * * @see enable_multiline_span * @return bool */ function get_multiline_span() { return $this->allow_multiline_span; } /** * Sets the style for a keyword group. If $preserve_defaults is * true, then styles are merged with the default styles, with the * user defined styles having priority * * @param int The key of the keyword group to change the styles of * @param string The style to make the keywords * @param boolean Whether to merge the new styles with the old or just * to overwrite them * @since 1.0.0 */ function set_keyword_group_style($key, $style, $preserve_defaults = false) { //Set the style for this keyword group if (!$preserve_defaults) { $this->language_data['STYLES']['KEYWORDS'][$key] = $style; } else { $this->language_data['STYLES']['KEYWORDS'][$key] .= $style; } //Update the lexic permissions if (!isset($this->lexic_permissions['KEYWORDS'][$key])) { $this->lexic_permissions['KEYWORDS'][$key] = true; } } /** * Turns highlighting on/off for a keyword group * * @param int The key of the keyword group to turn on or off * @param boolean Whether to turn highlighting for that group on or off * @since 1.0.0 */ function set_keyword_group_highlighting($key, $flag = true) { $this->lexic_permissions['KEYWORDS'][$key] = ($flag) ? true : false; } /** * Sets the styles for comment groups. If $preserve_defaults is * true, then styles are merged with the default styles, with the * user defined styles having priority * * @param int The key of the comment group to change the styles of * @param string The style to make the comments * @param boolean Whether to merge the new styles with the old or just * to overwrite them * @since 1.0.0 */ function set_comments_style($key, $style, $preserve_defaults = false) { if (!$preserve_defaults) { $this->language_data['STYLES']['COMMENTS'][$key] = $style; } else { $this->language_data['STYLES']['COMMENTS'][$key] .= $style; } } /** * Turns highlighting on/off for comment groups * * @param int The key of the comment group to turn on or off * @param boolean Whether to turn highlighting for that group on or off * @since 1.0.0 */ function set_comments_highlighting($key, $flag = true) { $this->lexic_permissions['COMMENTS'][$key] = ($flag) ? true : false; } /** * Sets the styles for escaped characters. If $preserve_defaults is * true, then styles are merged with the default styles, with the * user defined styles having priority * * @param string The style to make the escape characters * @param boolean Whether to merge the new styles with the old or just * to overwrite them * @since 1.0.0 */ function set_escape_characters_style($style, $preserve_defaults = false, $group = 0) { if (!$preserve_defaults) { $this->language_data['STYLES']['ESCAPE_CHAR'][$group] = $style; } else { $this->language_data['STYLES']['ESCAPE_CHAR'][$group] .= $style; } } /** * Turns highlighting on/off for escaped characters * * @param boolean Whether to turn highlighting for escape characters on or off * @since 1.0.0 */ function set_escape_characters_highlighting($flag = true) { $this->lexic_permissions['ESCAPE_CHAR'] = ($flag) ? true : false; } /** * Sets the styles for brackets. If $preserve_defaults is * true, then styles are merged with the default styles, with the * user defined styles having priority * * This method is DEPRECATED: use set_symbols_style instead. * This method will be removed in 1.2.X * * @param string The style to make the brackets * @param boolean Whether to merge the new styles with the old or just * to overwrite them * @since 1.0.0 * @deprecated In favour of set_symbols_style */ function set_brackets_style($style, $preserve_defaults = false) { if (!$preserve_defaults) { $this->language_data['STYLES']['BRACKETS'][0] = $style; } else { $this->language_data['STYLES']['BRACKETS'][0] .= $style; } } /** * Turns highlighting on/off for brackets * * This method is DEPRECATED: use set_symbols_highlighting instead. * This method will be remove in 1.2.X * * @param boolean Whether to turn highlighting for brackets on or off * @since 1.0.0 * @deprecated In favour of set_symbols_highlighting */ function set_brackets_highlighting($flag) { $this->lexic_permissions['BRACKETS'] = ($flag) ? true : false; } /** * Sets the styles for symbols. If $preserve_defaults is * true, then styles are merged with the default styles, with the * user defined styles having priority * * @param string The style to make the symbols * @param boolean Whether to merge the new styles with the old or just * to overwrite them * @param int Tells the group of symbols for which style should be set. * @since 1.0.1 */ function set_symbols_style($style, $preserve_defaults = false, $group = 0) { // Update the style of symbols if (!$preserve_defaults) { $this->language_data['STYLES']['SYMBOLS'][$group] = $style; } else { $this->language_data['STYLES']['SYMBOLS'][$group] .= $style; } // For backward compatibility if (0 == $group) { $this->set_brackets_style ($style, $preserve_defaults); } } /** * Turns highlighting on/off for symbols * * @param boolean Whether to turn highlighting for symbols on or off * @since 1.0.0 */ function set_symbols_highlighting($flag) { // Update lexic permissions for this symbol group $this->lexic_permissions['SYMBOLS'] = ($flag) ? true : false; // For backward compatibility $this->set_brackets_highlighting ($flag); } /** * Sets the styles for strings. If $preserve_defaults is * true, then styles are merged with the default styles, with the * user defined styles having priority * * @param string The style to make the escape characters * @param boolean Whether to merge the new styles with the old or just * to overwrite them * @param int Tells the group of strings for which style should be set. * @since 1.0.0 */ function set_strings_style($style, $preserve_defaults = false, $group = 0) { if (!$preserve_defaults) { $this->language_data['STYLES']['STRINGS'][$group] = $style; } else { $this->language_data['STYLES']['STRINGS'][$group] .= $style; } } /** * Turns highlighting on/off for strings * * @param boolean Whether to turn highlighting for strings on or off * @since 1.0.0 */ function set_strings_highlighting($flag) { $this->lexic_permissions['STRINGS'] = ($flag) ? true : false; } /** * Sets the styles for strict code blocks. If $preserve_defaults is * true, then styles are merged with the default styles, with the * user defined styles having priority * * @param string The style to make the script blocks * @param boolean Whether to merge the new styles with the old or just * to overwrite them * @param int Tells the group of script blocks for which style should be set. * @since 1.0.8.4 */ function set_script_style($style, $preserve_defaults = false, $group = 0) { // Update the style of symbols if (!$preserve_defaults) { $this->language_data['STYLES']['SCRIPT'][$group] = $style; } else { $this->language_data['STYLES']['SCRIPT'][$group] .= $style; } } /** * Sets the styles for numbers. If $preserve_defaults is * true, then styles are merged with the default styles, with the * user defined styles having priority * * @param string The style to make the numbers * @param boolean Whether to merge the new styles with the old or just * to overwrite them * @param int Tells the group of numbers for which style should be set. * @since 1.0.0 */ function set_numbers_style($style, $preserve_defaults = false, $group = 0) { if (!$preserve_defaults) { $this->language_data['STYLES']['NUMBERS'][$group] = $style; } else { $this->language_data['STYLES']['NUMBERS'][$group] .= $style; } } /** * Turns highlighting on/off for numbers * * @param boolean Whether to turn highlighting for numbers on or off * @since 1.0.0 */ function set_numbers_highlighting($flag) { $this->lexic_permissions['NUMBERS'] = ($flag) ? true : false; } /** * Sets the styles for methods. $key is a number that references the * appropriate "object splitter" - see the language file for the language * you are highlighting to get this number. If $preserve_defaults is * true, then styles are merged with the default styles, with the * user defined styles having priority * * @param int The key of the object splitter to change the styles of * @param string The style to make the methods * @param boolean Whether to merge the new styles with the old or just * to overwrite them * @since 1.0.0 */ function set_methods_style($key, $style, $preserve_defaults = false) { if (!$preserve_defaults) { $this->language_data['STYLES']['METHODS'][$key] = $style; } else { $this->language_data['STYLES']['METHODS'][$key] .= $style; } } /** * Turns highlighting on/off for methods * * @param boolean Whether to turn highlighting for methods on or off * @since 1.0.0 */ function set_methods_highlighting($flag) { $this->lexic_permissions['METHODS'] = ($flag) ? true : false; } /** * Sets the styles for regexps. If $preserve_defaults is * true, then styles are merged with the default styles, with the * user defined styles having priority * * @param string The style to make the regular expression matches * @param boolean Whether to merge the new styles with the old or just * to overwrite them * @since 1.0.0 */ function set_regexps_style($key, $style, $preserve_defaults = false) { if (!$preserve_defaults) { $this->language_data['STYLES']['REGEXPS'][$key] = $style; } else { $this->language_data['STYLES']['REGEXPS'][$key] .= $style; } } /** * Turns highlighting on/off for regexps * * @param int The key of the regular expression group to turn on or off * @param boolean Whether to turn highlighting for the regular expression group on or off * @since 1.0.0 */ function set_regexps_highlighting($key, $flag) { $this->lexic_permissions['REGEXPS'][$key] = ($flag) ? true : false; } /** * Sets whether a set of keywords are checked for in a case sensitive manner * * @param int The key of the keyword group to change the case sensitivity of * @param boolean Whether to check in a case sensitive manner or not * @since 1.0.0 */ function set_case_sensitivity($key, $case) { $this->language_data['CASE_SENSITIVE'][$key] = ($case) ? true : false; } /** * Sets the case that keywords should use when found. Use the constants: * * - GESHI_CAPS_NO_CHANGE: leave keywords as-is * - GESHI_CAPS_UPPER: convert all keywords to uppercase where found * - GESHI_CAPS_LOWER: convert all keywords to lowercase where found * * @param int A constant specifying what to do with matched keywords * @since 1.0.1 */ function set_case_keywords($case) { if (in_array($case, array( GESHI_CAPS_NO_CHANGE, GESHI_CAPS_UPPER, GESHI_CAPS_LOWER))) { $this->language_data['CASE_KEYWORDS'] = $case; } } /** * Sets how many spaces a tab is substituted for * * Widths below zero are ignored * * @param int The tab width * @since 1.0.0 */ function set_tab_width($width) { $this->tab_width = intval($width); //Check if it fit's the constraints: if ($this->tab_width < 1) { //Return it to the default $this->tab_width = 8; } } /** * Sets whether or not to use tab-stop width specifed by language * * @param boolean Whether to use language-specific tab-stop widths * @since 1.0.7.20 */ function set_use_language_tab_width($use) { $this->use_language_tab_width = (bool) $use; } /** * Returns the tab width to use, based on the current language and user * preference * * @return int Tab width * @since 1.0.7.20 */ function get_real_tab_width() { if (!$this->use_language_tab_width || !isset($this->language_data['TAB_WIDTH'])) { return $this->tab_width; } else { return $this->language_data['TAB_WIDTH']; } } /** * Enables/disables strict highlighting. Default is off, calling this * method without parameters will turn it on. See documentation * for more details on strict mode and where to use it. * * @param boolean Whether to enable strict mode or not * @since 1.0.0 */ function enable_strict_mode($mode = true) { if (GESHI_MAYBE == $this->language_data['STRICT_MODE_APPLIES']) { $this->strict_mode = ($mode) ? GESHI_ALWAYS : GESHI_NEVER; } } /** * Disables all highlighting * * @since 1.0.0 * @todo Rewrite with array traversal * @deprecated In favour of enable_highlighting */ function disable_highlighting() { $this->enable_highlighting(false); } /** * Enables all highlighting * * The optional flag parameter was added in version 1.0.7.21 and can be used * to enable (true) or disable (false) all highlighting. * * @since 1.0.0 * @param boolean A flag specifying whether to enable or disable all highlighting * @todo Rewrite with array traversal */ function enable_highlighting($flag = true) { $flag = $flag ? true : false; foreach ($this->lexic_permissions as $key => $value) { if (is_array($value)) { foreach ($value as $k => $v) { $this->lexic_permissions[$key][$k] = $flag; } } else { $this->lexic_permissions[$key] = $flag; } } // Context blocks $this->enable_important_blocks = $flag; } /** * Given a file extension, this method returns either a valid geshi language * name, or the empty string if it couldn't be found * * @param string The extension to get a language name for * @param array A lookup array to use instead of the default one * @since 1.0.5 * @todo Re-think about how this method works (maybe make it private and/or make it * a extension->lang lookup?) * @todo static? */ function get_language_name_from_extension( $extension, $lookup = array() ) { $extension = strtolower($extension); if ( !is_array($lookup) || empty($lookup)) { $lookup = array( '6502acme' => array( 'a', 's', 'asm', 'inc' ), '6502tasm' => array( 'a', 's', 'asm', 'inc' ), '6502kickass' => array( 'a', 's', 'asm', 'inc' ), '68000devpac' => array( 'a', 's', 'asm', 'inc' ), 'abap' => array('abap'), 'actionscript' => array('as'), 'ada' => array('a', 'ada', 'adb', 'ads'), 'apache' => array('conf'), 'asm' => array('ash', 'asm', 'inc'), 'asp' => array('asp'), 'bash' => array('sh'), 'bf' => array('bf'), 'c' => array('c', 'h'), 'c_mac' => array('c', 'h'), 'caddcl' => array(), 'cadlisp' => array(), 'cdfg' => array('cdfg'), 'cobol' => array('cbl'), 'cpp' => array('cpp', 'hpp', 'C', 'H', 'CPP', 'HPP'), 'csharp' => array('cs'), 'css' => array('css'), 'd' => array('d'), 'delphi' => array('dpk', 'dpr', 'pp', 'pas'), 'diff' => array('diff', 'patch'), 'dos' => array('bat', 'cmd'), 'gdb' => array('kcrash', 'crash', 'bt'), 'gettext' => array('po', 'pot'), 'gml' => array('gml'), 'gnuplot' => array('plt'), 'groovy' => array('groovy'), 'haskell' => array('hs'), 'haxe' => array('hx'), 'html4strict' => array('html', 'htm'), 'ini' => array('ini', 'desktop'), 'java' => array('java'), 'javascript' => array('js'), 'klonec' => array('kl1'), 'klonecpp' => array('klx'), 'latex' => array('tex'), 'lisp' => array('lisp'), 'lua' => array('lua'), 'matlab' => array('m'), 'mpasm' => array(), 'mysql' => array('sql'), 'nsis' => array(), 'objc' => array(), 'oobas' => array(), 'oracle8' => array(), 'oracle10' => array(), 'pascal' => array('pas'), 'perl' => array('pl', 'pm'), 'php' => array('php', 'php5', 'phtml', 'phps'), 'povray' => array('pov'), 'providex' => array('pvc', 'pvx'), 'prolog' => array('pl'), 'python' => array('py'), 'qbasic' => array('bi'), 'reg' => array('reg'), 'ruby' => array('rb'), 'sas' => array('sas'), 'scala' => array('scala'), 'scheme' => array('scm'), 'scilab' => array('sci'), 'smalltalk' => array('st'), 'smarty' => array(), 'tcl' => array('tcl'), 'text' => array('txt'), 'vb' => array('bas'), 'vbnet' => array(), 'visualfoxpro' => array(), 'whitespace' => array('ws'), 'xml' => array('xml', 'svg', 'xrc'), 'z80' => array('z80', 'asm', 'inc') ); } foreach ($lookup as $lang => $extensions) { if (in_array($extension, $extensions)) { return $lang; } } return 'text'; } /** * Given a file name, this method loads its contents in, and attempts * to set the language automatically. An optional lookup table can be * passed for looking up the language name. If not specified a default * table is used * * The language table is in the form *
    array(
         *   'lang_name' => array('extension', 'extension', ...),
         *   'lang_name' ...
         * );
    * * @param string The filename to load the source from * @param array A lookup array to use instead of the default one * @todo Complete rethink of this and above method * @since 1.0.5 */ function load_from_file($file_name, $lookup = array()) { if (is_readable($file_name)) { $this->set_source(file_get_contents($file_name)); $this->set_language($this->get_language_name_from_extension(substr(strrchr($file_name, '.'), 1), $lookup)); } else { $this->error = GESHI_ERROR_FILE_NOT_READABLE; } } /** * Adds a keyword to a keyword group for highlighting * * @param int The key of the keyword group to add the keyword to * @param string The word to add to the keyword group * @since 1.0.0 */ function add_keyword($key, $word) { if (!is_array($this->language_data['KEYWORDS'][$key])) { $this->language_data['KEYWORDS'][$key] = array(); } if (!in_array($word, $this->language_data['KEYWORDS'][$key])) { $this->language_data['KEYWORDS'][$key][] = $word; //NEW in 1.0.8 don't recompile the whole optimized regexp, simply append it if ($this->parse_cache_built) { $subkey = count($this->language_data['CACHED_KEYWORD_LISTS'][$key]) - 1; $this->language_data['CACHED_KEYWORD_LISTS'][$key][$subkey] .= '|' . preg_quote($word, '/'); } } } /** * Removes a keyword from a keyword group * * @param int The key of the keyword group to remove the keyword from * @param string The word to remove from the keyword group * @param bool Wether to automatically recompile the optimized regexp list or not. * Note: if you set this to false and @see GeSHi->parse_code() was already called once, * for the current language, you have to manually call @see GeSHi->optimize_keyword_group() * or the removed keyword will stay in cache and still be highlighted! On the other hand * it might be too expensive to recompile the regexp list for every removal if you want to * remove a lot of keywords. * @since 1.0.0 */ function remove_keyword($key, $word, $recompile = true) { $key_to_remove = array_search($word, $this->language_data['KEYWORDS'][$key]); if ($key_to_remove !== false) { unset($this->language_data['KEYWORDS'][$key][$key_to_remove]); //NEW in 1.0.8, optionally recompile keyword group if ($recompile && $this->parse_cache_built) { $this->optimize_keyword_group($key); } } } /** * Creates a new keyword group * * @param int The key of the keyword group to create * @param string The styles for the keyword group * @param boolean Whether the keyword group is case sensitive ornot * @param array The words to use for the keyword group * @since 1.0.0 */ function add_keyword_group($key, $styles, $case_sensitive = true, $words = array()) { $words = (array) $words; if (empty($words)) { // empty word lists mess up highlighting return false; } //Add the new keyword group internally $this->language_data['KEYWORDS'][$key] = $words; $this->lexic_permissions['KEYWORDS'][$key] = true; $this->language_data['CASE_SENSITIVE'][$key] = $case_sensitive; $this->language_data['STYLES']['KEYWORDS'][$key] = $styles; //NEW in 1.0.8, cache keyword regexp if ($this->parse_cache_built) { $this->optimize_keyword_group($key); } } /** * Removes a keyword group * * @param int The key of the keyword group to remove * @since 1.0.0 */ function remove_keyword_group ($key) { //Remove the keyword group internally unset($this->language_data['KEYWORDS'][$key]); unset($this->lexic_permissions['KEYWORDS'][$key]); unset($this->language_data['CASE_SENSITIVE'][$key]); unset($this->language_data['STYLES']['KEYWORDS'][$key]); //NEW in 1.0.8 unset($this->language_data['CACHED_KEYWORD_LISTS'][$key]); } /** * compile optimized regexp list for keyword group * * @param int The key of the keyword group to compile & optimize * @since 1.0.8 */ function optimize_keyword_group($key) { $this->language_data['CACHED_KEYWORD_LISTS'][$key] = $this->optimize_regexp_list($this->language_data['KEYWORDS'][$key]); $space_as_whitespace = false; if(isset($this->language_data['PARSER_CONTROL'])) { if(isset($this->language_data['PARSER_CONTROL']['KEYWORDS'])) { if(isset($this->language_data['PARSER_CONTROL']['KEYWORDS']['SPACE_AS_WHITESPACE'])) { $space_as_whitespace = $this->language_data['PARSER_CONTROL']['KEYWORDS']['SPACE_AS_WHITESPACE']; } if(isset($this->language_data['PARSER_CONTROL']['KEYWORDS'][$key]['SPACE_AS_WHITESPACE'])) { if(isset($this->language_data['PARSER_CONTROL']['KEYWORDS'][$key]['SPACE_AS_WHITESPACE'])) { $space_as_whitespace = $this->language_data['PARSER_CONTROL']['KEYWORDS'][$key]['SPACE_AS_WHITESPACE']; } } } } if($space_as_whitespace) { foreach($this->language_data['CACHED_KEYWORD_LISTS'][$key] as $rxk => $rxv) { $this->language_data['CACHED_KEYWORD_LISTS'][$key][$rxk] = str_replace(" ", "\\s+", $rxv); } } } /** * Sets the content of the header block * * @param string The content of the header block * @since 1.0.2 */ function set_header_content($content) { $this->header_content = $content; } /** * Sets the content of the footer block * * @param string The content of the footer block * @since 1.0.2 */ function set_footer_content($content) { $this->footer_content = $content; } /** * Sets the style for the header content * * @param string The style for the header content * @since 1.0.2 */ function set_header_content_style($style) { $this->header_content_style = $style; } /** * Sets the style for the footer content * * @param string The style for the footer content * @since 1.0.2 */ function set_footer_content_style($style) { $this->footer_content_style = $style; } /** * Sets whether to force a surrounding block around * the highlighted code or not * * @param boolean Tells whether to enable or disable this feature * @since 1.0.7.20 */ function enable_inner_code_block($flag) { $this->force_code_block = (bool)$flag; } /** * Sets the base URL to be used for keywords * * @param int The key of the keyword group to set the URL for * @param string The URL to set for the group. If {FNAME} is in * the url somewhere, it is replaced by the keyword * that the URL is being made for * @since 1.0.2 */ function set_url_for_keyword_group($group, $url) { $this->language_data['URLS'][$group] = $url; } /** * Sets styles for links in code * * @param int A constant that specifies what state the style is being * set for - e.g. :hover or :visited * @param string The styles to use for that state * @since 1.0.2 */ function set_link_styles($type, $styles) { $this->link_styles[$type] = $styles; } /** * Sets the target for links in code * * @param string The target for links in the code, e.g. _blank * @since 1.0.3 */ function set_link_target($target) { if (!$target) { $this->link_target = ''; } else { $this->link_target = ' target="' . $target . '"'; } } /** * Sets styles for important parts of the code * * @param string The styles to use on important parts of the code * @since 1.0.2 */ function set_important_styles($styles) { $this->important_styles = $styles; } /** * Sets whether context-important blocks are highlighted * * @param boolean Tells whether to enable or disable highlighting of important blocks * @todo REMOVE THIS SHIZ FROM GESHI! * @deprecated * @since 1.0.2 */ function enable_important_blocks($flag) { $this->enable_important_blocks = ( $flag ) ? true : false; } /** * Whether CSS IDs should be added to each line * * @param boolean If true, IDs will be added to each line. * @since 1.0.2 */ function enable_ids($flag = true) { $this->add_ids = ($flag) ? true : false; } /** * Specifies which lines to highlight extra * * The extra style parameter was added in 1.0.7.21. * * @param mixed An array of line numbers to highlight, or just a line * number on its own. * @param string A string specifying the style to use for this line. * If null is specified, the default style is used. * If false is specified, the line will be removed from * special highlighting * @since 1.0.2 * @todo Some data replication here that could be cut down on */ function highlight_lines_extra($lines, $style = null) { if (is_array($lines)) { //Split up the job using single lines at a time foreach ($lines as $line) { $this->highlight_lines_extra($line, $style); } } else { //Mark the line as being highlighted specially $lines = intval($lines); $this->highlight_extra_lines[$lines] = $lines; //Decide on which style to use if ($style === null) { //Check if we should use default style unset($this->highlight_extra_lines_styles[$lines]); } elseif ($style === false) { //Check if to remove this line unset($this->highlight_extra_lines[$lines]); unset($this->highlight_extra_lines_styles[$lines]); } else { $this->highlight_extra_lines_styles[$lines] = $style; } } } /** * Sets the style for extra-highlighted lines * * @param string The style for extra-highlighted lines * @since 1.0.2 */ function set_highlight_lines_extra_style($styles) { $this->highlight_extra_lines_style = $styles; } /** * Sets the line-ending * * @param string The new line-ending * @since 1.0.2 */ function set_line_ending($line_ending) { $this->line_ending = (string)$line_ending; } /** * Sets what number line numbers should start at. Should * be a positive integer, and will be converted to one. * * Warning: Using this method will add the "start" * attribute to the <ol> that is used for line numbering. * This is not valid XHTML strict, so if that's what you * care about then don't use this method. Firefox is getting * support for the CSS method of doing this in 1.1 and Opera * has support for the CSS method, but (of course) IE doesn't * so it's not worth doing it the CSS way yet. * * @param int The number to start line numbers at * @since 1.0.2 */ function start_line_numbers_at($number) { $this->line_numbers_start = abs(intval($number)); } /** * Sets the encoding used for htmlspecialchars(), for international * support. * * NOTE: This is not needed for now because htmlspecialchars() is not * being used (it has a security hole in PHP4 that has not been patched). * Maybe in a future version it may make a return for speed reasons, but * I doubt it. * * @param string The encoding to use for the source * @since 1.0.3 */ function set_encoding($encoding) { if ($encoding) { $this->encoding = strtolower($encoding); } } /** * Turns linking of keywords on or off. * * @param boolean If true, links will be added to keywords * @since 1.0.2 */ function enable_keyword_links($enable = true) { $this->keyword_links = (bool) $enable; } /** * Setup caches needed for styling. This is automatically called in * parse_code() and get_stylesheet() when appropriate. This function helps * stylesheet generators as they rely on some style information being * preprocessed * * @since 1.0.8 * @access private */ function build_style_cache() { //Build the style cache needed to highlight numbers appropriate if($this->lexic_permissions['NUMBERS']) { //First check what way highlighting information for numbers are given if(!isset($this->language_data['NUMBERS'])) { $this->language_data['NUMBERS'] = 0; } if(is_array($this->language_data['NUMBERS'])) { $this->language_data['NUMBERS_CACHE'] = $this->language_data['NUMBERS']; } else { $this->language_data['NUMBERS_CACHE'] = array(); if(!$this->language_data['NUMBERS']) { $this->language_data['NUMBERS'] = GESHI_NUMBER_INT_BASIC | GESHI_NUMBER_FLT_NONSCI; } for($i = 0, $j = $this->language_data['NUMBERS']; $j > 0; ++$i, $j>>=1) { //Rearrange style indices if required ... if(isset($this->language_data['STYLES']['NUMBERS'][1<<$i])) { $this->language_data['STYLES']['NUMBERS'][$i] = $this->language_data['STYLES']['NUMBERS'][1<<$i]; unset($this->language_data['STYLES']['NUMBERS'][1<<$i]); } //Check if this bit is set for highlighting if($j&1) { //So this bit is set ... //Check if it belongs to group 0 or the actual stylegroup if(isset($this->language_data['STYLES']['NUMBERS'][$i])) { $this->language_data['NUMBERS_CACHE'][$i] = 1 << $i; } else { if(!isset($this->language_data['NUMBERS_CACHE'][0])) { $this->language_data['NUMBERS_CACHE'][0] = 0; } $this->language_data['NUMBERS_CACHE'][0] |= 1 << $i; } } } } } } /** * Setup caches needed for parsing. This is automatically called in parse_code() when appropriate. * This function makes stylesheet generators much faster as they do not need these caches. * * @since 1.0.8 * @access private */ function build_parse_cache() { // cache symbol regexp //As this is a costy operation, we avoid doing it for multiple groups ... //Instead we perform it for all symbols at once. // //For this to work, we need to reorganize the data arrays. if ($this->lexic_permissions['SYMBOLS'] && !empty($this->language_data['SYMBOLS'])) { $this->language_data['MULTIPLE_SYMBOL_GROUPS'] = count($this->language_data['STYLES']['SYMBOLS']) > 1; $this->language_data['SYMBOL_DATA'] = array(); $symbol_preg_multi = array(); // multi char symbols $symbol_preg_single = array(); // single char symbols foreach ($this->language_data['SYMBOLS'] as $key => $symbols) { if (is_array($symbols)) { foreach ($symbols as $sym) { $sym = $this->hsc($sym); if (!isset($this->language_data['SYMBOL_DATA'][$sym])) { $this->language_data['SYMBOL_DATA'][$sym] = $key; if (isset($sym[1])) { // multiple chars $symbol_preg_multi[] = preg_quote($sym, '/'); } else { // single char if ($sym == '-') { // don't trigger range out of order error $symbol_preg_single[] = '\-'; } else { $symbol_preg_single[] = preg_quote($sym, '/'); } } } } } else { $symbols = $this->hsc($symbols); if (!isset($this->language_data['SYMBOL_DATA'][$symbols])) { $this->language_data['SYMBOL_DATA'][$symbols] = 0; if (isset($symbols[1])) { // multiple chars $symbol_preg_multi[] = preg_quote($symbols, '/'); } elseif ($symbols == '-') { // don't trigger range out of order error $symbol_preg_single[] = '\-'; } else { // single char $symbol_preg_single[] = preg_quote($symbols, '/'); } } } } //Now we have an array with each possible symbol as the key and the style as the actual data. //This way we can set the correct style just the moment we highlight ... // //Now we need to rewrite our array to get a search string that $symbol_preg = array(); if (!empty($symbol_preg_multi)) { rsort($symbol_preg_multi); $symbol_preg[] = implode('|', $symbol_preg_multi); } if (!empty($symbol_preg_single)) { rsort($symbol_preg_single); $symbol_preg[] = '[' . implode('', $symbol_preg_single) . ']'; } $this->language_data['SYMBOL_SEARCH'] = implode("|", $symbol_preg); } // cache optimized regexp for keyword matching // remove old cache $this->language_data['CACHED_KEYWORD_LISTS'] = array(); foreach (array_keys($this->language_data['KEYWORDS']) as $key) { if (!isset($this->lexic_permissions['KEYWORDS'][$key]) || $this->lexic_permissions['KEYWORDS'][$key]) { $this->optimize_keyword_group($key); } } // brackets if ($this->lexic_permissions['BRACKETS']) { $this->language_data['CACHE_BRACKET_MATCH'] = array('[', ']', '(', ')', '{', '}'); if (!$this->use_classes && isset($this->language_data['STYLES']['BRACKETS'][0])) { $this->language_data['CACHE_BRACKET_REPLACE'] = array( '<| style="' . $this->language_data['STYLES']['BRACKETS'][0] . '">[|>', '<| style="' . $this->language_data['STYLES']['BRACKETS'][0] . '">]|>', '<| style="' . $this->language_data['STYLES']['BRACKETS'][0] . '">(|>', '<| style="' . $this->language_data['STYLES']['BRACKETS'][0] . '">)|>', '<| style="' . $this->language_data['STYLES']['BRACKETS'][0] . '">{|>', '<| style="' . $this->language_data['STYLES']['BRACKETS'][0] . '">}|>', ); } else { $this->language_data['CACHE_BRACKET_REPLACE'] = array( '<| class="br0">[|>', '<| class="br0">]|>', '<| class="br0">(|>', '<| class="br0">)|>', '<| class="br0">{|>', '<| class="br0">}|>', ); } } //Build the parse cache needed to highlight numbers appropriate if($this->lexic_permissions['NUMBERS']) { //Check if the style rearrangements have been processed ... //This also does some preprocessing to check which style groups are useable ... if(!isset($this->language_data['NUMBERS_CACHE'])) { $this->build_style_cache(); } //Number format specification //All this formats are matched case-insensitively! static $numbers_format = array( GESHI_NUMBER_INT_BASIC => '(?:(? '(? '(? '(? '(? '(? '(? '(? '(? '(? '(? '(? '(? '(? '(? '(?language_data['NUMBERS_RXCACHE'] = array(); foreach($this->language_data['NUMBERS_CACHE'] as $key => $rxdata) { if(is_string($rxdata)) { $regexp = $rxdata; } else { //This is a bitfield of number flags to highlight: //Build an array, implode them together and make this the actual RX $rxuse = array(); for($i = 1; $i <= $rxdata; $i<<=1) { if($rxdata & $i) { $rxuse[] = $numbers_format[$i]; } } $regexp = implode("|", $rxuse); } $this->language_data['NUMBERS_RXCACHE'][$key] = "/(?)($regexp)(?!(?:|(?>[^\<]))+>)(?![^<]*>)(?!\|>)(?!\/>)/i"; // } if(!isset($this->language_data['PARSER_CONTROL']['NUMBERS']['PRECHECK_RX'])) { $this->language_data['PARSER_CONTROL']['NUMBERS']['PRECHECK_RX'] = '#\d#'; } } $this->parse_cache_built = true; } /** * Returns the code in $this->source, highlighted and surrounded by the * nessecary HTML. * * This should only be called ONCE, cos it's SLOW! If you want to highlight * the same source multiple times, you're better off doing a whole lot of * str_replaces to replace the <span>s * * @since 1.0.0 */ function parse_code () { // Start the timer $start_time = microtime(); // Replace all newlines to a common form. $code = str_replace("\r\n", "\n", $this->source); $code = str_replace("\r", "\n", $code); // Firstly, if there is an error, we won't highlight if ($this->error) { //Escape the source for output $result = $this->hsc($this->source); //This fix is related to SF#1923020, but has to be applied regardless of //actually highlighting symbols. $result = str_replace(array('', ''), array(';', '|'), $result); // Timing is irrelevant $this->set_time($start_time, $start_time); $this->finalise($result); return $result; } // make sure the parse cache is up2date if (!$this->parse_cache_built) { $this->build_parse_cache(); } // Initialise various stuff $length = strlen($code); $COMMENT_MATCHED = false; $stuff_to_parse = ''; $endresult = ''; // "Important" selections are handled like multiline comments // @todo GET RID OF THIS SHIZ if ($this->enable_important_blocks) { $this->language_data['COMMENT_MULTI'][GESHI_START_IMPORTANT] = GESHI_END_IMPORTANT; } if ($this->strict_mode) { // Break the source into bits. Each bit will be a portion of the code // within script delimiters - for example, HTML between < and > $k = 0; $parts = array(); $matches = array(); $next_match_pointer = null; // we use a copy to unset delimiters on demand (when they are not found) $delim_copy = $this->language_data['SCRIPT_DELIMITERS']; $i = 0; while ($i < $length) { $next_match_pos = $length + 1; // never true foreach ($delim_copy as $dk => $delimiters) { if(is_array($delimiters)) { foreach ($delimiters as $open => $close) { // make sure the cache is setup properly if (!isset($matches[$dk][$open])) { $matches[$dk][$open] = array( 'next_match' => -1, 'dk' => $dk, 'open' => $open, // needed for grouping of adjacent code blocks (see below) 'open_strlen' => strlen($open), 'close' => $close, 'close_strlen' => strlen($close), ); } // Get the next little bit for this opening string if ($matches[$dk][$open]['next_match'] < $i) { // only find the next pos if it was not already cached $open_pos = strpos($code, $open, $i); if ($open_pos === false) { // no match for this delimiter ever unset($delim_copy[$dk][$open]); continue; } $matches[$dk][$open]['next_match'] = $open_pos; } if ($matches[$dk][$open]['next_match'] < $next_match_pos) { //So we got a new match, update the close_pos $matches[$dk][$open]['close_pos'] = strpos($code, $close, $matches[$dk][$open]['next_match']+1); $next_match_pointer =& $matches[$dk][$open]; $next_match_pos = $matches[$dk][$open]['next_match']; } } } else { //So we should match an RegExp as Strict Block ... /** * The value in $delimiters is expected to be an RegExp * containing exactly 2 matching groups: * - Group 1 is the opener * - Group 2 is the closer */ if(!GESHI_PHP_PRE_433 && //Needs proper rewrite to work with PHP >=4.3.0; 4.3.3 is guaranteed to work. preg_match($delimiters, $code, $matches_rx, PREG_OFFSET_CAPTURE, $i)) { //We got a match ... if(isset($matches_rx['start']) && isset($matches_rx['end'])) { $matches[$dk] = array( 'next_match' => $matches_rx['start'][1], 'dk' => $dk, 'close_strlen' => strlen($matches_rx['end'][0]), 'close_pos' => $matches_rx['end'][1], ); } else { $matches[$dk] = array( 'next_match' => $matches_rx[1][1], 'dk' => $dk, 'close_strlen' => strlen($matches_rx[2][0]), 'close_pos' => $matches_rx[2][1], ); } } else { // no match for this delimiter ever unset($delim_copy[$dk]); continue; } if ($matches[$dk]['next_match'] <= $next_match_pos) { $next_match_pointer =& $matches[$dk]; $next_match_pos = $matches[$dk]['next_match']; } } } // non-highlightable text $parts[$k] = array( 1 => substr($code, $i, $next_match_pos - $i) ); ++$k; if ($next_match_pos > $length) { // out of bounds means no next match was found break; } // highlightable code $parts[$k][0] = $next_match_pointer['dk']; //Only combine for non-rx script blocks if(is_array($delim_copy[$next_match_pointer['dk']])) { // group adjacent script blocks, e.g. should be one block, not three! $i = $next_match_pos + $next_match_pointer['open_strlen']; while (true) { $close_pos = strpos($code, $next_match_pointer['close'], $i); if ($close_pos == false) { break; } $i = $close_pos + $next_match_pointer['close_strlen']; if ($i == $length) { break; } if ($code[$i] == $next_match_pointer['open'][0] && ($next_match_pointer['open_strlen'] == 1 || substr($code, $i, $next_match_pointer['open_strlen']) == $next_match_pointer['open'])) { // merge adjacent but make sure we don't merge things like foreach ($matches as $submatches) { foreach ($submatches as $match) { if ($match['next_match'] == $i) { // a different block already matches here! break 3; } } } } else { break; } } } else { $close_pos = $next_match_pointer['close_pos'] + $next_match_pointer['close_strlen']; $i = $close_pos; } if ($close_pos === false) { // no closing delimiter found! $parts[$k][1] = substr($code, $next_match_pos); ++$k; break; } else { $parts[$k][1] = substr($code, $next_match_pos, $i - $next_match_pos); ++$k; } } unset($delim_copy, $next_match_pointer, $next_match_pos, $matches); $num_parts = $k; if ($num_parts == 1 && $this->strict_mode == GESHI_MAYBE) { // when we have only one part, we don't have anything to highlight at all. // if we have a "maybe" strict language, this should be handled as highlightable code $parts = array( 0 => array( 0 => '', 1 => '' ), 1 => array( 0 => null, 1 => $parts[0][1] ) ); $num_parts = 2; } } else { // Not strict mode - simply dump the source into // the array at index 1 (the first highlightable block) $parts = array( 0 => array( 0 => '', 1 => '' ), 1 => array( 0 => null, 1 => $code ) ); $num_parts = 2; } //Unset variables we won't need any longer unset($code); //Preload some repeatedly used values regarding hardquotes ... $hq = isset($this->language_data['HARDQUOTE']) ? $this->language_data['HARDQUOTE'][0] : false; $hq_strlen = strlen($hq); //Preload if line numbers are to be generated afterwards //Added a check if line breaks should be forced even without line numbers, fixes SF#1727398 $check_linenumbers = $this->line_numbers != GESHI_NO_LINE_NUMBERS || !empty($this->highlight_extra_lines) || !$this->allow_multiline_span; //preload the escape char for faster checking ... $escaped_escape_char = $this->hsc($this->language_data['ESCAPE_CHAR']); // this is used for single-line comments $sc_disallowed_before = ""; $sc_disallowed_after = ""; if (isset($this->language_data['PARSER_CONTROL'])) { if (isset($this->language_data['PARSER_CONTROL']['COMMENTS'])) { if (isset($this->language_data['PARSER_CONTROL']['COMMENTS']['DISALLOWED_BEFORE'])) { $sc_disallowed_before = $this->language_data['PARSER_CONTROL']['COMMENTS']['DISALLOWED_BEFORE']; } if (isset($this->language_data['PARSER_CONTROL']['COMMENTS']['DISALLOWED_AFTER'])) { $sc_disallowed_after = $this->language_data['PARSER_CONTROL']['COMMENTS']['DISALLOWED_AFTER']; } } } //Fix for SF#1932083: Multichar Quotemarks unsupported $is_string_starter = array(); if ($this->lexic_permissions['STRINGS']) { foreach ($this->language_data['QUOTEMARKS'] as $quotemark) { if (!isset($is_string_starter[$quotemark[0]])) { $is_string_starter[$quotemark[0]] = (string)$quotemark; } elseif (is_string($is_string_starter[$quotemark[0]])) { $is_string_starter[$quotemark[0]] = array( $is_string_starter[$quotemark[0]], $quotemark); } else { $is_string_starter[$quotemark[0]][] = $quotemark; } } } // Now we go through each part. We know that even-indexed parts are // code that shouldn't be highlighted, and odd-indexed parts should // be highlighted for ($key = 0; $key < $num_parts; ++$key) { $STRICTATTRS = ''; // If this block should be highlighted... if (!($key & 1)) { // Else not a block to highlight $endresult .= $this->hsc($parts[$key][1]); unset($parts[$key]); continue; } $result = ''; $part = $parts[$key][1]; $highlight_part = true; if ($this->strict_mode && !is_null($parts[$key][0])) { // get the class key for this block of code $script_key = $parts[$key][0]; $highlight_part = $this->language_data['HIGHLIGHT_STRICT_BLOCK'][$script_key]; if ($this->language_data['STYLES']['SCRIPT'][$script_key] != '' && $this->lexic_permissions['SCRIPT']) { // Add a span element around the source to // highlight the overall source block if (!$this->use_classes && $this->language_data['STYLES']['SCRIPT'][$script_key] != '') { $attributes = ' style="' . $this->language_data['STYLES']['SCRIPT'][$script_key] . '"'; } else { $attributes = ' class="sc' . $script_key . '"'; } $result .= ""; $STRICTATTRS = $attributes; } } if ($highlight_part) { // Now, highlight the code in this block. This code // is really the engine of GeSHi (along with the method // parse_non_string_part). // cache comment regexps incrementally $next_comment_regexp_key = ''; $next_comment_regexp_pos = -1; $next_comment_multi_pos = -1; $next_comment_single_pos = -1; $comment_regexp_cache_per_key = array(); $comment_multi_cache_per_key = array(); $comment_single_cache_per_key = array(); $next_open_comment_multi = ''; $next_comment_single_key = ''; $escape_regexp_cache_per_key = array(); $next_escape_regexp_key = ''; $next_escape_regexp_pos = -1; $length = strlen($part); for ($i = 0; $i < $length; ++$i) { // Get the next char $char = $part[$i]; $char_len = 1; // update regexp comment cache if needed if (isset($this->language_data['COMMENT_REGEXP']) && $next_comment_regexp_pos < $i) { $next_comment_regexp_pos = $length; foreach ($this->language_data['COMMENT_REGEXP'] as $comment_key => $regexp) { $match_i = false; if (isset($comment_regexp_cache_per_key[$comment_key]) && ($comment_regexp_cache_per_key[$comment_key]['pos'] >= $i || $comment_regexp_cache_per_key[$comment_key]['pos'] === false)) { // we have already matched something if ($comment_regexp_cache_per_key[$comment_key]['pos'] === false) { // this comment is never matched continue; } $match_i = $comment_regexp_cache_per_key[$comment_key]['pos']; } elseif ( //This is to allow use of the offset parameter in preg_match and stay as compatible with older PHP versions as possible (GESHI_PHP_PRE_433 && preg_match($regexp, substr($part, $i), $match, PREG_OFFSET_CAPTURE)) || (!GESHI_PHP_PRE_433 && preg_match($regexp, $part, $match, PREG_OFFSET_CAPTURE, $i)) ) { $match_i = $match[0][1]; if (GESHI_PHP_PRE_433) { $match_i += $i; } $comment_regexp_cache_per_key[$comment_key] = array( 'key' => $comment_key, 'length' => strlen($match[0][0]), 'pos' => $match_i ); } else { $comment_regexp_cache_per_key[$comment_key]['pos'] = false; continue; } if ($match_i !== false && $match_i < $next_comment_regexp_pos) { $next_comment_regexp_pos = $match_i; $next_comment_regexp_key = $comment_key; if ($match_i === $i) { break; } } } } $string_started = false; if (isset($is_string_starter[$char])) { // Possibly the start of a new string ... //Check which starter it was ... //Fix for SF#1932083: Multichar Quotemarks unsupported if (is_array($is_string_starter[$char])) { $char_new = ''; foreach ($is_string_starter[$char] as $testchar) { if ($testchar === substr($part, $i, strlen($testchar)) && strlen($testchar) > strlen($char_new)) { $char_new = $testchar; $string_started = true; } } if ($string_started) { $char = $char_new; } } else { $testchar = $is_string_starter[$char]; if ($testchar === substr($part, $i, strlen($testchar))) { $char = $testchar; $string_started = true; } } $char_len = strlen($char); } if ($string_started && ($i != $next_comment_regexp_pos)) { // Hand out the correct style information for this string $string_key = array_search($char, $this->language_data['QUOTEMARKS']); if (!isset($this->language_data['STYLES']['STRINGS'][$string_key]) || !isset($this->language_data['STYLES']['ESCAPE_CHAR'][$string_key])) { $string_key = 0; } // parse the stuff before this $result .= $this->parse_non_string_part($stuff_to_parse); $stuff_to_parse = ''; if (!$this->use_classes) { $string_attributes = ' style="' . $this->language_data['STYLES']['STRINGS'][$string_key] . '"'; } else { $string_attributes = ' class="st'.$string_key.'"'; } // now handle the string $string = "" . GeSHi::hsc($char); $start = $i + $char_len; $string_open = true; if(empty($this->language_data['ESCAPE_REGEXP'])) { $next_escape_regexp_pos = $length; } do { //Get the regular ending pos ... $close_pos = strpos($part, $char, $start); if(false === $close_pos) { $close_pos = $length; } if($this->lexic_permissions['ESCAPE_CHAR']) { // update escape regexp cache if needed if (isset($this->language_data['ESCAPE_REGEXP']) && $next_escape_regexp_pos < $start) { $next_escape_regexp_pos = $length; foreach ($this->language_data['ESCAPE_REGEXP'] as $escape_key => $regexp) { $match_i = false; if (isset($escape_regexp_cache_per_key[$escape_key]) && ($escape_regexp_cache_per_key[$escape_key]['pos'] >= $start || $escape_regexp_cache_per_key[$escape_key]['pos'] === false)) { // we have already matched something if ($escape_regexp_cache_per_key[$escape_key]['pos'] === false) { // this comment is never matched continue; } $match_i = $escape_regexp_cache_per_key[$escape_key]['pos']; } elseif ( //This is to allow use of the offset parameter in preg_match and stay as compatible with older PHP versions as possible (GESHI_PHP_PRE_433 && preg_match($regexp, substr($part, $start), $match, PREG_OFFSET_CAPTURE)) || (!GESHI_PHP_PRE_433 && preg_match($regexp, $part, $match, PREG_OFFSET_CAPTURE, $start)) ) { $match_i = $match[0][1]; if (GESHI_PHP_PRE_433) { $match_i += $start; } $escape_regexp_cache_per_key[$escape_key] = array( 'key' => $escape_key, 'length' => strlen($match[0][0]), 'pos' => $match_i ); } else { $escape_regexp_cache_per_key[$escape_key]['pos'] = false; continue; } if ($match_i !== false && $match_i < $next_escape_regexp_pos) { $next_escape_regexp_pos = $match_i; $next_escape_regexp_key = $escape_key; if ($match_i === $start) { break; } } } } //Find the next simple escape position if('' != $this->language_data['ESCAPE_CHAR']) { $simple_escape = strpos($part, $this->language_data['ESCAPE_CHAR'], $start); if(false === $simple_escape) { $simple_escape = $length; } } else { $simple_escape = $length; } } else { $next_escape_regexp_pos = $length; $simple_escape = $length; } if($simple_escape < $next_escape_regexp_pos && $simple_escape < $length && $simple_escape < $close_pos) { //The nexxt escape sequence is a simple one ... $es_pos = $simple_escape; //Add the stuff not in the string yet ... $string .= $this->hsc(substr($part, $start, $es_pos - $start)); //Get the style for this escaped char ... if (!$this->use_classes) { $escape_char_attributes = ' style="' . $this->language_data['STYLES']['ESCAPE_CHAR'][0] . '"'; } else { $escape_char_attributes = ' class="es0"'; } //Add the style for the escape char ... $string .= "" . GeSHi::hsc($this->language_data['ESCAPE_CHAR']); //Get the byte AFTER the ESCAPE_CHAR we just found $es_char = $part[$es_pos + 1]; if ($es_char == "\n") { // don't put a newline around newlines $string .= "\n"; $start = $es_pos + 2; } elseif (ord($es_char) >= 128) { //This is an non-ASCII char (UTF8 or single byte) //This code tries to work around SF#2037598 ... if(function_exists('mb_substr')) { $es_char_m = mb_substr(substr($part, $es_pos+1, 16), 0, 1, $this->encoding); $string .= $es_char_m . ''; } elseif (!GESHI_PHP_PRE_433 && 'utf-8' == $this->encoding) { if(preg_match("/[\xC2-\xDF][\x80-\xBF]". "|\xE0[\xA0-\xBF][\x80-\xBF]". "|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}". "|\xED[\x80-\x9F][\x80-\xBF]". "|\xF0[\x90-\xBF][\x80-\xBF]{2}". "|[\xF1-\xF3][\x80-\xBF]{3}". "|\xF4[\x80-\x8F][\x80-\xBF]{2}/s", $part, $es_char_m, null, $es_pos + 1)) { $es_char_m = $es_char_m[0]; } else { $es_char_m = $es_char; } $string .= $this->hsc($es_char_m) . ''; } else { $es_char_m = $this->hsc($es_char); } $start = $es_pos + strlen($es_char_m) + 1; } else { $string .= $this->hsc($es_char) . ''; $start = $es_pos + 2; } } elseif ($next_escape_regexp_pos < $length && $next_escape_regexp_pos < $close_pos) { $es_pos = $next_escape_regexp_pos; //Add the stuff not in the string yet ... $string .= $this->hsc(substr($part, $start, $es_pos - $start)); //Get the key and length of this match ... $escape = $escape_regexp_cache_per_key[$next_escape_regexp_key]; $escape_str = substr($part, $es_pos, $escape['length']); $escape_key = $escape['key']; //Get the style for this escaped char ... if (!$this->use_classes) { $escape_char_attributes = ' style="' . $this->language_data['STYLES']['ESCAPE_CHAR'][$escape_key] . '"'; } else { $escape_char_attributes = ' class="es' . $escape_key . '"'; } //Add the style for the escape char ... $string .= "" . $this->hsc($escape_str) . ''; $start = $es_pos + $escape['length']; } else { //Copy the remainder of the string ... $string .= $this->hsc(substr($part, $start, $close_pos - $start + $char_len)) . ''; $start = $close_pos + $char_len; $string_open = false; } } while($string_open); if ($check_linenumbers) { // Are line numbers used? If, we should end the string before // the newline and begin it again (so when
  • s are put in the source // remains XHTML compliant) // note to self: This opens up possibility of config files specifying // that languages can/cannot have multiline strings??? $string = str_replace("\n", "\n", $string); } $result .= $string; $string = ''; $i = $start - 1; continue; } elseif ($this->lexic_permissions['STRINGS'] && $hq && $hq[0] == $char && substr($part, $i, $hq_strlen) == $hq && ($i != $next_comment_regexp_pos)) { // The start of a hard quoted string if (!$this->use_classes) { $string_attributes = ' style="' . $this->language_data['STYLES']['STRINGS']['HARD'] . '"'; $escape_char_attributes = ' style="' . $this->language_data['STYLES']['ESCAPE_CHAR']['HARD'] . '"'; } else { $string_attributes = ' class="st_h"'; $escape_char_attributes = ' class="es_h"'; } // parse the stuff before this $result .= $this->parse_non_string_part($stuff_to_parse); $stuff_to_parse = ''; // now handle the string $string = ''; // look for closing quote $start = $i + $hq_strlen; while ($close_pos = strpos($part, $this->language_data['HARDQUOTE'][1], $start)) { $start = $close_pos + 1; if ($this->lexic_permissions['ESCAPE_CHAR'] && $part[$close_pos - 1] == $this->language_data['HARDCHAR'] && (($i + $hq_strlen) != ($close_pos))) { //Support empty string for HQ escapes if Starter = Escape // make sure this quote is not escaped foreach ($this->language_data['HARDESCAPE'] as $hardescape) { if (substr($part, $close_pos - 1, strlen($hardescape)) == $hardescape) { // check wether this quote is escaped or if it is something like '\\' $escape_char_pos = $close_pos - 1; while ($escape_char_pos > 0 && $part[$escape_char_pos - 1] == $this->language_data['HARDCHAR']) { --$escape_char_pos; } if (($close_pos - $escape_char_pos) & 1) { // uneven number of escape chars => this quote is escaped continue 2; } } } } // found closing quote break; } //Found the closing delimiter? if (!$close_pos) { // span till the end of this $part when no closing delimiter is found $close_pos = $length; } //Get the actual string $string = substr($part, $i, $close_pos - $i + 1); $i = $close_pos; // handle escape chars and encode html chars // (special because when we have escape chars within our string they may not be escaped) if ($this->lexic_permissions['ESCAPE_CHAR'] && $this->language_data['ESCAPE_CHAR']) { $start = 0; $new_string = ''; while ($es_pos = strpos($string, $this->language_data['ESCAPE_CHAR'], $start)) { // hmtl escape stuff before $new_string .= $this->hsc(substr($string, $start, $es_pos - $start)); // check if this is a hard escape foreach ($this->language_data['HARDESCAPE'] as $hardescape) { if (substr($string, $es_pos, strlen($hardescape)) == $hardescape) { // indeed, this is a hardescape $new_string .= "" . $this->hsc($hardescape) . ''; $start = $es_pos + strlen($hardescape); continue 2; } } // not a hard escape, but a normal escape // they come in pairs of two $c = 0; while (isset($string[$es_pos + $c]) && isset($string[$es_pos + $c + 1]) && $string[$es_pos + $c] == $this->language_data['ESCAPE_CHAR'] && $string[$es_pos + $c + 1] == $this->language_data['ESCAPE_CHAR']) { $c += 2; } if ($c) { $new_string .= "" . str_repeat($escaped_escape_char, $c) . ''; $start = $es_pos + $c; } else { // this is just a single lonely escape char... $new_string .= $escaped_escape_char; $start = $es_pos + 1; } } $string = $new_string . $this->hsc(substr($string, $start)); } else { $string = $this->hsc($string); } if ($check_linenumbers) { // Are line numbers used? If, we should end the string before // the newline and begin it again (so when
  • s are put in the source // remains XHTML compliant) // note to self: This opens up possibility of config files specifying // that languages can/cannot have multiline strings??? $string = str_replace("\n", "\n", $string); } $result .= "" . $string . ''; $string = ''; continue; } else { //Have a look for regexp comments if ($i == $next_comment_regexp_pos) { $COMMENT_MATCHED = true; $comment = $comment_regexp_cache_per_key[$next_comment_regexp_key]; $test_str = $this->hsc(substr($part, $i, $comment['length'])); //@todo If remove important do remove here if ($this->lexic_permissions['COMMENTS']['MULTI']) { if (!$this->use_classes) { $attributes = ' style="' . $this->language_data['STYLES']['COMMENTS'][$comment['key']] . '"'; } else { $attributes = ' class="co' . $comment['key'] . '"'; } $test_str = "" . $test_str . ""; // Short-cut through all the multiline code if ($check_linenumbers) { // strreplace to put close span and open span around multiline newlines $test_str = str_replace( "\n", "\n", str_replace("\n ", "\n ", $test_str) ); } } $i += $comment['length'] - 1; // parse the rest $result .= $this->parse_non_string_part($stuff_to_parse); $stuff_to_parse = ''; } // If we haven't matched a regexp comment, try multi-line comments if (!$COMMENT_MATCHED) { // Is this a multiline comment? if (!empty($this->language_data['COMMENT_MULTI']) && $next_comment_multi_pos < $i) { $next_comment_multi_pos = $length; foreach ($this->language_data['COMMENT_MULTI'] as $open => $close) { $match_i = false; if (isset($comment_multi_cache_per_key[$open]) && ($comment_multi_cache_per_key[$open] >= $i || $comment_multi_cache_per_key[$open] === false)) { // we have already matched something if ($comment_multi_cache_per_key[$open] === false) { // this comment is never matched continue; } $match_i = $comment_multi_cache_per_key[$open]; } elseif (($match_i = stripos($part, $open, $i)) !== false) { $comment_multi_cache_per_key[$open] = $match_i; } else { $comment_multi_cache_per_key[$open] = false; continue; } if ($match_i !== false && $match_i < $next_comment_multi_pos) { $next_comment_multi_pos = $match_i; $next_open_comment_multi = $open; if ($match_i === $i) { break; } } } } if ($i == $next_comment_multi_pos) { $open = $next_open_comment_multi; $close = $this->language_data['COMMENT_MULTI'][$open]; $open_strlen = strlen($open); $close_strlen = strlen($close); $COMMENT_MATCHED = true; $test_str_match = $open; //@todo If remove important do remove here if ($this->lexic_permissions['COMMENTS']['MULTI'] || $open == GESHI_START_IMPORTANT) { if ($open != GESHI_START_IMPORTANT) { if (!$this->use_classes) { $attributes = ' style="' . $this->language_data['STYLES']['COMMENTS']['MULTI'] . '"'; } else { $attributes = ' class="coMULTI"'; } $test_str = "" . $this->hsc($open); } else { if (!$this->use_classes) { $attributes = ' style="' . $this->important_styles . '"'; } else { $attributes = ' class="imp"'; } // We don't include the start of the comment if it's an // "important" part $test_str = ""; } } else { $test_str = $this->hsc($open); } $close_pos = strpos( $part, $close, $i + $open_strlen ); if ($close_pos === false) { $close_pos = $length; } // Short-cut through all the multiline code $rest_of_comment = $this->hsc(substr($part, $i + $open_strlen, $close_pos - $i - $open_strlen + $close_strlen)); if (($this->lexic_permissions['COMMENTS']['MULTI'] || $test_str_match == GESHI_START_IMPORTANT) && $check_linenumbers) { // strreplace to put close span and open span around multiline newlines $test_str .= str_replace( "\n", "\n", str_replace("\n ", "\n ", $rest_of_comment) ); } else { $test_str .= $rest_of_comment; } if ($this->lexic_permissions['COMMENTS']['MULTI'] || $test_str_match == GESHI_START_IMPORTANT) { $test_str .= ''; } $i = $close_pos + $close_strlen - 1; // parse the rest $result .= $this->parse_non_string_part($stuff_to_parse); $stuff_to_parse = ''; } } // If we haven't matched a multiline comment, try single-line comments if (!$COMMENT_MATCHED) { // cache potential single line comment occurances if (!empty($this->language_data['COMMENT_SINGLE']) && $next_comment_single_pos < $i) { $next_comment_single_pos = $length; foreach ($this->language_data['COMMENT_SINGLE'] as $comment_key => $comment_mark) { $match_i = false; if (isset($comment_single_cache_per_key[$comment_key]) && ($comment_single_cache_per_key[$comment_key] >= $i || $comment_single_cache_per_key[$comment_key] === false)) { // we have already matched something if ($comment_single_cache_per_key[$comment_key] === false) { // this comment is never matched continue; } $match_i = $comment_single_cache_per_key[$comment_key]; } elseif ( // case sensitive comments ($this->language_data['CASE_SENSITIVE'][GESHI_COMMENTS] && ($match_i = stripos($part, $comment_mark, $i)) !== false) || // non case sensitive (!$this->language_data['CASE_SENSITIVE'][GESHI_COMMENTS] && (($match_i = strpos($part, $comment_mark, $i)) !== false))) { $comment_single_cache_per_key[$comment_key] = $match_i; } else { $comment_single_cache_per_key[$comment_key] = false; continue; } if ($match_i !== false && $match_i < $next_comment_single_pos) { $next_comment_single_pos = $match_i; $next_comment_single_key = $comment_key; if ($match_i === $i) { break; } } } } if ($next_comment_single_pos == $i) { $comment_key = $next_comment_single_key; $comment_mark = $this->language_data['COMMENT_SINGLE'][$comment_key]; $com_len = strlen($comment_mark); // This check will find special variables like $# in bash // or compiler directives of Delphi beginning {$ if ((empty($sc_disallowed_before) || ($i == 0) || (false === strpos($sc_disallowed_before, $part[$i-1]))) && (empty($sc_disallowed_after) || ($length <= $i + $com_len) || (false === strpos($sc_disallowed_after, $part[$i + $com_len])))) { // this is a valid comment $COMMENT_MATCHED = true; if ($this->lexic_permissions['COMMENTS'][$comment_key]) { if (!$this->use_classes) { $attributes = ' style="' . $this->language_data['STYLES']['COMMENTS'][$comment_key] . '"'; } else { $attributes = ' class="co' . $comment_key . '"'; } $test_str = "" . $this->hsc($this->change_case($comment_mark)); } else { $test_str = $this->hsc($comment_mark); } //Check if this comment is the last in the source $close_pos = strpos($part, "\n", $i); $oops = false; if ($close_pos === false) { $close_pos = $length; $oops = true; } $test_str .= $this->hsc(substr($part, $i + $com_len, $close_pos - $i - $com_len)); if ($this->lexic_permissions['COMMENTS'][$comment_key]) { $test_str .= ""; } // Take into account that the comment might be the last in the source if (!$oops) { $test_str .= "\n"; } $i = $close_pos; // parse the rest $result .= $this->parse_non_string_part($stuff_to_parse); $stuff_to_parse = ''; } } } } // Where are we adding this char? if (!$COMMENT_MATCHED) { $stuff_to_parse .= $char; } else { $result .= $test_str; unset($test_str); $COMMENT_MATCHED = false; } } // Parse the last bit $result .= $this->parse_non_string_part($stuff_to_parse); $stuff_to_parse = ''; } else { $result .= $this->hsc($part); } // Close the that surrounds the block if ($STRICTATTRS != '') { $result = str_replace("\n", "\n", $result); $result .= ''; } $endresult .= $result; unset($part, $parts[$key], $result); } //This fix is related to SF#1923020, but has to be applied regardless of //actually highlighting symbols. /** NOTE: memorypeak #3 */ $endresult = str_replace(array('', ''), array(';', '|'), $endresult); // // Parse the last stuff (redundant?) // $result .= $this->parse_non_string_part($stuff_to_parse); // Lop off the very first and last spaces // $result = substr($result, 1, -1); // We're finished: stop timing $this->set_time($start_time, microtime()); $this->finalise($endresult); return $endresult; } /** * Swaps out spaces and tabs for HTML indentation. Not needed if * the code is in a pre block... * * @param string The source to indent (reference!) * @since 1.0.0 * @access private */ function indent(&$result) { /// Replace tabs with the correct number of spaces if (false !== strpos($result, "\t")) { $lines = explode("\n", $result); $result = null;//Save memory while we process the lines individually $tab_width = $this->get_real_tab_width(); $tab_string = ' ' . str_repeat(' ', $tab_width); for ($key = 0, $n = count($lines); $key < $n; $key++) { $line = $lines[$key]; if (false === strpos($line, "\t")) { continue; } $pos = 0; $length = strlen($line); $lines[$key] = ''; // reduce memory $IN_TAG = false; for ($i = 0; $i < $length; ++$i) { $char = $line[$i]; // Simple engine to work out whether we're in a tag. // If we are we modify $pos. This is so we ignore HTML // in the line and only workout the tab replacement // via the actual content of the string // This test could be improved to include strings in the // html so that < or > would be allowed in user's styles // (e.g. quotes: '<' '>'; or similar) if ($IN_TAG) { if ('>' == $char) { $IN_TAG = false; } $lines[$key] .= $char; } elseif ('<' == $char) { $IN_TAG = true; $lines[$key] .= '<'; } elseif ('&' == $char) { $substr = substr($line, $i + 3, 5); $posi = strpos($substr, ';'); if (false === $posi) { ++$pos; } else { $pos -= $posi+2; } $lines[$key] .= $char; } elseif ("\t" == $char) { $str = ''; // OPTIMISE - move $strs out. Make an array: // $tabs = array( // 1 => ' ', // 2 => '  ', // 3 => '   ' etc etc // to use instead of building a string every time $tab_end_width = $tab_width - ($pos % $tab_width); //Moved out of the look as it doesn't change within the loop if (($pos & 1) || 1 == $tab_end_width) { $str .= substr($tab_string, 6, $tab_end_width); } else { $str .= substr($tab_string, 0, $tab_end_width+5); } $lines[$key] .= $str; $pos += $tab_end_width; if (false === strpos($line, "\t", $i + 1)) { $lines[$key] .= substr($line, $i + 1); break; } } elseif (0 == $pos && ' ' == $char) { $lines[$key] .= ' '; ++$pos; } else { $lines[$key] .= $char; ++$pos; } } } $result = implode("\n", $lines); unset($lines);//We don't need the lines separated beyond this --- free them! } // Other whitespace // BenBE: Fix to reduce the number of replacements to be done $result = preg_replace('/^ /m', ' ', $result); $result = str_replace(' ', '  ', $result); if ($this->line_numbers == GESHI_NO_LINE_NUMBERS && $this->header_type != GESHI_HEADER_PRE_TABLE) { if ($this->line_ending === null) { $result = nl2br($result); } else { $result = str_replace("\n", $this->line_ending, $result); } } } /** * Changes the case of a keyword for those languages where a change is asked for * * @param string The keyword to change the case of * @return string The keyword with its case changed * @since 1.0.0 * @access private */ function change_case($instr) { switch ($this->language_data['CASE_KEYWORDS']) { case GESHI_CAPS_UPPER: return strtoupper($instr); case GESHI_CAPS_LOWER: return strtolower($instr); default: return $instr; } } /** * Handles replacements of keywords to include markup and links if requested * * @param string The keyword to add the Markup to * @return The HTML for the match found * @since 1.0.8 * @access private * * @todo Get rid of ender in keyword links */ function handle_keyword_replace($match) { $k = $this->_kw_replace_group; $keyword = $match[0]; $keyword_match = $match[1]; $before = ''; $after = ''; if ($this->keyword_links) { // Keyword links have been ebabled if (isset($this->language_data['URLS'][$k]) && $this->language_data['URLS'][$k] != '') { // There is a base group for this keyword // Old system: strtolower //$keyword = ( $this->language_data['CASE_SENSITIVE'][$group] ) ? $keyword : strtolower($keyword); // New system: get keyword from language file to get correct case if (!$this->language_data['CASE_SENSITIVE'][$k] && strpos($this->language_data['URLS'][$k], '{FNAME}') !== false) { foreach ($this->language_data['KEYWORDS'][$k] as $word) { if (strcasecmp($word, $keyword_match) == 0) { break; } } } else { $word = $keyword_match; } $before = '<|UR1|"' . str_replace( array( '{FNAME}', '{FNAMEL}', '{FNAMEU}', '.'), array( str_replace('+', '%20', urlencode($this->hsc($word))), str_replace('+', '%20', urlencode($this->hsc(strtolower($word)))), str_replace('+', '%20', urlencode($this->hsc(strtoupper($word)))), ''), $this->language_data['URLS'][$k] ) . '">'; $after = ''; } } return $before . '<|/'. $k .'/>' . $this->change_case($keyword) . '|>' . $after; } /** * handles regular expressions highlighting-definitions with callback functions * * @note this is a callback, don't use it directly * * @param array the matches array * @return The highlighted string * @since 1.0.8 * @access private */ function handle_regexps_callback($matches) { // before: "' style=\"' . call_user_func(\"$func\", '\\1') . '\"\\1|>'", return ' style="' . call_user_func($this->language_data['STYLES']['REGEXPS'][$this->_rx_key], $matches[1]) . '"'. $matches[1] . '|>'; } /** * handles newlines in REGEXPS matches. Set the _hmr_* vars before calling this * * @note this is a callback, don't use it directly * * @param array the matches array * @return string * @since 1.0.8 * @access private */ function handle_multiline_regexps($matches) { $before = $this->_hmr_before; $after = $this->_hmr_after; if ($this->_hmr_replace) { $replace = $this->_hmr_replace; $search = array(); foreach (array_keys($matches) as $k) { $search[] = '\\' . $k; } $before = str_replace($search, $matches, $before); $after = str_replace($search, $matches, $after); $replace = str_replace($search, $matches, $replace); } else { $replace = $matches[0]; } return $before . '<|!REG3XP' . $this->_hmr_key .'!>' . str_replace("\n", "|>\n<|!REG3XP" . $this->_hmr_key . '!>', $replace) . '|>' . $after; } /** * Takes a string that has no strings or comments in it, and highlights * stuff like keywords, numbers and methods. * * @param string The string to parse for keyword, numbers etc. * @since 1.0.0 * @access private * @todo BUGGY! Why? Why not build string and return? */ function parse_non_string_part($stuff_to_parse) { $stuff_to_parse = ' ' . $this->hsc($stuff_to_parse); // Highlight keywords $disallowed_before = "(?lexic_permissions['STRINGS']) { $quotemarks = preg_quote(implode($this->language_data['QUOTEMARKS']), '/'); $disallowed_before .= $quotemarks; $disallowed_after .= $quotemarks; } $disallowed_before .= "])"; $disallowed_after .= "])"; $parser_control_pergroup = false; if (isset($this->language_data['PARSER_CONTROL'])) { if (isset($this->language_data['PARSER_CONTROL']['KEYWORDS'])) { $x = 0; // check wether per-keyword-group parser_control is enabled if (isset($this->language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_BEFORE'])) { $disallowed_before = $this->language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_BEFORE']; ++$x; } if (isset($this->language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_AFTER'])) { $disallowed_after = $this->language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_AFTER']; ++$x; } $parser_control_pergroup = (count($this->language_data['PARSER_CONTROL']['KEYWORDS']) - $x) > 0; } } foreach (array_keys($this->language_data['KEYWORDS']) as $k) { if (!isset($this->lexic_permissions['KEYWORDS'][$k]) || $this->lexic_permissions['KEYWORDS'][$k]) { $case_sensitive = $this->language_data['CASE_SENSITIVE'][$k]; $modifiers = $case_sensitive ? '' : 'i'; // NEW in 1.0.8 - per-keyword-group parser control $disallowed_before_local = $disallowed_before; $disallowed_after_local = $disallowed_after; if ($parser_control_pergroup && isset($this->language_data['PARSER_CONTROL']['KEYWORDS'][$k])) { if (isset($this->language_data['PARSER_CONTROL']['KEYWORDS'][$k]['DISALLOWED_BEFORE'])) { $disallowed_before_local = $this->language_data['PARSER_CONTROL']['KEYWORDS'][$k]['DISALLOWED_BEFORE']; } if (isset($this->language_data['PARSER_CONTROL']['KEYWORDS'][$k]['DISALLOWED_AFTER'])) { $disallowed_after_local = $this->language_data['PARSER_CONTROL']['KEYWORDS'][$k]['DISALLOWED_AFTER']; } } $this->_kw_replace_group = $k; //NEW in 1.0.8, the cached regexp list // since we don't want PHP / PCRE to crash due to too large patterns we split them into smaller chunks for ($set = 0, $set_length = count($this->language_data['CACHED_KEYWORD_LISTS'][$k]); $set < $set_length; ++$set) { $keywordset =& $this->language_data['CACHED_KEYWORD_LISTS'][$k][$set]; // Might make a more unique string for putting the number in soon // Basically, we don't put the styles in yet because then the styles themselves will // get highlighted if the language has a CSS keyword in it (like CSS, for example ;)) $stuff_to_parse = preg_replace_callback( "/$disallowed_before_local({$keywordset})(?!\(?:htm|php|aspx?))$disallowed_after_local/$modifiers", array($this, 'handle_keyword_replace'), $stuff_to_parse ); } } } // Regular expressions foreach ($this->language_data['REGEXPS'] as $key => $regexp) { if ($this->lexic_permissions['REGEXPS'][$key]) { if (is_array($regexp)) { if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) { // produce valid HTML when we match multiple lines $this->_hmr_replace = $regexp[GESHI_REPLACE]; $this->_hmr_before = $regexp[GESHI_BEFORE]; $this->_hmr_key = $key; $this->_hmr_after = $regexp[GESHI_AFTER]; $stuff_to_parse = preg_replace_callback( "/" . $regexp[GESHI_SEARCH] . "/{$regexp[GESHI_MODIFIERS]}", array($this, 'handle_multiline_regexps'), $stuff_to_parse); $this->_hmr_replace = false; $this->_hmr_before = ''; $this->_hmr_after = ''; } else { $stuff_to_parse = preg_replace( '/' . $regexp[GESHI_SEARCH] . '/' . $regexp[GESHI_MODIFIERS], $regexp[GESHI_BEFORE] . '<|!REG3XP'. $key .'!>' . $regexp[GESHI_REPLACE] . '|>' . $regexp[GESHI_AFTER], $stuff_to_parse); } } else { if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) { // produce valid HTML when we match multiple lines $this->_hmr_key = $key; $stuff_to_parse = preg_replace_callback( "/(" . $regexp . ")/", array($this, 'handle_multiline_regexps'), $stuff_to_parse); $this->_hmr_key = ''; } else { $stuff_to_parse = preg_replace( "/(" . $regexp . ")/", "<|!REG3XP$key!>\\1|>", $stuff_to_parse); } } } } // Highlight numbers. As of 1.0.8 we support different types of numbers $numbers_found = false; if ($this->lexic_permissions['NUMBERS'] && preg_match($this->language_data['PARSER_CONTROL']['NUMBERS']['PRECHECK_RX'], $stuff_to_parse )) { $numbers_found = true; //For each of the formats ... foreach($this->language_data['NUMBERS_RXCACHE'] as $id => $regexp) { //Check if it should be highlighted ... $stuff_to_parse = preg_replace($regexp, "<|/NUM!$id/>\\1|>", $stuff_to_parse); } } // // Now that's all done, replace /[number]/ with the correct styles // foreach (array_keys($this->language_data['KEYWORDS']) as $k) { if (!$this->use_classes) { $attributes = ' style="' . (isset($this->language_data['STYLES']['KEYWORDS'][$k]) ? $this->language_data['STYLES']['KEYWORDS'][$k] : "") . '"'; } else { $attributes = ' class="kw' . $k . '"'; } $stuff_to_parse = str_replace("<|/$k/>", "<|$attributes>", $stuff_to_parse); } if ($numbers_found) { // Put number styles in foreach($this->language_data['NUMBERS_RXCACHE'] as $id => $regexp) { //Commented out for now, as this needs some review ... // if ($numbers_permissions & $id) { //Get the appropriate style ... //Checking for unset styles is done by the style cache builder ... if (!$this->use_classes) { $attributes = ' style="' . $this->language_data['STYLES']['NUMBERS'][$id] . '"'; } else { $attributes = ' class="nu'.$id.'"'; } //Set in the correct styles ... $stuff_to_parse = str_replace("/NUM!$id/", $attributes, $stuff_to_parse); // } } } // Highlight methods and fields in objects if ($this->lexic_permissions['METHODS'] && $this->language_data['OOLANG']) { $oolang_spaces = "[\s]*"; $oolang_before = ""; $oolang_after = "[a-zA-Z][a-zA-Z0-9_]*"; if (isset($this->language_data['PARSER_CONTROL'])) { if (isset($this->language_data['PARSER_CONTROL']['OOLANG'])) { if (isset($this->language_data['PARSER_CONTROL']['OOLANG']['MATCH_BEFORE'])) { $oolang_before = $this->language_data['PARSER_CONTROL']['OOLANG']['MATCH_BEFORE']; } if (isset($this->language_data['PARSER_CONTROL']['OOLANG']['MATCH_AFTER'])) { $oolang_after = $this->language_data['PARSER_CONTROL']['OOLANG']['MATCH_AFTER']; } if (isset($this->language_data['PARSER_CONTROL']['OOLANG']['MATCH_SPACES'])) { $oolang_spaces = $this->language_data['PARSER_CONTROL']['OOLANG']['MATCH_SPACES']; } } } foreach ($this->language_data['OBJECT_SPLITTERS'] as $key => $splitter) { if (false !== strpos($stuff_to_parse, $splitter)) { if (!$this->use_classes) { $attributes = ' style="' . $this->language_data['STYLES']['METHODS'][$key] . '"'; } else { $attributes = ' class="me' . $key . '"'; } $stuff_to_parse = preg_replace("/($oolang_before)(" . preg_quote($this->language_data['OBJECT_SPLITTERS'][$key], '/') . ")($oolang_spaces)($oolang_after)/", "\\1\\2\\3<|$attributes>\\4|>", $stuff_to_parse); } } } // // Highlight brackets. Yes, I've tried adding a semi-colon to this list. // You try it, and see what happens ;) // TODO: Fix lexic permissions not converting entities if shouldn't // be highlighting regardless // if ($this->lexic_permissions['BRACKETS']) { $stuff_to_parse = str_replace( $this->language_data['CACHE_BRACKET_MATCH'], $this->language_data['CACHE_BRACKET_REPLACE'], $stuff_to_parse ); } //FIX for symbol highlighting ... if ($this->lexic_permissions['SYMBOLS'] && !empty($this->language_data['SYMBOLS'])) { //Get all matches and throw away those witin a block that is already highlighted... (i.e. matched by a regexp) $n_symbols = preg_match_all("/<\|(?:|[^>])+>(?:(?!\|>).*?)\|>|<\/a>|(?:" . $this->language_data['SYMBOL_SEARCH'] . ")+(?![^<]+?>)/", $stuff_to_parse, $pot_symbols, PREG_OFFSET_CAPTURE | PREG_SET_ORDER); $global_offset = 0; for ($s_id = 0; $s_id < $n_symbols; ++$s_id) { $symbol_match = $pot_symbols[$s_id][0][0]; if (strpos($symbol_match, '<') !== false || strpos($symbol_match, '>') !== false) { // already highlighted blocks _must_ include either < or > // so if this conditional applies, we have to skip this match // BenBE: UNLESS the block contains or if(strpos($symbol_match, '') === false && strpos($symbol_match, '') === false) { continue; } } // if we reach this point, we have a valid match which needs to be highlighted $symbol_length = strlen($symbol_match); $symbol_offset = $pot_symbols[$s_id][0][1]; unset($pot_symbols[$s_id]); $symbol_end = $symbol_length + $symbol_offset; $symbol_hl = ""; // if we have multiple styles, we have to handle them properly if ($this->language_data['MULTIPLE_SYMBOL_GROUPS']) { $old_sym = -1; // Split the current stuff to replace into its atomic symbols ... preg_match_all("/" . $this->language_data['SYMBOL_SEARCH'] . "/", $symbol_match, $sym_match_syms, PREG_PATTERN_ORDER); foreach ($sym_match_syms[0] as $sym_ms) { //Check if consequtive symbols belong to the same group to save output ... if (isset($this->language_data['SYMBOL_DATA'][$sym_ms]) && ($this->language_data['SYMBOL_DATA'][$sym_ms] != $old_sym)) { if (-1 != $old_sym) { $symbol_hl .= "|>"; } $old_sym = $this->language_data['SYMBOL_DATA'][$sym_ms]; if (!$this->use_classes) { $symbol_hl .= '<| style="' . $this->language_data['STYLES']['SYMBOLS'][$old_sym] . '">'; } else { $symbol_hl .= '<| class="sy' . $old_sym . '">'; } } $symbol_hl .= $sym_ms; } unset($sym_match_syms); //Close remaining tags and insert the replacement at the right position ... //Take caution if symbol_hl is empty to avoid doubled closing spans. if (-1 != $old_sym) { $symbol_hl .= "|>"; } } else { if (!$this->use_classes) { $symbol_hl = '<| style="' . $this->language_data['STYLES']['SYMBOLS'][0] . '">'; } else { $symbol_hl = '<| class="sy0">'; } $symbol_hl .= $symbol_match . '|>'; } $stuff_to_parse = substr_replace($stuff_to_parse, $symbol_hl, $symbol_offset + $global_offset, $symbol_length); // since we replace old text with something of different size, // we'll have to keep track of the differences $global_offset += strlen($symbol_hl) - $symbol_length; } } //FIX for symbol highlighting ... // Add class/style for regexps foreach (array_keys($this->language_data['REGEXPS']) as $key) { if ($this->lexic_permissions['REGEXPS'][$key]) { if (is_callable($this->language_data['STYLES']['REGEXPS'][$key])) { $this->_rx_key = $key; $stuff_to_parse = preg_replace_callback("/!REG3XP$key!(.*)\|>/U", array($this, 'handle_regexps_callback'), $stuff_to_parse); } else { if (!$this->use_classes) { $attributes = ' style="' . $this->language_data['STYLES']['REGEXPS'][$key] . '"'; } else { if (is_array($this->language_data['REGEXPS'][$key]) && array_key_exists(GESHI_CLASS, $this->language_data['REGEXPS'][$key])) { $attributes = ' class="' . $this->language_data['REGEXPS'][$key][GESHI_CLASS] . '"'; } else { $attributes = ' class="re' . $key . '"'; } } $stuff_to_parse = str_replace("!REG3XP$key!", "$attributes", $stuff_to_parse); } } } // Replace with . for urls $stuff_to_parse = str_replace('', '.', $stuff_to_parse); // Replace <|UR1| with link_styles[GESHI_LINK])) { if ($this->use_classes) { $stuff_to_parse = str_replace('<|UR1|', 'link_target . ' href=', $stuff_to_parse); } else { $stuff_to_parse = str_replace('<|UR1|', 'link_target . ' style="' . $this->link_styles[GESHI_LINK] . '" href=', $stuff_to_parse); } } else { $stuff_to_parse = str_replace('<|UR1|', 'link_target . ' href=', $stuff_to_parse); } // // NOW we add the span thingy ;) // $stuff_to_parse = str_replace('<|', '', '', $stuff_to_parse ); return substr($stuff_to_parse, 1); } /** * Sets the time taken to parse the code * * @param microtime The time when parsing started * @param microtime The time when parsing ended * @since 1.0.2 * @access private */ function set_time($start_time, $end_time) { $start = explode(' ', $start_time); $end = explode(' ', $end_time); $this->time = $end[0] + $end[1] - $start[0] - $start[1]; } /** * Gets the time taken to parse the code * * @return double The time taken to parse the code * @since 1.0.2 */ function get_time() { return $this->time; } /** * Merges arrays recursively, overwriting values of the first array with values of later arrays * * @since 1.0.8 * @access private */ function merge_arrays() { $arrays = func_get_args(); $narrays = count($arrays); // check arguments // comment out if more performance is necessary (in this case the foreach loop will trigger a warning if the argument is not an array) for ($i = 0; $i < $narrays; $i ++) { if (!is_array($arrays[$i])) { // also array_merge_recursive returns nothing in this case trigger_error('Argument #' . ($i+1) . ' is not an array - trying to merge array with scalar! Returning false!', E_USER_WARNING); return false; } } // the first array is in the output set in every case $ret = $arrays[0]; // merege $ret with the remaining arrays for ($i = 1; $i < $narrays; $i ++) { foreach ($arrays[$i] as $key => $value) { if (is_array($value) && isset($ret[$key])) { // if $ret[$key] is not an array you try to merge an scalar value with an array - the result is not defined (incompatible arrays) // in this case the call will trigger an E_USER_WARNING and the $ret[$key] will be false. $ret[$key] = $this->merge_arrays($ret[$key], $value); } else { $ret[$key] = $value; } } } return $ret; } /** * Gets language information and stores it for later use * * @param string The filename of the language file you want to load * @since 1.0.0 * @access private * @todo Needs to load keys for lexic permissions for keywords, regexps etc */ function load_language($file_name) { if ($file_name == $this->loaded_language) { // this file is already loaded! return; } //Prepare some stuff before actually loading the language file $this->loaded_language = $file_name; $this->parse_cache_built = false; $this->enable_highlighting(); $language_data = array(); //Load the language file require $file_name; // Perhaps some checking might be added here later to check that // $language data is a valid thing but maybe not $this->language_data = $language_data; // Set strict mode if should be set $this->strict_mode = $this->language_data['STRICT_MODE_APPLIES']; // Set permissions for all lexics to true // so they'll be highlighted by default foreach (array_keys($this->language_data['KEYWORDS']) as $key) { if (!empty($this->language_data['KEYWORDS'][$key])) { $this->lexic_permissions['KEYWORDS'][$key] = true; } else { $this->lexic_permissions['KEYWORDS'][$key] = false; } } foreach (array_keys($this->language_data['COMMENT_SINGLE']) as $key) { $this->lexic_permissions['COMMENTS'][$key] = true; } foreach (array_keys($this->language_data['REGEXPS']) as $key) { $this->lexic_permissions['REGEXPS'][$key] = true; } // for BenBE and future code reviews: // we can use empty here since we only check for existance and emptiness of an array // if it is not an array at all but rather false or null this will work as intended as well // even if $this->language_data['PARSER_CONTROL'] is undefined this won't trigger a notice if (!empty($this->language_data['PARSER_CONTROL']['ENABLE_FLAGS'])) { foreach ($this->language_data['PARSER_CONTROL']['ENABLE_FLAGS'] as $flag => $value) { // it's either true or false and maybe is true as well $perm = $value !== GESHI_NEVER; if ($flag == 'ALL') { $this->enable_highlighting($perm); continue; } if (!isset($this->lexic_permissions[$flag])) { // unknown lexic permission continue; } if (is_array($this->lexic_permissions[$flag])) { foreach ($this->lexic_permissions[$flag] as $key => $val) { $this->lexic_permissions[$flag][$key] = $perm; } } else { $this->lexic_permissions[$flag] = $perm; } } unset($this->language_data['PARSER_CONTROL']['ENABLE_FLAGS']); } //Fix: Problem where hardescapes weren't handled if no ESCAPE_CHAR was given //You need to set one for HARDESCAPES only in this case. if(!isset($this->language_data['HARDCHAR'])) { $this->language_data['HARDCHAR'] = $this->language_data['ESCAPE_CHAR']; } //NEW in 1.0.8: Allow styles to be loaded from a separate file to override defaults $style_filename = substr($file_name, 0, -4) . '.style.php'; if (is_readable($style_filename)) { //Clear any style_data that could have been set before ... if (isset($style_data)) { unset($style_data); } //Read the Style Information from the style file include $style_filename; //Apply the new styles to our current language styles if (isset($style_data) && is_array($style_data)) { $this->language_data['STYLES'] = $this->merge_arrays($this->language_data['STYLES'], $style_data); } } } /** * Takes the parsed code and various options, and creates the HTML * surrounding it to make it look nice. * * @param string The code already parsed (reference!) * @since 1.0.0 * @access private */ function finalise(&$parsed_code) { // Remove end parts of important declarations // This is BUGGY!! My fault for bad code: fix coming in 1.2 // @todo Remove this crap if ($this->enable_important_blocks && (strpos($parsed_code, $this->hsc(GESHI_START_IMPORTANT)) === false)) { $parsed_code = str_replace($this->hsc(GESHI_END_IMPORTANT), '', $parsed_code); } // Add HTML whitespace stuff if we're using the
    header if ($this->header_type != GESHI_HEADER_PRE && $this->header_type != GESHI_HEADER_PRE_VALID) { $this->indent($parsed_code); } // purge some unnecessary stuff /** NOTE: memorypeak #1 */ $parsed_code = preg_replace('#]+>(\s*)#', '\\1', $parsed_code); // If we are using IDs for line numbers, there needs to be an overall // ID set to prevent collisions. if ($this->add_ids && !$this->overall_id) { $this->overall_id = 'geshi-' . substr(md5(microtime()), 0, 4); } // Get code into lines /** NOTE: memorypeak #2 */ $code = explode("\n", $parsed_code); $parsed_code = $this->header(); // If we're using line numbers, we insert
  • s and appropriate // markup to style them (otherwise we don't need to do anything) if ($this->line_numbers != GESHI_NO_LINE_NUMBERS && $this->header_type != GESHI_HEADER_PRE_TABLE) { // If we're using the
     header, we shouldn't add newlines because
                // the 
     will line-break them (and the 
  • s already do this for us) $ls = ($this->header_type != GESHI_HEADER_PRE && $this->header_type != GESHI_HEADER_PRE_VALID) ? "\n" : ''; // Set vars to defaults for following loop $i = 0; // Foreach line... for ($i = 0, $n = count($code); $i < $n;) { //Reset the attributes for a new line ... $attrs = array(); // Make lines have at least one space in them if they're empty // BenBE: Checking emptiness using trim instead of relying on blanks if ('' == trim($code[$i])) { $code[$i] = ' '; } // If this is a "special line"... if ($this->line_numbers == GESHI_FANCY_LINE_NUMBERS && $i % $this->line_nth_row == ($this->line_nth_row - 1)) { // Set the attributes to style the line if ($this->use_classes) { //$attr = ' class="li2"'; $attrs['class'][] = 'li2'; $def_attr = ' class="de2"'; } else { //$attr = ' style="' . $this->line_style2 . '"'; $attrs['style'][] = $this->line_style2; // This style "covers up" the special styles set for special lines // so that styles applied to special lines don't apply to the actual // code on that line $def_attr = ' style="' . $this->code_style . '"'; } } else { if ($this->use_classes) { //$attr = ' class="li1"'; $attrs['class'][] = 'li1'; $def_attr = ' class="de1"'; } else { //$attr = ' style="' . $this->line_style1 . '"'; $attrs['style'][] = $this->line_style1; $def_attr = ' style="' . $this->code_style . '"'; } } //Check which type of tag to insert for this line if ($this->header_type == GESHI_HEADER_PRE_VALID) { $start = ""; $end = '
  • '; } else { // Span or div? $start = ""; $end = ''; } ++$i; // Are we supposed to use ids? If so, add them if ($this->add_ids) { $attrs['id'][] = "$this->overall_id-$i"; } //Is this some line with extra styles??? if (in_array($i, $this->highlight_extra_lines)) { if ($this->use_classes) { if (isset($this->highlight_extra_lines_styles[$i])) { $attrs['class'][] = "lx$i"; } else { $attrs['class'][] = "ln-xtra"; } } else { array_push($attrs['style'], $this->get_line_style($i)); } } // Add in the line surrounded by appropriate list HTML $attr_string = ''; foreach ($attrs as $key => $attr) { $attr_string .= ' ' . $key . '="' . implode(' ', $attr) . '"'; } $parsed_code .= "$start{$code[$i-1]}$end
  • $ls"; unset($code[$i - 1]); } } else { $n = count($code); if ($this->use_classes) { $attributes = ' class="de1"'; } else { $attributes = ' style="'. $this->code_style .'"'; } if ($this->header_type == GESHI_HEADER_PRE_VALID) { $parsed_code .= ''; } elseif ($this->header_type == GESHI_HEADER_PRE_TABLE) { if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) { if ($this->use_classes) { $attrs = ' class="ln"'; } else { $attrs = ' style="'. $this->table_linenumber_style .'"'; } $parsed_code .= ''; // get linenumbers // we don't merge it with the for below, since it should be better for // memory consumption this way // @todo: but... actually it would still be somewhat nice to merge the two loops // the mem peaks are at different positions for ($i = 0; $i < $n; ++$i) { $close = 0; // fancy lines if ($this->line_numbers == GESHI_FANCY_LINE_NUMBERS && $i % $this->line_nth_row == ($this->line_nth_row - 1)) { // Set the attributes to style the line if ($this->use_classes) { $parsed_code .= ''; } else { // This style "covers up" the special styles set for special lines // so that styles applied to special lines don't apply to the actual // code on that line $parsed_code .= '' .''; } $close += 2; } //Is this some line with extra styles??? if (in_array($i + 1, $this->highlight_extra_lines)) { if ($this->use_classes) { if (isset($this->highlight_extra_lines_styles[$i])) { $parsed_code .= ""; } else { $parsed_code .= ""; } } else { $parsed_code .= "get_line_style($i) . "\">"; } ++$close; } $parsed_code .= $this->line_numbers_start + $i; if ($close) { $parsed_code .= str_repeat('', $close); } elseif ($i != $n) { $parsed_code .= "\n"; } } $parsed_code .= ''; } $parsed_code .= ''; } // No line numbers, but still need to handle highlighting lines extra. // Have to use divs so the full width of the code is highlighted $close = 0; for ($i = 0; $i < $n; ++$i) { // Make lines have at least one space in them if they're empty // BenBE: Checking emptiness using trim instead of relying on blanks if ('' == trim($code[$i])) { $code[$i] = ' '; } // fancy lines if ($this->line_numbers == GESHI_FANCY_LINE_NUMBERS && $i % $this->line_nth_row == ($this->line_nth_row - 1)) { // Set the attributes to style the line if ($this->use_classes) { $parsed_code .= ''; } else { // This style "covers up" the special styles set for special lines // so that styles applied to special lines don't apply to the actual // code on that line $parsed_code .= '' .''; } $close += 2; } //Is this some line with extra styles??? if (in_array($i + 1, $this->highlight_extra_lines)) { if ($this->use_classes) { if (isset($this->highlight_extra_lines_styles[$i])) { $parsed_code .= ""; } else { $parsed_code .= ""; } } else { $parsed_code .= "get_line_style($i) . "\">"; } ++$close; } $parsed_code .= $code[$i]; if ($close) { $parsed_code .= str_repeat('', $close); $close = 0; } elseif ($i + 1 < $n) { $parsed_code .= "\n"; } unset($code[$i]); } if ($this->header_type == GESHI_HEADER_PRE_VALID || $this->header_type == GESHI_HEADER_PRE_TABLE) { $parsed_code .= ''; } if ($this->header_type == GESHI_HEADER_PRE_TABLE && $this->line_numbers != GESHI_NO_LINE_NUMBERS) { $parsed_code .= ''; } } $parsed_code .= $this->footer(); } /** * Creates the header for the code block (with correct attributes) * * @return string The header for the code block * @since 1.0.0 * @access private */ function header() { // Get attributes needed /** * @todo Document behaviour change - class is outputted regardless of whether * we're using classes or not. Same with style */ $attributes = ' class="' . $this->_genCSSName($this->language); if ($this->overall_class != '') { $attributes .= " ".$this->_genCSSName($this->overall_class); } $attributes .= '"'; if ($this->overall_id != '') { $attributes .= " id=\"{$this->overall_id}\""; } if ($this->overall_style != '' && !$this->use_classes) { $attributes .= ' style="' . $this->overall_style . '"'; } $ol_attributes = ''; if ($this->line_numbers_start != 1) { $ol_attributes .= ' start="' . $this->line_numbers_start . '"'; } // Get the header HTML $header = $this->header_content; if ($header) { if ($this->header_type == GESHI_HEADER_PRE || $this->header_type == GESHI_HEADER_PRE_VALID) { $header = str_replace("\n", '', $header); } $header = $this->replace_keywords($header); if ($this->use_classes) { $attr = ' class="head"'; } else { $attr = " style=\"{$this->header_content_style}\""; } if ($this->header_type == GESHI_HEADER_PRE_TABLE && $this->line_numbers != GESHI_NO_LINE_NUMBERS) { $header = "$header"; } else { $header = "$header"; } } if (GESHI_HEADER_NONE == $this->header_type) { if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) { return "$header"; } return $header . ($this->force_code_block ? '
    ' : ''); } // Work out what to return and do it if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) { if ($this->header_type == GESHI_HEADER_PRE) { return "$header"; } elseif ($this->header_type == GESHI_HEADER_DIV || $this->header_type == GESHI_HEADER_PRE_VALID) { return "$header"; } elseif ($this->header_type == GESHI_HEADER_PRE_TABLE) { return "$header"; } } else { if ($this->header_type == GESHI_HEADER_PRE) { return "$header" . ($this->force_code_block ? '
    ' : ''); } else { return "$header" . ($this->force_code_block ? '
    ' : ''); } } } /** * Returns the footer for the code block. * * @return string The footer for the code block * @since 1.0.0 * @access private */ function footer() { $footer = $this->footer_content; if ($footer) { if ($this->header_type == GESHI_HEADER_PRE) { $footer = str_replace("\n", '', $footer);; } $footer = $this->replace_keywords($footer); if ($this->use_classes) { $attr = ' class="foot"'; } else { $attr = " style=\"{$this->footer_content_style}\""; } if ($this->header_type == GESHI_HEADER_PRE_TABLE && $this->line_numbers != GESHI_NO_LINE_NUMBERS) { $footer = "$footer"; } else { $footer = "$footer
    "; } } if (GESHI_HEADER_NONE == $this->header_type) { return ($this->line_numbers != GESHI_NO_LINE_NUMBERS) ? '' . $footer : $footer; } if ($this->header_type == GESHI_HEADER_DIV || $this->header_type == GESHI_HEADER_PRE_VALID) { if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) { return "$footer
    "; } return ($this->force_code_block ? '
    ' : '') . "$footer"; } elseif ($this->header_type == GESHI_HEADER_PRE_TABLE) { if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) { return "$footer"; } return ($this->force_code_block ? '' : '') . "$footer"; } else { if ($this->line_numbers != GESHI_NO_LINE_NUMBERS) { return "$footer"; } return ($this->force_code_block ? '' : '') . "$footer"; } } /** * Replaces certain keywords in the header and footer with * certain configuration values * * @param string The header or footer content to do replacement on * @return string The header or footer with replaced keywords * @since 1.0.2 * @access private */ function replace_keywords($instr) { $keywords = $replacements = array(); $keywords[] = '
      to have no effect at all if there are line numbers // (
        s have margins that should be destroyed so all layout is // controlled by the set_overall_style method, which works on the //
         or 
        container). Additionally, set default styles for lines if (!$economy_mode || $this->line_numbers != GESHI_NO_LINE_NUMBERS) { //$stylesheet .= "$selector, {$selector}ol, {$selector}ol li {margin: 0;}\n"; $stylesheet .= "$selector.de1, $selector.de2 {{$this->code_style}}\n"; } // Add overall styles // note: neglect economy_mode, empty styles are meaningless if ($this->overall_style != '') { $stylesheet .= "$selector {{$this->overall_style}}\n"; } // Add styles for links // note: economy mode does not make _any_ sense here // either the style is empty and thus no selector is needed // or the appropriate key is given. foreach ($this->link_styles as $key => $style) { if ($style != '') { switch ($key) { case GESHI_LINK: $stylesheet .= "{$selector}a:link {{$style}}\n"; break; case GESHI_HOVER: $stylesheet .= "{$selector}a:hover {{$style}}\n"; break; case GESHI_ACTIVE: $stylesheet .= "{$selector}a:active {{$style}}\n"; break; case GESHI_VISITED: $stylesheet .= "{$selector}a:visited {{$style}}\n"; break; } } } // Header and footer // note: neglect economy_mode, empty styles are meaningless if ($this->header_content_style != '') { $stylesheet .= "$selector.head {{$this->header_content_style}}\n"; } if ($this->footer_content_style != '') { $stylesheet .= "$selector.foot {{$this->footer_content_style}}\n"; } // Styles for important stuff // note: neglect economy_mode, empty styles are meaningless if ($this->important_styles != '') { $stylesheet .= "$selector.imp {{$this->important_styles}}\n"; } // Simple line number styles if ((!$economy_mode || $this->line_numbers != GESHI_NO_LINE_NUMBERS) && $this->line_style1 != '') { $stylesheet .= "{$selector}li, {$selector}.li1 {{$this->line_style1}}\n"; } if ((!$economy_mode || $this->line_numbers != GESHI_NO_LINE_NUMBERS) && $this->table_linenumber_style != '') { $stylesheet .= "{$selector}.ln {{$this->table_linenumber_style}}\n"; } // If there is a style set for fancy line numbers, echo it out if ((!$economy_mode || $this->line_numbers == GESHI_FANCY_LINE_NUMBERS) && $this->line_style2 != '') { $stylesheet .= "{$selector}.li2 {{$this->line_style2}}\n"; } // note: empty styles are meaningless foreach ($this->language_data['STYLES']['KEYWORDS'] as $group => $styles) { if ($styles != '' && (!$economy_mode || (isset($this->lexic_permissions['KEYWORDS'][$group]) && $this->lexic_permissions['KEYWORDS'][$group]))) { $stylesheet .= "$selector.kw$group {{$styles}}\n"; } } foreach ($this->language_data['STYLES']['COMMENTS'] as $group => $styles) { if ($styles != '' && (!$economy_mode || (isset($this->lexic_permissions['COMMENTS'][$group]) && $this->lexic_permissions['COMMENTS'][$group]) || (!empty($this->language_data['COMMENT_REGEXP']) && !empty($this->language_data['COMMENT_REGEXP'][$group])))) { $stylesheet .= "$selector.co$group {{$styles}}\n"; } } foreach ($this->language_data['STYLES']['ESCAPE_CHAR'] as $group => $styles) { if ($styles != '' && (!$economy_mode || $this->lexic_permissions['ESCAPE_CHAR'])) { // NEW: since 1.0.8 we have to handle hardescapes if ($group === 'HARD') { $group = '_h'; } $stylesheet .= "$selector.es$group {{$styles}}\n"; } } foreach ($this->language_data['STYLES']['BRACKETS'] as $group => $styles) { if ($styles != '' && (!$economy_mode || $this->lexic_permissions['BRACKETS'])) { $stylesheet .= "$selector.br$group {{$styles}}\n"; } } foreach ($this->language_data['STYLES']['SYMBOLS'] as $group => $styles) { if ($styles != '' && (!$economy_mode || $this->lexic_permissions['SYMBOLS'])) { $stylesheet .= "$selector.sy$group {{$styles}}\n"; } } foreach ($this->language_data['STYLES']['STRINGS'] as $group => $styles) { if ($styles != '' && (!$economy_mode || $this->lexic_permissions['STRINGS'])) { // NEW: since 1.0.8 we have to handle hardquotes if ($group === 'HARD') { $group = '_h'; } $stylesheet .= "$selector.st$group {{$styles}}\n"; } } foreach ($this->language_data['STYLES']['NUMBERS'] as $group => $styles) { if ($styles != '' && (!$economy_mode || $this->lexic_permissions['NUMBERS'])) { $stylesheet .= "$selector.nu$group {{$styles}}\n"; } } foreach ($this->language_data['STYLES']['METHODS'] as $group => $styles) { if ($styles != '' && (!$economy_mode || $this->lexic_permissions['METHODS'])) { $stylesheet .= "$selector.me$group {{$styles}}\n"; } } // note: neglect economy_mode, empty styles are meaningless foreach ($this->language_data['STYLES']['SCRIPT'] as $group => $styles) { if ($styles != '') { $stylesheet .= "$selector.sc$group {{$styles}}\n"; } } foreach ($this->language_data['STYLES']['REGEXPS'] as $group => $styles) { if ($styles != '' && (!$economy_mode || (isset($this->lexic_permissions['REGEXPS'][$group]) && $this->lexic_permissions['REGEXPS'][$group]))) { if (is_array($this->language_data['REGEXPS'][$group]) && array_key_exists(GESHI_CLASS, $this->language_data['REGEXPS'][$group])) { $stylesheet .= "$selector."; $stylesheet .= $this->language_data['REGEXPS'][$group][GESHI_CLASS]; $stylesheet .= " {{$styles}}\n"; } else { $stylesheet .= "$selector.re$group {{$styles}}\n"; } } } // Styles for lines being highlighted extra if (!$economy_mode || (count($this->highlight_extra_lines)!=count($this->highlight_extra_lines_styles))) { $stylesheet .= "{$selector}.ln-xtra, {$selector}li.ln-xtra, {$selector}div.ln-xtra {{$this->highlight_extra_lines_style}}\n"; } $stylesheet .= "{$selector}span.xtra { display:block; }\n"; foreach ($this->highlight_extra_lines_styles as $lineid => $linestyle) { $stylesheet .= "{$selector}.lx$lineid, {$selector}li.lx$lineid, {$selector}div.lx$lineid {{$linestyle}}\n"; } return $stylesheet; } /** * Get's the style that is used for the specified line * * @param int The line number information is requested for * @access private * @since 1.0.7.21 */ function get_line_style($line) { //$style = null; $style = null; if (isset($this->highlight_extra_lines_styles[$line])) { $style = $this->highlight_extra_lines_styles[$line]; } else { // if no "extra" style assigned $style = $this->highlight_extra_lines_style; } return $style; } /** * this functions creates an optimized regular expression list * of an array of strings. * * Example: * $list = array('faa', 'foo', 'foobar'); * => string 'f(aa|oo(bar)?)' * * @param $list array of (unquoted) strings * @param $regexp_delimiter your regular expression delimiter, @see preg_quote() * @return string for regular expression * @author Milian Wolff * @since 1.0.8 * @access private */ function optimize_regexp_list($list, $regexp_delimiter = '/') { $regex_chars = array('.', '\\', '+', '-', '*', '?', '[', '^', ']', '$', '(', ')', '{', '}', '=', '!', '<', '>', '|', ':', $regexp_delimiter); sort($list); $regexp_list = array(''); $num_subpatterns = 0; $list_key = 0; // the tokens which we will use to generate the regexp list $tokens = array(); $prev_keys = array(); // go through all entries of the list and generate the token list $cur_len = 0; for ($i = 0, $i_max = count($list); $i < $i_max; ++$i) { if ($cur_len > GESHI_MAX_PCRE_LENGTH) { // seems like the length of this pcre is growing exorbitantly $regexp_list[++$list_key] = $this->_optimize_regexp_list_tokens_to_string($tokens); $num_subpatterns = substr_count($regexp_list[$list_key], '(?:'); $tokens = array(); $cur_len = 0; } $level = 0; $entry = preg_quote((string) $list[$i], $regexp_delimiter); $pointer = &$tokens; // properly assign the new entry to the correct position in the token array // possibly generate smaller common denominator keys while (true) { // get the common denominator if (isset($prev_keys[$level])) { if ($prev_keys[$level] == $entry) { // this is a duplicate entry, skip it continue 2; } $char = 0; while (isset($entry[$char]) && isset($prev_keys[$level][$char]) && $entry[$char] == $prev_keys[$level][$char]) { ++$char; } if ($char > 0) { // this entry has at least some chars in common with the current key if ($char == strlen($prev_keys[$level])) { // current key is totally matched, i.e. this entry has just some bits appended $pointer = &$pointer[$prev_keys[$level]]; } else { // only part of the keys match $new_key_part1 = substr($prev_keys[$level], 0, $char); $new_key_part2 = substr($prev_keys[$level], $char); if (in_array($new_key_part1[0], $regex_chars) || in_array($new_key_part2[0], $regex_chars)) { // this is bad, a regex char as first character $pointer[$entry] = array('' => true); array_splice($prev_keys, $level, count($prev_keys), $entry); $cur_len += strlen($entry); continue; } else { // relocate previous tokens $pointer[$new_key_part1] = array($new_key_part2 => $pointer[$prev_keys[$level]]); unset($pointer[$prev_keys[$level]]); $pointer = &$pointer[$new_key_part1]; // recreate key index array_splice($prev_keys, $level, count($prev_keys), array($new_key_part1, $new_key_part2)); $cur_len += strlen($new_key_part2); } } ++$level; $entry = substr($entry, $char); continue; } // else: fall trough, i.e. no common denominator was found } if ($level == 0 && !empty($tokens)) { // we can dump current tokens into the string and throw them away afterwards $new_entry = $this->_optimize_regexp_list_tokens_to_string($tokens); $new_subpatterns = substr_count($new_entry, '(?:'); if (GESHI_MAX_PCRE_SUBPATTERNS && $num_subpatterns + $new_subpatterns > GESHI_MAX_PCRE_SUBPATTERNS) { $regexp_list[++$list_key] = $new_entry; $num_subpatterns = $new_subpatterns; } else { if (!empty($regexp_list[$list_key])) { $new_entry = '|' . $new_entry; } $regexp_list[$list_key] .= $new_entry; $num_subpatterns += $new_subpatterns; } $tokens = array(); $cur_len = 0; } // no further common denominator found $pointer[$entry] = array('' => true); array_splice($prev_keys, $level, count($prev_keys), $entry); $cur_len += strlen($entry); break; } unset($list[$i]); } // make sure the last tokens get converted as well $new_entry = $this->_optimize_regexp_list_tokens_to_string($tokens); if (GESHI_MAX_PCRE_SUBPATTERNS && $num_subpatterns + substr_count($new_entry, '(?:') > GESHI_MAX_PCRE_SUBPATTERNS) { if ( !empty($regexp_list[$list_key]) ) { ++$list_key; } $regexp_list[$list_key] = $new_entry; } else { if (!empty($regexp_list[$list_key])) { $new_entry = '|' . $new_entry; } $regexp_list[$list_key] .= $new_entry; } return $regexp_list; } /** * this function creates the appropriate regexp string of an token array * you should not call this function directly, @see $this->optimize_regexp_list(). * * @param &$tokens array of tokens * @param $recursed bool to know wether we recursed or not * @return string * @author Milian Wolff * @since 1.0.8 * @access private */ function _optimize_regexp_list_tokens_to_string(&$tokens, $recursed = false) { $list = ''; foreach ($tokens as $token => $sub_tokens) { $list .= $token; $close_entry = isset($sub_tokens['']); unset($sub_tokens['']); if (!empty($sub_tokens)) { $list .= '(?:' . $this->_optimize_regexp_list_tokens_to_string($sub_tokens, true) . ')'; if ($close_entry) { // make sub_tokens optional $list .= '?'; } } $list .= '|'; } if (!$recursed) { // do some optimizations // common trailing strings // BUGGY! //$list = preg_replace_callback('#(?<=^|\:|\|)\w+?(\w+)(?:\|.+\1)+(?=\|)#', create_function( // '$matches', 'return "(?:" . preg_replace("#" . preg_quote($matches[1], "#") . "(?=\||$)#", "", $matches[0]) . ")" . $matches[1];'), $list); // (?:p)? => p? $list = preg_replace('#\(\?\:(.)\)\?#', '\1?', $list); // (?:a|b|c|d|...)? => [abcd...]? // TODO: a|bb|c => [ac]|bb static $callback_2; if (!isset($callback_2)) { $callback_2 = create_function('$matches', 'return "[" . str_replace("|", "", $matches[1]) . "]";'); } $list = preg_replace_callback('#\(\?\:((?:.\|)+.)\)#', $callback_2, $list); } // return $list without trailing pipe return substr($list, 0, -1); } } // End Class GeSHi if (!function_exists('geshi_highlight')) { /** * Easy way to highlight stuff. Behaves just like highlight_string * * @param string The code to highlight * @param string The language to highlight the code in * @param string The path to the language files. You can leave this blank if you need * as from version 1.0.7 the path should be automatically detected * @param boolean Whether to return the result or to echo * @return string The code highlighted (if $return is true) * @since 1.0.2 */ function geshi_highlight($string, $language, $path = null, $return = false) { $geshi = new GeSHi($string, $language, $path); $geshi->set_header_type(GESHI_HEADER_NONE); if ($return) { return '' . $geshi->parse_code() . ''; } echo '' . $geshi->parse_code() . ''; if ($geshi->error()) { return false; } return true; } } ?>cppcheck-1.61/htdocs/site/geshi/geshi/000077500000000000000000000000001217722632100176525ustar00rootroot00000000000000cppcheck-1.61/htdocs/site/geshi/geshi/c.php000066400000000000000000000243311217722632100206100ustar00rootroot00000000000000 'C', 'COMMENT_SINGLE' => array(1 => '//', 2 => '#'), 'COMMENT_MULTI' => array('/*' => '*/'), 'COMMENT_REGEXP' => array( //Multiline-continued single-line comments 1 => '/\/\/(?:\\\\\\\\|\\\\\\n|.)*$/m', //Multiline-continued preprocessor define 2 => '/#(?:\\\\\\\\|\\\\\\n|.)*$/m' ), 'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE, 'QUOTEMARKS' => array("'", '"'), 'ESCAPE_CHAR' => '', 'ESCAPE_REGEXP' => array( //Simple Single Char Escapes 1 => "#\\\\[\\\\abfnrtv\'\"?\n]#i", //Hexadecimal Char Specs 2 => "#\\\\x[\da-fA-F]{2}#", //Hexadecimal Char Specs 3 => "#\\\\u[\da-fA-F]{4}#", //Hexadecimal Char Specs 4 => "#\\\\U[\da-fA-F]{8}#", //Octal Char Specs 5 => "#\\\\[0-7]{1,3}#" ), 'NUMBERS' => GESHI_NUMBER_INT_BASIC | GESHI_NUMBER_INT_CSTYLE | GESHI_NUMBER_BIN_PREFIX_0B | GESHI_NUMBER_OCT_PREFIX | GESHI_NUMBER_HEX_PREFIX | GESHI_NUMBER_FLT_NONSCI | GESHI_NUMBER_FLT_NONSCI_F | GESHI_NUMBER_FLT_SCI_SHORT | GESHI_NUMBER_FLT_SCI_ZERO, 'KEYWORDS' => array( 1 => array( 'if', 'return', 'while', 'case', 'continue', 'default', 'do', 'else', 'for', 'switch', 'goto' ), 2 => array( 'null', 'false', 'break', 'true', 'function', 'enum', 'extern', 'inline' ), 3 => array( // assert.h 'assert', //complex.h 'cabs', 'cacos', 'cacosh', 'carg', 'casin', 'casinh', 'catan', 'catanh', 'ccos', 'ccosh', 'cexp', 'cimag', 'cis', 'clog', 'conj', 'cpow', 'cproj', 'creal', 'csin', 'csinh', 'csqrt', 'ctan', 'ctanh', //ctype.h 'digittoint', 'isalnum', 'isalpha', 'isascii', 'isblank', 'iscntrl', 'isdigit', 'isgraph', 'islower', 'isprint', 'ispunct', 'isspace', 'isupper', 'isxdigit', 'toascii', 'tolower', 'toupper', //inttypes.h 'imaxabs', 'imaxdiv', 'strtoimax', 'strtoumax', 'wcstoimax', 'wcstoumax', //locale.h 'localeconv', 'setlocale', //math.h 'acos', 'asin', 'atan', 'atan2', 'ceil', 'cos', 'cosh', 'exp', 'fabs', 'floor', 'frexp', 'ldexp', 'log', 'log10', 'modf', 'pow', 'sin', 'sinh', 'sqrt', 'tan', 'tanh', //setjmp.h 'longjmp', 'setjmp', //signal.h 'raise', //stdarg.h 'va_arg', 'va_copy', 'va_end', 'va_start', //stddef.h 'offsetof', //stdio.h 'clearerr', 'fclose', 'fdopen', 'feof', 'ferror', 'fflush', 'fgetc', 'fgetpos', 'fgets', 'fopen', 'fprintf', 'fputc', 'fputchar', 'fputs', 'fread', 'freopen', 'fscanf', 'fseek', 'fsetpos', 'ftell', 'fwrite', 'getc', 'getch', 'getchar', 'gets', 'perror', 'printf', 'putc', 'putchar', 'puts', 'remove', 'rename', 'rewind', 'scanf', 'setbuf', 'setvbuf', 'snprintf', 'sprintf', 'sscanf', 'tmpfile', 'tmpnam', 'ungetc', 'vfprintf', 'vfscanf', 'vprintf', 'vscanf', 'vsprintf', 'vsscanf', //stdlib.h 'abort', 'abs', 'atexit', 'atof', 'atoi', 'atol', 'bsearch', 'calloc', 'div', 'exit', 'free', 'getenv', 'itoa', 'labs', 'ldiv', 'ltoa', 'malloc', 'qsort', 'rand', 'realloc', 'srand', 'strtod', 'strtol', 'strtoul', 'system', //string.h 'memchr', 'memcmp', 'memcpy', 'memmove', 'memset', 'strcat', 'strchr', 'strcmp', 'strcoll', 'strcpy', 'strcspn', 'strerror', 'strlen', 'strncat', 'strncmp', 'strncpy', 'strpbrk', 'strrchr', 'strspn', 'strstr', 'strtok', 'strxfrm', //time.h 'asctime', 'clock', 'ctime', 'difftime', 'gmtime', 'localtime', 'mktime', 'strftime', 'time', //wchar.h 'btowc', 'fgetwc', 'fgetws', 'fputwc', 'fputws', 'fwide', 'fwprintf', 'fwscanf', 'getwc', 'getwchar', 'mbrlen', 'mbrtowc', 'mbsinit', 'mbsrtowcs', 'putwc', 'putwchar', 'swprintf', 'swscanf', 'ungetwc', 'vfwprintf', 'vswprintf', 'vwprintf', 'wcrtomb', 'wcscat', 'wcschr', 'wcscmp', 'wcscoll', 'wcscpy', 'wcscspn', 'wcsftime', 'wcslen', 'wcsncat', 'wcsncmp', 'wcsncpy', 'wcspbrk', 'wcsrchr', 'wcsrtombs', 'wcsspn', 'wcsstr', 'wcstod', 'wcstok', 'wcstol', 'wcstoul', 'wcsxfrm', 'wctob', 'wmemchr', 'wmemcmp', 'wmemcpy', 'wmemmove', 'wmemset', 'wprintf', 'wscanf', //wctype.h 'iswalnum', 'iswalpha', 'iswcntrl', 'iswctype', 'iswdigit', 'iswgraph', 'iswlower', 'iswprint', 'iswpunct', 'iswspace', 'iswupper', 'iswxdigit', 'towctrans', 'towlower', 'towupper', 'wctrans', 'wctype' ), 4 => array( 'auto', 'char', 'const', 'double', 'float', 'int', 'long', 'register', 'short', 'signed', 'sizeof', 'static', 'struct', 'typedef', 'union', 'unsigned', 'void', 'volatile', 'wchar_t', 'int8', 'int16', 'int32', 'int64', 'uint8', 'uint16', 'uint32', 'uint64', 'int_fast8_t', 'int_fast16_t', 'int_fast32_t', 'int_fast64_t', 'uint_fast8_t', 'uint_fast16_t', 'uint_fast32_t', 'uint_fast64_t', 'int_least8_t', 'int_least16_t', 'int_least32_t', 'int_least64_t', 'uint_least8_t', 'uint_least16_t', 'uint_least32_t', 'uint_least64_t', 'int8_t', 'int16_t', 'int32_t', 'int64_t', 'uint8_t', 'uint16_t', 'uint32_t', 'uint64_t', 'intmax_t', 'uintmax_t', 'intptr_t', 'uintptr_t', 'size_t', 'off_t' ), ), 'SYMBOLS' => array( '(', ')', '{', '}', '[', ']', '+', '-', '*', '/', '%', '=', '<', '>', '!', '^', '&', '|', '?', ':', ';', ',' ), 'CASE_SENSITIVE' => array( GESHI_COMMENTS => false, 1 => true, 2 => true, 3 => true, 4 => true, ), 'STYLES' => array( 'KEYWORDS' => array( 1 => 'color: #b1b100;', 2 => 'color: #000000; font-weight: bold;', 3 => 'color: #000066;', 4 => 'color: #993333;' ), 'COMMENTS' => array( 1 => 'color: #666666; font-style: italic;', 2 => 'color: #339933;', 'MULTI' => 'color: #808080; font-style: italic;' ), 'ESCAPE_CHAR' => array( 0 => 'color: #000099; font-weight: bold;', 1 => 'color: #000099; font-weight: bold;', 2 => 'color: #660099; font-weight: bold;', 3 => 'color: #660099; font-weight: bold;', 4 => 'color: #660099; font-weight: bold;', 5 => 'color: #006699; font-weight: bold;', 'HARD' => '', ), 'BRACKETS' => array( 0 => 'color: #009900;' ), 'STRINGS' => array( 0 => 'color: #ff0000;' ), 'NUMBERS' => array( 0 => 'color: #0000dd;', GESHI_NUMBER_BIN_PREFIX_0B => 'color: #208080;', GESHI_NUMBER_OCT_PREFIX => 'color: #208080;', GESHI_NUMBER_HEX_PREFIX => 'color: #208080;', GESHI_NUMBER_FLT_SCI_SHORT => 'color:#800080;', GESHI_NUMBER_FLT_SCI_ZERO => 'color:#800080;', GESHI_NUMBER_FLT_NONSCI_F => 'color:#800080;', GESHI_NUMBER_FLT_NONSCI => 'color:#800080;' ), 'METHODS' => array( 1 => 'color: #202020;', 2 => 'color: #202020;' ), 'SYMBOLS' => array( 0 => 'color: #339933;' ), 'REGEXPS' => array( ), 'SCRIPT' => array( ) ), 'URLS' => array( 1 => '', 2 => '', 3 => 'http://www.opengroup.org/onlinepubs/009695399/functions/{FNAMEL}.html', 4 => '' ), 'OOLANG' => true, 'OBJECT_SPLITTERS' => array( 1 => '.', 2 => '::' ), 'REGEXPS' => array( ), 'STRICT_MODE_APPLIES' => GESHI_NEVER, 'SCRIPT_DELIMITERS' => array( ), 'HIGHLIGHT_STRICT_BLOCK' => array( ), 'TAB_WIDTH' => 4 ); ?>cppcheck-1.61/htdocs/site/geshi/geshi/cpp.php000066400000000000000000000235671217722632100211620ustar00rootroot00000000000000 'C++', 'COMMENT_SINGLE' => array(1 => '//', 2 => '#'), 'COMMENT_MULTI' => array('/*' => '*/'), 'COMMENT_REGEXP' => array( //Multiline-continued single-line comments 1 => '/\/\/(?:\\\\\\\\|\\\\\\n|.)*$/m', //Multiline-continued preprocessor define 2 => '/#(?:\\\\\\\\|\\\\\\n|.)*$/m' ), 'CASE_KEYWORDS' => GESHI_CAPS_NO_CHANGE, 'QUOTEMARKS' => array("'", '"'), 'ESCAPE_CHAR' => '', 'ESCAPE_REGEXP' => array( //Simple Single Char Escapes 1 => "#\\\\[abfnrtv\\\'\"?\n]#i", //Hexadecimal Char Specs 2 => "#\\\\x[\da-fA-F]{2}#", //Hexadecimal Char Specs 3 => "#\\\\u[\da-fA-F]{4}#", //Hexadecimal Char Specs 4 => "#\\\\U[\da-fA-F]{8}#", //Octal Char Specs 5 => "#\\\\[0-7]{1,3}#" ), 'NUMBERS' => GESHI_NUMBER_INT_BASIC | GESHI_NUMBER_INT_CSTYLE | GESHI_NUMBER_BIN_PREFIX_0B | GESHI_NUMBER_OCT_PREFIX | GESHI_NUMBER_HEX_PREFIX | GESHI_NUMBER_FLT_NONSCI | GESHI_NUMBER_FLT_NONSCI_F | GESHI_NUMBER_FLT_SCI_SHORT | GESHI_NUMBER_FLT_SCI_ZERO, 'KEYWORDS' => array( 1 => array( 'break', 'case', 'continue', 'default', 'do', 'else', 'for', 'goto', 'if', 'return', 'switch', 'throw', 'while' ), 2 => array( 'NULL', 'false', 'true', 'enum', 'errno', 'EDOM', 'ERANGE', 'FLT_RADIX', 'FLT_ROUNDS', 'FLT_DIG', 'DBL_DIG', 'LDBL_DIG', 'FLT_EPSILON', 'DBL_EPSILON', 'LDBL_EPSILON', 'FLT_MANT_DIG', 'DBL_MANT_DIG', 'LDBL_MANT_DIG', 'FLT_MAX', 'DBL_MAX', 'LDBL_MAX', 'FLT_MAX_EXP', 'DBL_MAX_EXP', 'LDBL_MAX_EXP', 'FLT_MIN', 'DBL_MIN', 'LDBL_MIN', 'FLT_MIN_EXP', 'DBL_MIN_EXP', 'LDBL_MIN_EXP', 'CHAR_BIT', 'CHAR_MAX', 'CHAR_MIN', 'SCHAR_MAX', 'SCHAR_MIN', 'UCHAR_MAX', 'SHRT_MAX', 'SHRT_MIN', 'USHRT_MAX', 'INT_MAX', 'INT_MIN', 'UINT_MAX', 'LONG_MAX', 'LONG_MIN', 'ULONG_MAX', 'HUGE_VAL', 'SIGABRT', 'SIGFPE', 'SIGILL', 'SIGINT', 'SIGSEGV', 'SIGTERM', 'SIG_DFL', 'SIG_ERR', 'SIG_IGN', 'BUFSIZ', 'EOF', 'FILENAME_MAX', 'FOPEN_MAX', 'L_tmpnam', 'SEEK_CUR', 'SEEK_END', 'SEEK_SET', 'TMP_MAX', 'stdin', 'stdout', 'stderr', 'EXIT_FAILURE', 'EXIT_SUCCESS', 'RAND_MAX', 'CLOCKS_PER_SEC', 'virtual', 'public', 'private', 'protected', 'template', 'using', 'namespace', 'try', 'catch', 'inline', 'dynamic_cast', 'const_cast', 'reinterpret_cast', 'static_cast', 'explicit', 'friend', 'typename', 'typeid', 'class' ), 3 => array( 'cin', 'cerr', 'clog', 'cout', 'delete', 'new', 'this', 'printf', 'fprintf', 'snprintf', 'sprintf', 'assert', 'isalnum', 'isalpha', 'isdigit', 'iscntrl', 'isgraph', 'islower', 'isprint', 'ispunct', 'isspace', 'isupper', 'isxdigit', 'tolower', 'toupper', 'exp', 'log', 'log10', 'pow', 'sqrt', 'ceil', 'floor', 'fabs', 'ldexp', 'frexp', 'modf', 'fmod', 'sin', 'cos', 'tan', 'asin', 'acos', 'atan', 'atan2', 'sinh', 'cosh', 'tanh', 'setjmp', 'longjmp', 'va_start', 'va_arg', 'va_end', 'offsetof', 'sizeof', 'fopen', 'freopen', 'fflush', 'fclose', 'remove', 'rename', 'tmpfile', 'tmpname', 'setvbuf', 'setbuf', 'vfprintf', 'vprintf', 'vsprintf', 'fscanf', 'scanf', 'sscanf', 'fgetc', 'fgets', 'fputc', 'fputs', 'getc', 'getchar', 'gets', 'putc', 'putchar', 'puts', 'ungetc', 'fread', 'fwrite', 'fseek', 'ftell', 'rewind', 'fgetpos', 'fsetpos', 'clearerr', 'feof', 'ferror', 'perror', 'abs', 'labs', 'div', 'ldiv', 'atof', 'atoi', 'atol', 'strtod', 'strtol', 'strtoul', 'calloc', 'malloc', 'realloc', 'free', 'abort', 'exit', 'atexit', 'system', 'getenv', 'bsearch', 'qsort', 'rand', 'srand', 'strcpy', 'strncpy', 'strcat', 'strncat', 'strcmp', 'strncmp', 'strcoll', 'strchr', 'strrchr', 'strspn', 'strcspn', 'strpbrk', 'strstr', 'strlen', 'strerror', 'strtok', 'strxfrm', 'memcpy', 'memmove', 'memcmp', 'memchr', 'memset', 'clock', 'time', 'difftime', 'mktime', 'asctime', 'ctime', 'gmtime', 'localtime', 'strftime' ), 4 => array( 'auto', 'bool', 'char', 'const', 'double', 'float', 'int', 'long', 'longint', 'register', 'short', 'shortint', 'signed', 'static', 'struct', 'typedef', 'union', 'unsigned', 'void', 'volatile', 'extern', 'jmp_buf', 'signal', 'raise', 'va_list', 'ptrdiff_t', 'size_t', 'FILE', 'fpos_t', 'div_t', 'ldiv_t', 'clock_t', 'time_t', 'tm', 'wchar_t', 'int8', 'int16', 'int32', 'int64', 'uint8', 'uint16', 'uint32', 'uint64', 'int_fast8_t', 'int_fast16_t', 'int_fast32_t', 'int_fast64_t', 'uint_fast8_t', 'uint_fast16_t', 'uint_fast32_t', 'uint_fast64_t', 'int_least8_t', 'int_least16_t', 'int_least32_t', 'int_least64_t', 'uint_least8_t', 'uint_least16_t', 'uint_least32_t', 'uint_least64_t', 'int8_t', 'int16_t', 'int32_t', 'int64_t', 'uint8_t', 'uint16_t', 'uint32_t', 'uint64_t', 'intmax_t', 'uintmax_t', 'intptr_t', 'uintptr_t' ), ), 'SYMBOLS' => array( 0 => array('(', ')', '{', '}', '[', ']'), 1 => array('<', '>','='), 2 => array('+', '-', '*', '/', '%'), 3 => array('!', '^', '&', '|'), 4 => array('?', ':', ';') ), 'CASE_SENSITIVE' => array( GESHI_COMMENTS => false, 1 => true, 2 => true, 3 => true, 4 => true, ), 'STYLES' => array( 'KEYWORDS' => array( 1 => 'color: #0000ff;', 2 => 'color: #0000ff;', 3 => 'color: #0000dd;', 4 => 'color: #0000ff;' ), 'COMMENTS' => array( 1 => 'color: #666666;', 2 => 'color: #339900;', 'MULTI' => 'color: #ff0000; font-style: italic;' ), 'ESCAPE_CHAR' => array( 0 => 'color: #000099; font-weight: bold;', 1 => 'color: #000099; font-weight: bold;', 2 => 'color: #660099; font-weight: bold;', 3 => 'color: #660099; font-weight: bold;', 4 => 'color: #660099; font-weight: bold;', 5 => 'color: #006699; font-weight: bold;', 'HARD' => '', ), 'BRACKETS' => array( 0 => 'color: #008000;' ), 'STRINGS' => array( 0 => 'color: #FF0000;' ), 'NUMBERS' => array( 0 => 'color: #0000dd;', GESHI_NUMBER_BIN_PREFIX_0B => 'color: #208080;', GESHI_NUMBER_OCT_PREFIX => 'color: #208080;', GESHI_NUMBER_HEX_PREFIX => 'color: #208080;', GESHI_NUMBER_FLT_SCI_SHORT => 'color:#800080;', GESHI_NUMBER_FLT_SCI_ZERO => 'color:#800080;', GESHI_NUMBER_FLT_NONSCI_F => 'color:#800080;', GESHI_NUMBER_FLT_NONSCI => 'color:#800080;' ), 'METHODS' => array( 1 => 'color: #007788;', 2 => 'color: #007788;' ), 'SYMBOLS' => array( 0 => 'color: #008000;', 1 => 'color: #000080;', 2 => 'color: #000040;', 3 => 'color: #000040;', 4 => 'color: #008080;' ), 'REGEXPS' => array( ), 'SCRIPT' => array( ) ), 'URLS' => array( 1 => '', 2 => '', 3 => '', 4 => '' ), 'OOLANG' => true, 'OBJECT_SPLITTERS' => array( 1 => '.', 2 => '::' ), 'REGEXPS' => array( ), 'STRICT_MODE_APPLIES' => GESHI_NEVER, 'SCRIPT_DELIMITERS' => array( ), 'HIGHLIGHT_STRICT_BLOCK' => array( ), 'TAB_WIDTH' => 4, 'PARSER_CONTROL' => array( 'KEYWORDS' => array( 'DISALLOWED_BEFORE' => "(? "(?![a-zA-Z0-9_\|%\\-])" ) ) ); ?>cppcheck-1.61/htdocs/site/js/000077500000000000000000000000001217722632100160705ustar00rootroot00000000000000cppcheck-1.61/htdocs/site/js/cppcheck.js000066400000000000000000000021301217722632100202020ustar00rootroot00000000000000/* jshint unused:false, jquery:true */ function addFile() { var name = prompt("Name of library/platform/etc", ""); if (name !== null) { window.location = "http://cppcheck.sourceforge.net/cgi-bin/addfile.cgi?name=" + name; } } function editFile(name, version) { window.location = "http://cppcheck.sourceforge.net/cgi-bin/edit.cgi?name=" + name + "&version=" + version; } function renameFile(name1, version) { var name2 = prompt("Name", name1); if (name2 !== null) { window.location = "http://cppcheck.sourceforge.net/cgi-bin/renamefile.cgi?name1=" + name1 + "&name2=" + name2; } } function deleteFile(name, version) { window.location = "http://cppcheck.sourceforge.net/cgi-bin/deletefile.cgi?name=" + name + "&version=" + version; } function checkCodeLength() { if (document.f.code.value.length > 1024) { alert("Code length exceeded."); return false; } return true; } $(document).ready(function() { $("#resultsTable").tableFilter(); }); $(function() { $("#github-commits").listCommits("danmar", "cppcheck", "master"); }); cppcheck-1.61/htdocs/site/js/github.js000066400000000000000000000033671217722632100177210ustar00rootroot00000000000000/*! Inspired by: http://aboutcode.net/2010/11/11/list-github-projects-using-javascript.html */ /* jshint quotmark:true, jquery:true */ // htmlEntities taken from http://css-tricks.com/snippets/javascript/htmlentities-for-javascript/ function htmlEntities(str) { return String(str).replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"'); } jQuery.fn.listCommits = function(username, repository, branch) { this.html('Querying GitHub for recent commits…'); var target = this; $.getJSON('https://api.github.com/repos/' + username + '/' + repository + '/commits?sha=' + branch + '&callback=?', function(response) { var commits = response.data, list = $('
          '); target.empty().append(list); $(commits).each(function(i) { var githubUrl = 'https://github.com/' + username + '/' + repository + '/commit/' + this.sha, shortMessage = htmlEntities(cutLines(this.commit.message)); if (this.author !== null) { list.append('
        • ' + shortMessage + ' by ' + this.author.login + '
        • '); } else { list.append('
        • ' + shortMessage + ' by ' + this.commit.author.name + '
        • '); } if (i === 9) { return false; } }); }); function cutLines(message) { var lineFeed = message.indexOf('\n'); if (lineFeed > -1) { return message.slice(0, lineFeed); } return message; } }; cppcheck-1.61/htdocs/site/js/jquery-1.10.2.min.js000066400000000000000000002656631217722632100212660ustar00rootroot00000000000000/*! jQuery v1.10.2 | (c) 2005, 2013 jQuery Foundation, Inc. | jquery.org/license //@ sourceMappingURL=jquery-1.10.2.min.map */ (function(e,t){var n,r,i=typeof t,o=e.location,a=e.document,s=a.documentElement,l=e.jQuery,u=e.$,c={},p=[],f="1.10.2",d=p.concat,h=p.push,g=p.slice,m=p.indexOf,y=c.toString,v=c.hasOwnProperty,b=f.trim,x=function(e,t){return new x.fn.init(e,t,r)},w=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,T=/\S+/g,C=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,N=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,k=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,E=/^[\],:{}\s]*$/,S=/(?:^|:|,)(?:\s*\[)+/g,A=/\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g,j=/"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g,D=/^-ms-/,L=/-([\da-z])/gi,H=function(e,t){return t.toUpperCase()},q=function(e){(a.addEventListener||"load"===e.type||"complete"===a.readyState)&&(_(),x.ready())},_=function(){a.addEventListener?(a.removeEventListener("DOMContentLoaded",q,!1),e.removeEventListener("load",q,!1)):(a.detachEvent("onreadystatechange",q),e.detachEvent("onload",q))};x.fn=x.prototype={jquery:f,constructor:x,init:function(e,n,r){var i,o;if(!e)return this;if("string"==typeof e){if(i="<"===e.charAt(0)&&">"===e.charAt(e.length-1)&&e.length>=3?[null,e,null]:N.exec(e),!i||!i[1]&&n)return!n||n.jquery?(n||r).find(e):this.constructor(n).find(e);if(i[1]){if(n=n instanceof x?n[0]:n,x.merge(this,x.parseHTML(i[1],n&&n.nodeType?n.ownerDocument||n:a,!0)),k.test(i[1])&&x.isPlainObject(n))for(i in n)x.isFunction(this[i])?this[i](n[i]):this.attr(i,n[i]);return this}if(o=a.getElementById(i[2]),o&&o.parentNode){if(o.id!==i[2])return r.find(e);this.length=1,this[0]=o}return this.context=a,this.selector=e,this}return e.nodeType?(this.context=this[0]=e,this.length=1,this):x.isFunction(e)?r.ready(e):(e.selector!==t&&(this.selector=e.selector,this.context=e.context),x.makeArray(e,this))},selector:"",length:0,toArray:function(){return g.call(this)},get:function(e){return null==e?this.toArray():0>e?this[this.length+e]:this[e]},pushStack:function(e){var t=x.merge(this.constructor(),e);return t.prevObject=this,t.context=this.context,t},each:function(e,t){return x.each(this,e,t)},ready:function(e){return x.ready.promise().done(e),this},slice:function(){return this.pushStack(g.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(e){var t=this.length,n=+e+(0>e?t:0);return this.pushStack(n>=0&&t>n?[this[n]]:[])},map:function(e){return this.pushStack(x.map(this,function(t,n){return e.call(t,n,t)}))},end:function(){return this.prevObject||this.constructor(null)},push:h,sort:[].sort,splice:[].splice},x.fn.init.prototype=x.fn,x.extend=x.fn.extend=function(){var e,n,r,i,o,a,s=arguments[0]||{},l=1,u=arguments.length,c=!1;for("boolean"==typeof s&&(c=s,s=arguments[1]||{},l=2),"object"==typeof s||x.isFunction(s)||(s={}),u===l&&(s=this,--l);u>l;l++)if(null!=(o=arguments[l]))for(i in o)e=s[i],r=o[i],s!==r&&(c&&r&&(x.isPlainObject(r)||(n=x.isArray(r)))?(n?(n=!1,a=e&&x.isArray(e)?e:[]):a=e&&x.isPlainObject(e)?e:{},s[i]=x.extend(c,a,r)):r!==t&&(s[i]=r));return s},x.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),noConflict:function(t){return e.$===x&&(e.$=u),t&&e.jQuery===x&&(e.jQuery=l),x},isReady:!1,readyWait:1,holdReady:function(e){e?x.readyWait++:x.ready(!0)},ready:function(e){if(e===!0?!--x.readyWait:!x.isReady){if(!a.body)return setTimeout(x.ready);x.isReady=!0,e!==!0&&--x.readyWait>0||(n.resolveWith(a,[x]),x.fn.trigger&&x(a).trigger("ready").off("ready"))}},isFunction:function(e){return"function"===x.type(e)},isArray:Array.isArray||function(e){return"array"===x.type(e)},isWindow:function(e){return null!=e&&e==e.window},isNumeric:function(e){return!isNaN(parseFloat(e))&&isFinite(e)},type:function(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?c[y.call(e)]||"object":typeof e},isPlainObject:function(e){var n;if(!e||"object"!==x.type(e)||e.nodeType||x.isWindow(e))return!1;try{if(e.constructor&&!v.call(e,"constructor")&&!v.call(e.constructor.prototype,"isPrototypeOf"))return!1}catch(r){return!1}if(x.support.ownLast)for(n in e)return v.call(e,n);for(n in e);return n===t||v.call(e,n)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},error:function(e){throw Error(e)},parseHTML:function(e,t,n){if(!e||"string"!=typeof e)return null;"boolean"==typeof t&&(n=t,t=!1),t=t||a;var r=k.exec(e),i=!n&&[];return r?[t.createElement(r[1])]:(r=x.buildFragment([e],t,i),i&&x(i).remove(),x.merge([],r.childNodes))},parseJSON:function(n){return e.JSON&&e.JSON.parse?e.JSON.parse(n):null===n?n:"string"==typeof n&&(n=x.trim(n),n&&E.test(n.replace(A,"@").replace(j,"]").replace(S,"")))?Function("return "+n)():(x.error("Invalid JSON: "+n),t)},parseXML:function(n){var r,i;if(!n||"string"!=typeof n)return null;try{e.DOMParser?(i=new DOMParser,r=i.parseFromString(n,"text/xml")):(r=new ActiveXObject("Microsoft.XMLDOM"),r.async="false",r.loadXML(n))}catch(o){r=t}return r&&r.documentElement&&!r.getElementsByTagName("parsererror").length||x.error("Invalid XML: "+n),r},noop:function(){},globalEval:function(t){t&&x.trim(t)&&(e.execScript||function(t){e.eval.call(e,t)})(t)},camelCase:function(e){return e.replace(D,"ms-").replace(L,H)},nodeName:function(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()},each:function(e,t,n){var r,i=0,o=e.length,a=M(e);if(n){if(a){for(;o>i;i++)if(r=t.apply(e[i],n),r===!1)break}else for(i in e)if(r=t.apply(e[i],n),r===!1)break}else if(a){for(;o>i;i++)if(r=t.call(e[i],i,e[i]),r===!1)break}else for(i in e)if(r=t.call(e[i],i,e[i]),r===!1)break;return e},trim:b&&!b.call("\ufeff\u00a0")?function(e){return null==e?"":b.call(e)}:function(e){return null==e?"":(e+"").replace(C,"")},makeArray:function(e,t){var n=t||[];return null!=e&&(M(Object(e))?x.merge(n,"string"==typeof e?[e]:e):h.call(n,e)),n},inArray:function(e,t,n){var r;if(t){if(m)return m.call(t,e,n);for(r=t.length,n=n?0>n?Math.max(0,r+n):n:0;r>n;n++)if(n in t&&t[n]===e)return n}return-1},merge:function(e,n){var r=n.length,i=e.length,o=0;if("number"==typeof r)for(;r>o;o++)e[i++]=n[o];else while(n[o]!==t)e[i++]=n[o++];return e.length=i,e},grep:function(e,t,n){var r,i=[],o=0,a=e.length;for(n=!!n;a>o;o++)r=!!t(e[o],o),n!==r&&i.push(e[o]);return i},map:function(e,t,n){var r,i=0,o=e.length,a=M(e),s=[];if(a)for(;o>i;i++)r=t(e[i],i,n),null!=r&&(s[s.length]=r);else for(i in e)r=t(e[i],i,n),null!=r&&(s[s.length]=r);return d.apply([],s)},guid:1,proxy:function(e,n){var r,i,o;return"string"==typeof n&&(o=e[n],n=e,e=o),x.isFunction(e)?(r=g.call(arguments,2),i=function(){return e.apply(n||this,r.concat(g.call(arguments)))},i.guid=e.guid=e.guid||x.guid++,i):t},access:function(e,n,r,i,o,a,s){var l=0,u=e.length,c=null==r;if("object"===x.type(r)){o=!0;for(l in r)x.access(e,n,l,r[l],!0,a,s)}else if(i!==t&&(o=!0,x.isFunction(i)||(s=!0),c&&(s?(n.call(e,i),n=null):(c=n,n=function(e,t,n){return c.call(x(e),n)})),n))for(;u>l;l++)n(e[l],r,s?i:i.call(e[l],l,n(e[l],r)));return o?e:c?n.call(e):u?n(e[0],r):a},now:function(){return(new Date).getTime()},swap:function(e,t,n,r){var i,o,a={};for(o in t)a[o]=e.style[o],e.style[o]=t[o];i=n.apply(e,r||[]);for(o in t)e.style[o]=a[o];return i}}),x.ready.promise=function(t){if(!n)if(n=x.Deferred(),"complete"===a.readyState)setTimeout(x.ready);else if(a.addEventListener)a.addEventListener("DOMContentLoaded",q,!1),e.addEventListener("load",q,!1);else{a.attachEvent("onreadystatechange",q),e.attachEvent("onload",q);var r=!1;try{r=null==e.frameElement&&a.documentElement}catch(i){}r&&r.doScroll&&function o(){if(!x.isReady){try{r.doScroll("left")}catch(e){return setTimeout(o,50)}_(),x.ready()}}()}return n.promise(t)},x.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(e,t){c["[object "+t+"]"]=t.toLowerCase()});function M(e){var t=e.length,n=x.type(e);return x.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||"function"!==n&&(0===t||"number"==typeof t&&t>0&&t-1 in e)}r=x(a),function(e,t){var n,r,i,o,a,s,l,u,c,p,f,d,h,g,m,y,v,b="sizzle"+-new Date,w=e.document,T=0,C=0,N=st(),k=st(),E=st(),S=!1,A=function(e,t){return e===t?(S=!0,0):0},j=typeof t,D=1<<31,L={}.hasOwnProperty,H=[],q=H.pop,_=H.push,M=H.push,O=H.slice,F=H.indexOf||function(e){var t=0,n=this.length;for(;n>t;t++)if(this[t]===e)return t;return-1},B="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",P="[\\x20\\t\\r\\n\\f]",R="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",W=R.replace("w","w#"),$="\\["+P+"*("+R+")"+P+"*(?:([*^$|!~]?=)"+P+"*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|("+W+")|)|)"+P+"*\\]",I=":("+R+")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|"+$.replace(3,8)+")*)|.*)\\)|)",z=RegExp("^"+P+"+|((?:^|[^\\\\])(?:\\\\.)*)"+P+"+$","g"),X=RegExp("^"+P+"*,"+P+"*"),U=RegExp("^"+P+"*([>+~]|"+P+")"+P+"*"),V=RegExp(P+"*[+~]"),Y=RegExp("="+P+"*([^\\]'\"]*)"+P+"*\\]","g"),J=RegExp(I),G=RegExp("^"+W+"$"),Q={ID:RegExp("^#("+R+")"),CLASS:RegExp("^\\.("+R+")"),TAG:RegExp("^("+R.replace("w","w*")+")"),ATTR:RegExp("^"+$),PSEUDO:RegExp("^"+I),CHILD:RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+P+"*(even|odd|(([+-]|)(\\d*)n|)"+P+"*(?:([+-]|)"+P+"*(\\d+)|))"+P+"*\\)|)","i"),bool:RegExp("^(?:"+B+")$","i"),needsContext:RegExp("^"+P+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+P+"*((?:-\\d)?\\d*)"+P+"*\\)|)(?=[^-]|$)","i")},K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,et=/^(?:input|select|textarea|button)$/i,tt=/^h\d$/i,nt=/'|\\/g,rt=RegExp("\\\\([\\da-f]{1,6}"+P+"?|("+P+")|.)","ig"),it=function(e,t,n){var r="0x"+t-65536;return r!==r||n?t:0>r?String.fromCharCode(r+65536):String.fromCharCode(55296|r>>10,56320|1023&r)};try{M.apply(H=O.call(w.childNodes),w.childNodes),H[w.childNodes.length].nodeType}catch(ot){M={apply:H.length?function(e,t){_.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function at(e,t,n,i){var o,a,s,l,u,c,d,m,y,x;if((t?t.ownerDocument||t:w)!==f&&p(t),t=t||f,n=n||[],!e||"string"!=typeof e)return n;if(1!==(l=t.nodeType)&&9!==l)return[];if(h&&!i){if(o=Z.exec(e))if(s=o[1]){if(9===l){if(a=t.getElementById(s),!a||!a.parentNode)return n;if(a.id===s)return n.push(a),n}else if(t.ownerDocument&&(a=t.ownerDocument.getElementById(s))&&v(t,a)&&a.id===s)return n.push(a),n}else{if(o[2])return M.apply(n,t.getElementsByTagName(e)),n;if((s=o[3])&&r.getElementsByClassName&&t.getElementsByClassName)return M.apply(n,t.getElementsByClassName(s)),n}if(r.qsa&&(!g||!g.test(e))){if(m=d=b,y=t,x=9===l&&e,1===l&&"object"!==t.nodeName.toLowerCase()){c=mt(e),(d=t.getAttribute("id"))?m=d.replace(nt,"\\$&"):t.setAttribute("id",m),m="[id='"+m+"'] ",u=c.length;while(u--)c[u]=m+yt(c[u]);y=V.test(e)&&t.parentNode||t,x=c.join(",")}if(x)try{return M.apply(n,y.querySelectorAll(x)),n}catch(T){}finally{d||t.removeAttribute("id")}}}return kt(e.replace(z,"$1"),t,n,i)}function st(){var e=[];function t(n,r){return e.push(n+=" ")>o.cacheLength&&delete t[e.shift()],t[n]=r}return t}function lt(e){return e[b]=!0,e}function ut(e){var t=f.createElement("div");try{return!!e(t)}catch(n){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function ct(e,t){var n=e.split("|"),r=e.length;while(r--)o.attrHandle[n[r]]=t}function pt(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&(~t.sourceIndex||D)-(~e.sourceIndex||D);if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function ft(e){return function(t){var n=t.nodeName.toLowerCase();return"input"===n&&t.type===e}}function dt(e){return function(t){var n=t.nodeName.toLowerCase();return("input"===n||"button"===n)&&t.type===e}}function ht(e){return lt(function(t){return t=+t,lt(function(n,r){var i,o=e([],n.length,t),a=o.length;while(a--)n[i=o[a]]&&(n[i]=!(r[i]=n[i]))})})}s=at.isXML=function(e){var t=e&&(e.ownerDocument||e).documentElement;return t?"HTML"!==t.nodeName:!1},r=at.support={},p=at.setDocument=function(e){var n=e?e.ownerDocument||e:w,i=n.defaultView;return n!==f&&9===n.nodeType&&n.documentElement?(f=n,d=n.documentElement,h=!s(n),i&&i.attachEvent&&i!==i.top&&i.attachEvent("onbeforeunload",function(){p()}),r.attributes=ut(function(e){return e.className="i",!e.getAttribute("className")}),r.getElementsByTagName=ut(function(e){return e.appendChild(n.createComment("")),!e.getElementsByTagName("*").length}),r.getElementsByClassName=ut(function(e){return e.innerHTML="
          ",e.firstChild.className="i",2===e.getElementsByClassName("i").length}),r.getById=ut(function(e){return d.appendChild(e).id=b,!n.getElementsByName||!n.getElementsByName(b).length}),r.getById?(o.find.ID=function(e,t){if(typeof t.getElementById!==j&&h){var n=t.getElementById(e);return n&&n.parentNode?[n]:[]}},o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){return e.getAttribute("id")===t}}):(delete o.find.ID,o.filter.ID=function(e){var t=e.replace(rt,it);return function(e){var n=typeof e.getAttributeNode!==j&&e.getAttributeNode("id");return n&&n.value===t}}),o.find.TAG=r.getElementsByTagName?function(e,n){return typeof n.getElementsByTagName!==j?n.getElementsByTagName(e):t}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},o.find.CLASS=r.getElementsByClassName&&function(e,n){return typeof n.getElementsByClassName!==j&&h?n.getElementsByClassName(e):t},m=[],g=[],(r.qsa=K.test(n.querySelectorAll))&&(ut(function(e){e.innerHTML="",e.querySelectorAll("[selected]").length||g.push("\\["+P+"*(?:value|"+B+")"),e.querySelectorAll(":checked").length||g.push(":checked")}),ut(function(e){var t=n.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("t",""),e.querySelectorAll("[t^='']").length&&g.push("[*^$]="+P+"*(?:''|\"\")"),e.querySelectorAll(":enabled").length||g.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),g.push(",.*:")})),(r.matchesSelector=K.test(y=d.webkitMatchesSelector||d.mozMatchesSelector||d.oMatchesSelector||d.msMatchesSelector))&&ut(function(e){r.disconnectedMatch=y.call(e,"div"),y.call(e,"[s!='']:x"),m.push("!=",I)}),g=g.length&&RegExp(g.join("|")),m=m.length&&RegExp(m.join("|")),v=K.test(d.contains)||d.compareDocumentPosition?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},A=d.compareDocumentPosition?function(e,t){if(e===t)return S=!0,0;var i=t.compareDocumentPosition&&e.compareDocumentPosition&&e.compareDocumentPosition(t);return i?1&i||!r.sortDetached&&t.compareDocumentPosition(e)===i?e===n||v(w,e)?-1:t===n||v(w,t)?1:c?F.call(c,e)-F.call(c,t):0:4&i?-1:1:e.compareDocumentPosition?-1:1}:function(e,t){var r,i=0,o=e.parentNode,a=t.parentNode,s=[e],l=[t];if(e===t)return S=!0,0;if(!o||!a)return e===n?-1:t===n?1:o?-1:a?1:c?F.call(c,e)-F.call(c,t):0;if(o===a)return pt(e,t);r=e;while(r=r.parentNode)s.unshift(r);r=t;while(r=r.parentNode)l.unshift(r);while(s[i]===l[i])i++;return i?pt(s[i],l[i]):s[i]===w?-1:l[i]===w?1:0},n):f},at.matches=function(e,t){return at(e,null,null,t)},at.matchesSelector=function(e,t){if((e.ownerDocument||e)!==f&&p(e),t=t.replace(Y,"='$1']"),!(!r.matchesSelector||!h||m&&m.test(t)||g&&g.test(t)))try{var n=y.call(e,t);if(n||r.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(i){}return at(t,f,null,[e]).length>0},at.contains=function(e,t){return(e.ownerDocument||e)!==f&&p(e),v(e,t)},at.attr=function(e,n){(e.ownerDocument||e)!==f&&p(e);var i=o.attrHandle[n.toLowerCase()],a=i&&L.call(o.attrHandle,n.toLowerCase())?i(e,n,!h):t;return a===t?r.attributes||!h?e.getAttribute(n):(a=e.getAttributeNode(n))&&a.specified?a.value:null:a},at.error=function(e){throw Error("Syntax error, unrecognized expression: "+e)},at.uniqueSort=function(e){var t,n=[],i=0,o=0;if(S=!r.detectDuplicates,c=!r.sortStable&&e.slice(0),e.sort(A),S){while(t=e[o++])t===e[o]&&(i=n.push(o));while(i--)e.splice(n[i],1)}return e},a=at.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=a(e)}else if(3===i||4===i)return e.nodeValue}else for(;t=e[r];r++)n+=a(t);return n},o=at.selectors={cacheLength:50,createPseudo:lt,match:Q,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(rt,it),e[3]=(e[4]||e[5]||"").replace(rt,it),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||at.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&at.error(e[0]),e},PSEUDO:function(e){var n,r=!e[5]&&e[2];return Q.CHILD.test(e[0])?null:(e[3]&&e[4]!==t?e[2]=e[4]:r&&J.test(r)&&(n=mt(r,!0))&&(n=r.indexOf(")",r.length-n)-r.length)&&(e[0]=e[0].slice(0,n),e[2]=r.slice(0,n)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(rt,it).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=N[e+" "];return t||(t=RegExp("(^|"+P+")"+e+"("+P+"|$)"))&&N(e,function(e){return t.test("string"==typeof e.className&&e.className||typeof e.getAttribute!==j&&e.getAttribute("class")||"")})},ATTR:function(e,t,n){return function(r){var i=at.attr(r,e);return null==i?"!="===t:t?(i+="","="===t?i===n:"!="===t?i!==n:"^="===t?n&&0===i.indexOf(n):"*="===t?n&&i.indexOf(n)>-1:"$="===t?n&&i.slice(-n.length)===n:"~="===t?(" "+i+" ").indexOf(n)>-1:"|="===t?i===n||i.slice(0,n.length+1)===n+"-":!1):!0}},CHILD:function(e,t,n,r,i){var o="nth"!==e.slice(0,3),a="last"!==e.slice(-4),s="of-type"===t;return 1===r&&0===i?function(e){return!!e.parentNode}:function(t,n,l){var u,c,p,f,d,h,g=o!==a?"nextSibling":"previousSibling",m=t.parentNode,y=s&&t.nodeName.toLowerCase(),v=!l&&!s;if(m){if(o){while(g){p=t;while(p=p[g])if(s?p.nodeName.toLowerCase()===y:1===p.nodeType)return!1;h=g="only"===e&&!h&&"nextSibling"}return!0}if(h=[a?m.firstChild:m.lastChild],a&&v){c=m[b]||(m[b]={}),u=c[e]||[],d=u[0]===T&&u[1],f=u[0]===T&&u[2],p=d&&m.childNodes[d];while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if(1===p.nodeType&&++f&&p===t){c[e]=[T,d,f];break}}else if(v&&(u=(t[b]||(t[b]={}))[e])&&u[0]===T)f=u[1];else while(p=++d&&p&&p[g]||(f=d=0)||h.pop())if((s?p.nodeName.toLowerCase()===y:1===p.nodeType)&&++f&&(v&&((p[b]||(p[b]={}))[e]=[T,f]),p===t))break;return f-=i,f===r||0===f%r&&f/r>=0}}},PSEUDO:function(e,t){var n,r=o.pseudos[e]||o.setFilters[e.toLowerCase()]||at.error("unsupported pseudo: "+e);return r[b]?r(t):r.length>1?(n=[e,e,"",t],o.setFilters.hasOwnProperty(e.toLowerCase())?lt(function(e,n){var i,o=r(e,t),a=o.length;while(a--)i=F.call(e,o[a]),e[i]=!(n[i]=o[a])}):function(e){return r(e,0,n)}):r}},pseudos:{not:lt(function(e){var t=[],n=[],r=l(e.replace(z,"$1"));return r[b]?lt(function(e,t,n,i){var o,a=r(e,null,i,[]),s=e.length;while(s--)(o=a[s])&&(e[s]=!(t[s]=o))}):function(e,i,o){return t[0]=e,r(t,null,o,n),!n.pop()}}),has:lt(function(e){return function(t){return at(e,t).length>0}}),contains:lt(function(e){return function(t){return(t.textContent||t.innerText||a(t)).indexOf(e)>-1}}),lang:lt(function(e){return G.test(e||"")||at.error("unsupported lang: "+e),e=e.replace(rt,it).toLowerCase(),function(t){var n;do if(n=h?t.lang:t.getAttribute("xml:lang")||t.getAttribute("lang"))return n=n.toLowerCase(),n===e||0===n.indexOf(e+"-");while((t=t.parentNode)&&1===t.nodeType);return!1}}),target:function(t){var n=e.location&&e.location.hash;return n&&n.slice(1)===t.id},root:function(e){return e===d},focus:function(e){return e===f.activeElement&&(!f.hasFocus||f.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:function(e){return e.disabled===!1},disabled:function(e){return e.disabled===!0},checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,e.selected===!0},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeName>"@"||3===e.nodeType||4===e.nodeType)return!1;return!0},parent:function(e){return!o.pseudos.empty(e)},header:function(e){return tt.test(e.nodeName)},input:function(e){return et.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||t.toLowerCase()===e.type)},first:ht(function(){return[0]}),last:ht(function(e,t){return[t-1]}),eq:ht(function(e,t,n){return[0>n?n+t:n]}),even:ht(function(e,t){var n=0;for(;t>n;n+=2)e.push(n);return e}),odd:ht(function(e,t){var n=1;for(;t>n;n+=2)e.push(n);return e}),lt:ht(function(e,t,n){var r=0>n?n+t:n;for(;--r>=0;)e.push(r);return e}),gt:ht(function(e,t,n){var r=0>n?n+t:n;for(;t>++r;)e.push(r);return e})}},o.pseudos.nth=o.pseudos.eq;for(n in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})o.pseudos[n]=ft(n);for(n in{submit:!0,reset:!0})o.pseudos[n]=dt(n);function gt(){}gt.prototype=o.filters=o.pseudos,o.setFilters=new gt;function mt(e,t){var n,r,i,a,s,l,u,c=k[e+" "];if(c)return t?0:c.slice(0);s=e,l=[],u=o.preFilter;while(s){(!n||(r=X.exec(s)))&&(r&&(s=s.slice(r[0].length)||s),l.push(i=[])),n=!1,(r=U.exec(s))&&(n=r.shift(),i.push({value:n,type:r[0].replace(z," ")}),s=s.slice(n.length));for(a in o.filter)!(r=Q[a].exec(s))||u[a]&&!(r=u[a](r))||(n=r.shift(),i.push({value:n,type:a,matches:r}),s=s.slice(n.length));if(!n)break}return t?s.length:s?at.error(e):k(e,l).slice(0)}function yt(e){var t=0,n=e.length,r="";for(;n>t;t++)r+=e[t].value;return r}function vt(e,t,n){var r=t.dir,o=n&&"parentNode"===r,a=C++;return t.first?function(t,n,i){while(t=t[r])if(1===t.nodeType||o)return e(t,n,i)}:function(t,n,s){var l,u,c,p=T+" "+a;if(s){while(t=t[r])if((1===t.nodeType||o)&&e(t,n,s))return!0}else while(t=t[r])if(1===t.nodeType||o)if(c=t[b]||(t[b]={}),(u=c[r])&&u[0]===p){if((l=u[1])===!0||l===i)return l===!0}else if(u=c[r]=[p],u[1]=e(t,n,s)||i,u[1]===!0)return!0}}function bt(e){return e.length>1?function(t,n,r){var i=e.length;while(i--)if(!e[i](t,n,r))return!1;return!0}:e[0]}function xt(e,t,n,r,i){var o,a=[],s=0,l=e.length,u=null!=t;for(;l>s;s++)(o=e[s])&&(!n||n(o,r,i))&&(a.push(o),u&&t.push(s));return a}function wt(e,t,n,r,i,o){return r&&!r[b]&&(r=wt(r)),i&&!i[b]&&(i=wt(i,o)),lt(function(o,a,s,l){var u,c,p,f=[],d=[],h=a.length,g=o||Nt(t||"*",s.nodeType?[s]:s,[]),m=!e||!o&&t?g:xt(g,f,e,s,l),y=n?i||(o?e:h||r)?[]:a:m;if(n&&n(m,y,s,l),r){u=xt(y,d),r(u,[],s,l),c=u.length;while(c--)(p=u[c])&&(y[d[c]]=!(m[d[c]]=p))}if(o){if(i||e){if(i){u=[],c=y.length;while(c--)(p=y[c])&&u.push(m[c]=p);i(null,y=[],u,l)}c=y.length;while(c--)(p=y[c])&&(u=i?F.call(o,p):f[c])>-1&&(o[u]=!(a[u]=p))}}else y=xt(y===a?y.splice(h,y.length):y),i?i(null,a,y,l):M.apply(a,y)})}function Tt(e){var t,n,r,i=e.length,a=o.relative[e[0].type],s=a||o.relative[" "],l=a?1:0,c=vt(function(e){return e===t},s,!0),p=vt(function(e){return F.call(t,e)>-1},s,!0),f=[function(e,n,r){return!a&&(r||n!==u)||((t=n).nodeType?c(e,n,r):p(e,n,r))}];for(;i>l;l++)if(n=o.relative[e[l].type])f=[vt(bt(f),n)];else{if(n=o.filter[e[l].type].apply(null,e[l].matches),n[b]){for(r=++l;i>r;r++)if(o.relative[e[r].type])break;return wt(l>1&&bt(f),l>1&&yt(e.slice(0,l-1).concat({value:" "===e[l-2].type?"*":""})).replace(z,"$1"),n,r>l&&Tt(e.slice(l,r)),i>r&&Tt(e=e.slice(r)),i>r&&yt(e))}f.push(n)}return bt(f)}function Ct(e,t){var n=0,r=t.length>0,a=e.length>0,s=function(s,l,c,p,d){var h,g,m,y=[],v=0,b="0",x=s&&[],w=null!=d,C=u,N=s||a&&o.find.TAG("*",d&&l.parentNode||l),k=T+=null==C?1:Math.random()||.1;for(w&&(u=l!==f&&l,i=n);null!=(h=N[b]);b++){if(a&&h){g=0;while(m=e[g++])if(m(h,l,c)){p.push(h);break}w&&(T=k,i=++n)}r&&((h=!m&&h)&&v--,s&&x.push(h))}if(v+=b,r&&b!==v){g=0;while(m=t[g++])m(x,y,l,c);if(s){if(v>0)while(b--)x[b]||y[b]||(y[b]=q.call(p));y=xt(y)}M.apply(p,y),w&&!s&&y.length>0&&v+t.length>1&&at.uniqueSort(p)}return w&&(T=k,u=C),x};return r?lt(s):s}l=at.compile=function(e,t){var n,r=[],i=[],o=E[e+" "];if(!o){t||(t=mt(e)),n=t.length;while(n--)o=Tt(t[n]),o[b]?r.push(o):i.push(o);o=E(e,Ct(i,r))}return o};function Nt(e,t,n){var r=0,i=t.length;for(;i>r;r++)at(e,t[r],n);return n}function kt(e,t,n,i){var a,s,u,c,p,f=mt(e);if(!i&&1===f.length){if(s=f[0]=f[0].slice(0),s.length>2&&"ID"===(u=s[0]).type&&r.getById&&9===t.nodeType&&h&&o.relative[s[1].type]){if(t=(o.find.ID(u.matches[0].replace(rt,it),t)||[])[0],!t)return n;e=e.slice(s.shift().value.length)}a=Q.needsContext.test(e)?0:s.length;while(a--){if(u=s[a],o.relative[c=u.type])break;if((p=o.find[c])&&(i=p(u.matches[0].replace(rt,it),V.test(s[0].type)&&t.parentNode||t))){if(s.splice(a,1),e=i.length&&yt(s),!e)return M.apply(n,i),n;break}}}return l(e,f)(i,t,!h,n,V.test(e)),n}r.sortStable=b.split("").sort(A).join("")===b,r.detectDuplicates=S,p(),r.sortDetached=ut(function(e){return 1&e.compareDocumentPosition(f.createElement("div"))}),ut(function(e){return e.innerHTML="","#"===e.firstChild.getAttribute("href")})||ct("type|href|height|width",function(e,n,r){return r?t:e.getAttribute(n,"type"===n.toLowerCase()?1:2)}),r.attributes&&ut(function(e){return e.innerHTML="",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||ct("value",function(e,n,r){return r||"input"!==e.nodeName.toLowerCase()?t:e.defaultValue}),ut(function(e){return null==e.getAttribute("disabled")})||ct(B,function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&i.specified?i.value:e[n]===!0?n.toLowerCase():null}),x.find=at,x.expr=at.selectors,x.expr[":"]=x.expr.pseudos,x.unique=at.uniqueSort,x.text=at.getText,x.isXMLDoc=at.isXML,x.contains=at.contains}(e);var O={};function F(e){var t=O[e]={};return x.each(e.match(T)||[],function(e,n){t[n]=!0}),t}x.Callbacks=function(e){e="string"==typeof e?O[e]||F(e):x.extend({},e);var n,r,i,o,a,s,l=[],u=!e.once&&[],c=function(t){for(r=e.memory&&t,i=!0,a=s||0,s=0,o=l.length,n=!0;l&&o>a;a++)if(l[a].apply(t[0],t[1])===!1&&e.stopOnFalse){r=!1;break}n=!1,l&&(u?u.length&&c(u.shift()):r?l=[]:p.disable())},p={add:function(){if(l){var t=l.length;(function i(t){x.each(t,function(t,n){var r=x.type(n);"function"===r?e.unique&&p.has(n)||l.push(n):n&&n.length&&"string"!==r&&i(n)})})(arguments),n?o=l.length:r&&(s=t,c(r))}return this},remove:function(){return l&&x.each(arguments,function(e,t){var r;while((r=x.inArray(t,l,r))>-1)l.splice(r,1),n&&(o>=r&&o--,a>=r&&a--)}),this},has:function(e){return e?x.inArray(e,l)>-1:!(!l||!l.length)},empty:function(){return l=[],o=0,this},disable:function(){return l=u=r=t,this},disabled:function(){return!l},lock:function(){return u=t,r||p.disable(),this},locked:function(){return!u},fireWith:function(e,t){return!l||i&&!u||(t=t||[],t=[e,t.slice?t.slice():t],n?u.push(t):c(t)),this},fire:function(){return p.fireWith(this,arguments),this},fired:function(){return!!i}};return p},x.extend({Deferred:function(e){var t=[["resolve","done",x.Callbacks("once memory"),"resolved"],["reject","fail",x.Callbacks("once memory"),"rejected"],["notify","progress",x.Callbacks("memory")]],n="pending",r={state:function(){return n},always:function(){return i.done(arguments).fail(arguments),this},then:function(){var e=arguments;return x.Deferred(function(n){x.each(t,function(t,o){var a=o[0],s=x.isFunction(e[t])&&e[t];i[o[1]](function(){var e=s&&s.apply(this,arguments);e&&x.isFunction(e.promise)?e.promise().done(n.resolve).fail(n.reject).progress(n.notify):n[a+"With"](this===r?n.promise():this,s?[e]:arguments)})}),e=null}).promise()},promise:function(e){return null!=e?x.extend(e,r):r}},i={};return r.pipe=r.then,x.each(t,function(e,o){var a=o[2],s=o[3];r[o[1]]=a.add,s&&a.add(function(){n=s},t[1^e][2].disable,t[2][2].lock),i[o[0]]=function(){return i[o[0]+"With"](this===i?r:this,arguments),this},i[o[0]+"With"]=a.fireWith}),r.promise(i),e&&e.call(i,i),i},when:function(e){var t=0,n=g.call(arguments),r=n.length,i=1!==r||e&&x.isFunction(e.promise)?r:0,o=1===i?e:x.Deferred(),a=function(e,t,n){return function(r){t[e]=this,n[e]=arguments.length>1?g.call(arguments):r,n===s?o.notifyWith(t,n):--i||o.resolveWith(t,n)}},s,l,u;if(r>1)for(s=Array(r),l=Array(r),u=Array(r);r>t;t++)n[t]&&x.isFunction(n[t].promise)?n[t].promise().done(a(t,u,n)).fail(o.reject).progress(a(t,l,s)):--i;return i||o.resolveWith(u,n),o.promise()}}),x.support=function(t){var n,r,o,s,l,u,c,p,f,d=a.createElement("div");if(d.setAttribute("className","t"),d.innerHTML="
          a",n=d.getElementsByTagName("*")||[],r=d.getElementsByTagName("a")[0],!r||!r.style||!n.length)return t;s=a.createElement("select"),u=s.appendChild(a.createElement("option")),o=d.getElementsByTagName("input")[0],r.style.cssText="top:1px;float:left;opacity:.5",t.getSetAttribute="t"!==d.className,t.leadingWhitespace=3===d.firstChild.nodeType,t.tbody=!d.getElementsByTagName("tbody").length,t.htmlSerialize=!!d.getElementsByTagName("link").length,t.style=/top/.test(r.getAttribute("style")),t.hrefNormalized="/a"===r.getAttribute("href"),t.opacity=/^0.5/.test(r.style.opacity),t.cssFloat=!!r.style.cssFloat,t.checkOn=!!o.value,t.optSelected=u.selected,t.enctype=!!a.createElement("form").enctype,t.html5Clone="<:nav>"!==a.createElement("nav").cloneNode(!0).outerHTML,t.inlineBlockNeedsLayout=!1,t.shrinkWrapBlocks=!1,t.pixelPosition=!1,t.deleteExpando=!0,t.noCloneEvent=!0,t.reliableMarginRight=!0,t.boxSizingReliable=!0,o.checked=!0,t.noCloneChecked=o.cloneNode(!0).checked,s.disabled=!0,t.optDisabled=!u.disabled;try{delete d.test}catch(h){t.deleteExpando=!1}o=a.createElement("input"),o.setAttribute("value",""),t.input=""===o.getAttribute("value"),o.value="t",o.setAttribute("type","radio"),t.radioValue="t"===o.value,o.setAttribute("checked","t"),o.setAttribute("name","t"),l=a.createDocumentFragment(),l.appendChild(o),t.appendChecked=o.checked,t.checkClone=l.cloneNode(!0).cloneNode(!0).lastChild.checked,d.attachEvent&&(d.attachEvent("onclick",function(){t.noCloneEvent=!1}),d.cloneNode(!0).click());for(f in{submit:!0,change:!0,focusin:!0})d.setAttribute(c="on"+f,"t"),t[f+"Bubbles"]=c in e||d.attributes[c].expando===!1;d.style.backgroundClip="content-box",d.cloneNode(!0).style.backgroundClip="",t.clearCloneStyle="content-box"===d.style.backgroundClip;for(f in x(t))break;return t.ownLast="0"!==f,x(function(){var n,r,o,s="padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;",l=a.getElementsByTagName("body")[0];l&&(n=a.createElement("div"),n.style.cssText="border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px",l.appendChild(n).appendChild(d),d.innerHTML="
          t
          ",o=d.getElementsByTagName("td"),o[0].style.cssText="padding:0;margin:0;border:0;display:none",p=0===o[0].offsetHeight,o[0].style.display="",o[1].style.display="none",t.reliableHiddenOffsets=p&&0===o[0].offsetHeight,d.innerHTML="",d.style.cssText="box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;",x.swap(l,null!=l.style.zoom?{zoom:1}:{},function(){t.boxSizing=4===d.offsetWidth}),e.getComputedStyle&&(t.pixelPosition="1%"!==(e.getComputedStyle(d,null)||{}).top,t.boxSizingReliable="4px"===(e.getComputedStyle(d,null)||{width:"4px"}).width,r=d.appendChild(a.createElement("div")),r.style.cssText=d.style.cssText=s,r.style.marginRight=r.style.width="0",d.style.width="1px",t.reliableMarginRight=!parseFloat((e.getComputedStyle(r,null)||{}).marginRight)),typeof d.style.zoom!==i&&(d.innerHTML="",d.style.cssText=s+"width:1px;padding:1px;display:inline;zoom:1",t.inlineBlockNeedsLayout=3===d.offsetWidth,d.style.display="block",d.innerHTML="
          ",d.firstChild.style.width="5px",t.shrinkWrapBlocks=3!==d.offsetWidth,t.inlineBlockNeedsLayout&&(l.style.zoom=1)),l.removeChild(n),n=d=o=r=null)}),n=s=l=u=r=o=null,t }({});var B=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,P=/([A-Z])/g;function R(e,n,r,i){if(x.acceptData(e)){var o,a,s=x.expando,l=e.nodeType,u=l?x.cache:e,c=l?e[s]:e[s]&&s;if(c&&u[c]&&(i||u[c].data)||r!==t||"string"!=typeof n)return c||(c=l?e[s]=p.pop()||x.guid++:s),u[c]||(u[c]=l?{}:{toJSON:x.noop}),("object"==typeof n||"function"==typeof n)&&(i?u[c]=x.extend(u[c],n):u[c].data=x.extend(u[c].data,n)),a=u[c],i||(a.data||(a.data={}),a=a.data),r!==t&&(a[x.camelCase(n)]=r),"string"==typeof n?(o=a[n],null==o&&(o=a[x.camelCase(n)])):o=a,o}}function W(e,t,n){if(x.acceptData(e)){var r,i,o=e.nodeType,a=o?x.cache:e,s=o?e[x.expando]:x.expando;if(a[s]){if(t&&(r=n?a[s]:a[s].data)){x.isArray(t)?t=t.concat(x.map(t,x.camelCase)):t in r?t=[t]:(t=x.camelCase(t),t=t in r?[t]:t.split(" ")),i=t.length;while(i--)delete r[t[i]];if(n?!I(r):!x.isEmptyObject(r))return}(n||(delete a[s].data,I(a[s])))&&(o?x.cleanData([e],!0):x.support.deleteExpando||a!=a.window?delete a[s]:a[s]=null)}}}x.extend({cache:{},noData:{applet:!0,embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(e){return e=e.nodeType?x.cache[e[x.expando]]:e[x.expando],!!e&&!I(e)},data:function(e,t,n){return R(e,t,n)},removeData:function(e,t){return W(e,t)},_data:function(e,t,n){return R(e,t,n,!0)},_removeData:function(e,t){return W(e,t,!0)},acceptData:function(e){if(e.nodeType&&1!==e.nodeType&&9!==e.nodeType)return!1;var t=e.nodeName&&x.noData[e.nodeName.toLowerCase()];return!t||t!==!0&&e.getAttribute("classid")===t}}),x.fn.extend({data:function(e,n){var r,i,o=null,a=0,s=this[0];if(e===t){if(this.length&&(o=x.data(s),1===s.nodeType&&!x._data(s,"parsedAttrs"))){for(r=s.attributes;r.length>a;a++)i=r[a].name,0===i.indexOf("data-")&&(i=x.camelCase(i.slice(5)),$(s,i,o[i]));x._data(s,"parsedAttrs",!0)}return o}return"object"==typeof e?this.each(function(){x.data(this,e)}):arguments.length>1?this.each(function(){x.data(this,e,n)}):s?$(s,e,x.data(s,e)):null},removeData:function(e){return this.each(function(){x.removeData(this,e)})}});function $(e,n,r){if(r===t&&1===e.nodeType){var i="data-"+n.replace(P,"-$1").toLowerCase();if(r=e.getAttribute(i),"string"==typeof r){try{r="true"===r?!0:"false"===r?!1:"null"===r?null:+r+""===r?+r:B.test(r)?x.parseJSON(r):r}catch(o){}x.data(e,n,r)}else r=t}return r}function I(e){var t;for(t in e)if(("data"!==t||!x.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}x.extend({queue:function(e,n,r){var i;return e?(n=(n||"fx")+"queue",i=x._data(e,n),r&&(!i||x.isArray(r)?i=x._data(e,n,x.makeArray(r)):i.push(r)),i||[]):t},dequeue:function(e,t){t=t||"fx";var n=x.queue(e,t),r=n.length,i=n.shift(),o=x._queueHooks(e,t),a=function(){x.dequeue(e,t)};"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,a,o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return x._data(e,n)||x._data(e,n,{empty:x.Callbacks("once memory").add(function(){x._removeData(e,t+"queue"),x._removeData(e,n)})})}}),x.fn.extend({queue:function(e,n){var r=2;return"string"!=typeof e&&(n=e,e="fx",r--),r>arguments.length?x.queue(this[0],e):n===t?this:this.each(function(){var t=x.queue(this,e,n);x._queueHooks(this,e),"fx"===e&&"inprogress"!==t[0]&&x.dequeue(this,e)})},dequeue:function(e){return this.each(function(){x.dequeue(this,e)})},delay:function(e,t){return e=x.fx?x.fx.speeds[e]||e:e,t=t||"fx",this.queue(t,function(t,n){var r=setTimeout(t,e);n.stop=function(){clearTimeout(r)}})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,n){var r,i=1,o=x.Deferred(),a=this,s=this.length,l=function(){--i||o.resolveWith(a,[a])};"string"!=typeof e&&(n=e,e=t),e=e||"fx";while(s--)r=x._data(a[s],e+"queueHooks"),r&&r.empty&&(i++,r.empty.add(l));return l(),o.promise(n)}});var z,X,U=/[\t\r\n\f]/g,V=/\r/g,Y=/^(?:input|select|textarea|button|object)$/i,J=/^(?:a|area)$/i,G=/^(?:checked|selected)$/i,Q=x.support.getSetAttribute,K=x.support.input;x.fn.extend({attr:function(e,t){return x.access(this,x.attr,e,t,arguments.length>1)},removeAttr:function(e){return this.each(function(){x.removeAttr(this,e)})},prop:function(e,t){return x.access(this,x.prop,e,t,arguments.length>1)},removeProp:function(e){return e=x.propFix[e]||e,this.each(function(){try{this[e]=t,delete this[e]}catch(n){}})},addClass:function(e){var t,n,r,i,o,a=0,s=this.length,l="string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).addClass(e.call(this,t,this.className))});if(l)for(t=(e||"").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(U," "):" ")){o=0;while(i=t[o++])0>r.indexOf(" "+i+" ")&&(r+=i+" ");n.className=x.trim(r)}return this},removeClass:function(e){var t,n,r,i,o,a=0,s=this.length,l=0===arguments.length||"string"==typeof e&&e;if(x.isFunction(e))return this.each(function(t){x(this).removeClass(e.call(this,t,this.className))});if(l)for(t=(e||"").match(T)||[];s>a;a++)if(n=this[a],r=1===n.nodeType&&(n.className?(" "+n.className+" ").replace(U," "):"")){o=0;while(i=t[o++])while(r.indexOf(" "+i+" ")>=0)r=r.replace(" "+i+" "," ");n.className=e?x.trim(r):""}return this},toggleClass:function(e,t){var n=typeof e;return"boolean"==typeof t&&"string"===n?t?this.addClass(e):this.removeClass(e):x.isFunction(e)?this.each(function(n){x(this).toggleClass(e.call(this,n,this.className,t),t)}):this.each(function(){if("string"===n){var t,r=0,o=x(this),a=e.match(T)||[];while(t=a[r++])o.hasClass(t)?o.removeClass(t):o.addClass(t)}else(n===i||"boolean"===n)&&(this.className&&x._data(this,"__className__",this.className),this.className=this.className||e===!1?"":x._data(this,"__className__")||"")})},hasClass:function(e){var t=" "+e+" ",n=0,r=this.length;for(;r>n;n++)if(1===this[n].nodeType&&(" "+this[n].className+" ").replace(U," ").indexOf(t)>=0)return!0;return!1},val:function(e){var n,r,i,o=this[0];{if(arguments.length)return i=x.isFunction(e),this.each(function(n){var o;1===this.nodeType&&(o=i?e.call(this,n,x(this).val()):e,null==o?o="":"number"==typeof o?o+="":x.isArray(o)&&(o=x.map(o,function(e){return null==e?"":e+""})),r=x.valHooks[this.type]||x.valHooks[this.nodeName.toLowerCase()],r&&"set"in r&&r.set(this,o,"value")!==t||(this.value=o))});if(o)return r=x.valHooks[o.type]||x.valHooks[o.nodeName.toLowerCase()],r&&"get"in r&&(n=r.get(o,"value"))!==t?n:(n=o.value,"string"==typeof n?n.replace(V,""):null==n?"":n)}}}),x.extend({valHooks:{option:{get:function(e){var t=x.find.attr(e,"value");return null!=t?t:e.text}},select:{get:function(e){var t,n,r=e.options,i=e.selectedIndex,o="select-one"===e.type||0>i,a=o?null:[],s=o?i+1:r.length,l=0>i?s:o?i:0;for(;s>l;l++)if(n=r[l],!(!n.selected&&l!==i||(x.support.optDisabled?n.disabled:null!==n.getAttribute("disabled"))||n.parentNode.disabled&&x.nodeName(n.parentNode,"optgroup"))){if(t=x(n).val(),o)return t;a.push(t)}return a},set:function(e,t){var n,r,i=e.options,o=x.makeArray(t),a=i.length;while(a--)r=i[a],(r.selected=x.inArray(x(r).val(),o)>=0)&&(n=!0);return n||(e.selectedIndex=-1),o}}},attr:function(e,n,r){var o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return typeof e.getAttribute===i?x.prop(e,n,r):(1===s&&x.isXMLDoc(e)||(n=n.toLowerCase(),o=x.attrHooks[n]||(x.expr.match.bool.test(n)?X:z)),r===t?o&&"get"in o&&null!==(a=o.get(e,n))?a:(a=x.find.attr(e,n),null==a?t:a):null!==r?o&&"set"in o&&(a=o.set(e,r,n))!==t?a:(e.setAttribute(n,r+""),r):(x.removeAttr(e,n),t))},removeAttr:function(e,t){var n,r,i=0,o=t&&t.match(T);if(o&&1===e.nodeType)while(n=o[i++])r=x.propFix[n]||n,x.expr.match.bool.test(n)?K&&Q||!G.test(n)?e[r]=!1:e[x.camelCase("default-"+n)]=e[r]=!1:x.attr(e,n,""),e.removeAttribute(Q?n:r)},attrHooks:{type:{set:function(e,t){if(!x.support.radioValue&&"radio"===t&&x.nodeName(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},propFix:{"for":"htmlFor","class":"className"},prop:function(e,n,r){var i,o,a,s=e.nodeType;if(e&&3!==s&&8!==s&&2!==s)return a=1!==s||!x.isXMLDoc(e),a&&(n=x.propFix[n]||n,o=x.propHooks[n]),r!==t?o&&"set"in o&&(i=o.set(e,r,n))!==t?i:e[n]=r:o&&"get"in o&&null!==(i=o.get(e,n))?i:e[n]},propHooks:{tabIndex:{get:function(e){var t=x.find.attr(e,"tabindex");return t?parseInt(t,10):Y.test(e.nodeName)||J.test(e.nodeName)&&e.href?0:-1}}}}),X={set:function(e,t,n){return t===!1?x.removeAttr(e,n):K&&Q||!G.test(n)?e.setAttribute(!Q&&x.propFix[n]||n,n):e[x.camelCase("default-"+n)]=e[n]=!0,n}},x.each(x.expr.match.bool.source.match(/\w+/g),function(e,n){var r=x.expr.attrHandle[n]||x.find.attr;x.expr.attrHandle[n]=K&&Q||!G.test(n)?function(e,n,i){var o=x.expr.attrHandle[n],a=i?t:(x.expr.attrHandle[n]=t)!=r(e,n,i)?n.toLowerCase():null;return x.expr.attrHandle[n]=o,a}:function(e,n,r){return r?t:e[x.camelCase("default-"+n)]?n.toLowerCase():null}}),K&&Q||(x.attrHooks.value={set:function(e,n,r){return x.nodeName(e,"input")?(e.defaultValue=n,t):z&&z.set(e,n,r)}}),Q||(z={set:function(e,n,r){var i=e.getAttributeNode(r);return i||e.setAttributeNode(i=e.ownerDocument.createAttribute(r)),i.value=n+="","value"===r||n===e.getAttribute(r)?n:t}},x.expr.attrHandle.id=x.expr.attrHandle.name=x.expr.attrHandle.coords=function(e,n,r){var i;return r?t:(i=e.getAttributeNode(n))&&""!==i.value?i.value:null},x.valHooks.button={get:function(e,n){var r=e.getAttributeNode(n);return r&&r.specified?r.value:t},set:z.set},x.attrHooks.contenteditable={set:function(e,t,n){z.set(e,""===t?!1:t,n)}},x.each(["width","height"],function(e,n){x.attrHooks[n]={set:function(e,r){return""===r?(e.setAttribute(n,"auto"),r):t}}})),x.support.hrefNormalized||x.each(["href","src"],function(e,t){x.propHooks[t]={get:function(e){return e.getAttribute(t,4)}}}),x.support.style||(x.attrHooks.style={get:function(e){return e.style.cssText||t},set:function(e,t){return e.style.cssText=t+""}}),x.support.optSelected||(x.propHooks.selected={get:function(e){var t=e.parentNode;return t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex),null}}),x.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){x.propFix[this.toLowerCase()]=this}),x.support.enctype||(x.propFix.enctype="encoding"),x.each(["radio","checkbox"],function(){x.valHooks[this]={set:function(e,n){return x.isArray(n)?e.checked=x.inArray(x(e).val(),n)>=0:t}},x.support.checkOn||(x.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})});var Z=/^(?:input|select|textarea)$/i,et=/^key/,tt=/^(?:mouse|contextmenu)|click/,nt=/^(?:focusinfocus|focusoutblur)$/,rt=/^([^.]*)(?:\.(.+)|)$/;function it(){return!0}function ot(){return!1}function at(){try{return a.activeElement}catch(e){}}x.event={global:{},add:function(e,n,r,o,a){var s,l,u,c,p,f,d,h,g,m,y,v=x._data(e);if(v){r.handler&&(c=r,r=c.handler,a=c.selector),r.guid||(r.guid=x.guid++),(l=v.events)||(l=v.events={}),(f=v.handle)||(f=v.handle=function(e){return typeof x===i||e&&x.event.triggered===e.type?t:x.event.dispatch.apply(f.elem,arguments)},f.elem=e),n=(n||"").match(T)||[""],u=n.length;while(u--)s=rt.exec(n[u])||[],g=y=s[1],m=(s[2]||"").split(".").sort(),g&&(p=x.event.special[g]||{},g=(a?p.delegateType:p.bindType)||g,p=x.event.special[g]||{},d=x.extend({type:g,origType:y,data:o,handler:r,guid:r.guid,selector:a,needsContext:a&&x.expr.match.needsContext.test(a),namespace:m.join(".")},c),(h=l[g])||(h=l[g]=[],h.delegateCount=0,p.setup&&p.setup.call(e,o,m,f)!==!1||(e.addEventListener?e.addEventListener(g,f,!1):e.attachEvent&&e.attachEvent("on"+g,f))),p.add&&(p.add.call(e,d),d.handler.guid||(d.handler.guid=r.guid)),a?h.splice(h.delegateCount++,0,d):h.push(d),x.event.global[g]=!0);e=null}},remove:function(e,t,n,r,i){var o,a,s,l,u,c,p,f,d,h,g,m=x.hasData(e)&&x._data(e);if(m&&(c=m.events)){t=(t||"").match(T)||[""],u=t.length;while(u--)if(s=rt.exec(t[u])||[],d=g=s[1],h=(s[2]||"").split(".").sort(),d){p=x.event.special[d]||{},d=(r?p.delegateType:p.bindType)||d,f=c[d]||[],s=s[2]&&RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),l=o=f.length;while(o--)a=f[o],!i&&g!==a.origType||n&&n.guid!==a.guid||s&&!s.test(a.namespace)||r&&r!==a.selector&&("**"!==r||!a.selector)||(f.splice(o,1),a.selector&&f.delegateCount--,p.remove&&p.remove.call(e,a));l&&!f.length&&(p.teardown&&p.teardown.call(e,h,m.handle)!==!1||x.removeEvent(e,d,m.handle),delete c[d])}else for(d in c)x.event.remove(e,d+t[u],n,r,!0);x.isEmptyObject(c)&&(delete m.handle,x._removeData(e,"events"))}},trigger:function(n,r,i,o){var s,l,u,c,p,f,d,h=[i||a],g=v.call(n,"type")?n.type:n,m=v.call(n,"namespace")?n.namespace.split("."):[];if(u=f=i=i||a,3!==i.nodeType&&8!==i.nodeType&&!nt.test(g+x.event.triggered)&&(g.indexOf(".")>=0&&(m=g.split("."),g=m.shift(),m.sort()),l=0>g.indexOf(":")&&"on"+g,n=n[x.expando]?n:new x.Event(g,"object"==typeof n&&n),n.isTrigger=o?2:3,n.namespace=m.join("."),n.namespace_re=n.namespace?RegExp("(^|\\.)"+m.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,n.result=t,n.target||(n.target=i),r=null==r?[n]:x.makeArray(r,[n]),p=x.event.special[g]||{},o||!p.trigger||p.trigger.apply(i,r)!==!1)){if(!o&&!p.noBubble&&!x.isWindow(i)){for(c=p.delegateType||g,nt.test(c+g)||(u=u.parentNode);u;u=u.parentNode)h.push(u),f=u;f===(i.ownerDocument||a)&&h.push(f.defaultView||f.parentWindow||e)}d=0;while((u=h[d++])&&!n.isPropagationStopped())n.type=d>1?c:p.bindType||g,s=(x._data(u,"events")||{})[n.type]&&x._data(u,"handle"),s&&s.apply(u,r),s=l&&u[l],s&&x.acceptData(u)&&s.apply&&s.apply(u,r)===!1&&n.preventDefault();if(n.type=g,!o&&!n.isDefaultPrevented()&&(!p._default||p._default.apply(h.pop(),r)===!1)&&x.acceptData(i)&&l&&i[g]&&!x.isWindow(i)){f=i[l],f&&(i[l]=null),x.event.triggered=g;try{i[g]()}catch(y){}x.event.triggered=t,f&&(i[l]=f)}return n.result}},dispatch:function(e){e=x.event.fix(e);var n,r,i,o,a,s=[],l=g.call(arguments),u=(x._data(this,"events")||{})[e.type]||[],c=x.event.special[e.type]||{};if(l[0]=e,e.delegateTarget=this,!c.preDispatch||c.preDispatch.call(this,e)!==!1){s=x.event.handlers.call(this,e,u),n=0;while((o=s[n++])&&!e.isPropagationStopped()){e.currentTarget=o.elem,a=0;while((i=o.handlers[a++])&&!e.isImmediatePropagationStopped())(!e.namespace_re||e.namespace_re.test(i.namespace))&&(e.handleObj=i,e.data=i.data,r=((x.event.special[i.origType]||{}).handle||i.handler).apply(o.elem,l),r!==t&&(e.result=r)===!1&&(e.preventDefault(),e.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,e),e.result}},handlers:function(e,n){var r,i,o,a,s=[],l=n.delegateCount,u=e.target;if(l&&u.nodeType&&(!e.button||"click"!==e.type))for(;u!=this;u=u.parentNode||this)if(1===u.nodeType&&(u.disabled!==!0||"click"!==e.type)){for(o=[],a=0;l>a;a++)i=n[a],r=i.selector+" ",o[r]===t&&(o[r]=i.needsContext?x(r,this).index(u)>=0:x.find(r,this,null,[u]).length),o[r]&&o.push(i);o.length&&s.push({elem:u,handlers:o})}return n.length>l&&s.push({elem:this,handlers:n.slice(l)}),s},fix:function(e){if(e[x.expando])return e;var t,n,r,i=e.type,o=e,s=this.fixHooks[i];s||(this.fixHooks[i]=s=tt.test(i)?this.mouseHooks:et.test(i)?this.keyHooks:{}),r=s.props?this.props.concat(s.props):this.props,e=new x.Event(o),t=r.length;while(t--)n=r[t],e[n]=o[n];return e.target||(e.target=o.srcElement||a),3===e.target.nodeType&&(e.target=e.target.parentNode),e.metaKey=!!e.metaKey,s.filter?s.filter(e,o):e},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(e,t){return null==e.which&&(e.which=null!=t.charCode?t.charCode:t.keyCode),e}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(e,n){var r,i,o,s=n.button,l=n.fromElement;return null==e.pageX&&null!=n.clientX&&(i=e.target.ownerDocument||a,o=i.documentElement,r=i.body,e.pageX=n.clientX+(o&&o.scrollLeft||r&&r.scrollLeft||0)-(o&&o.clientLeft||r&&r.clientLeft||0),e.pageY=n.clientY+(o&&o.scrollTop||r&&r.scrollTop||0)-(o&&o.clientTop||r&&r.clientTop||0)),!e.relatedTarget&&l&&(e.relatedTarget=l===e.target?n.toElement:l),e.which||s===t||(e.which=1&s?1:2&s?3:4&s?2:0),e}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==at()&&this.focus)try{return this.focus(),!1}catch(e){}},delegateType:"focusin"},blur:{trigger:function(){return this===at()&&this.blur?(this.blur(),!1):t},delegateType:"focusout"},click:{trigger:function(){return x.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):t},_default:function(e){return x.nodeName(e.target,"a")}},beforeunload:{postDispatch:function(e){e.result!==t&&(e.originalEvent.returnValue=e.result)}}},simulate:function(e,t,n,r){var i=x.extend(new x.Event,n,{type:e,isSimulated:!0,originalEvent:{}});r?x.event.trigger(i,null,t):x.event.dispatch.call(t,i),i.isDefaultPrevented()&&n.preventDefault()}},x.removeEvent=a.removeEventListener?function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n,!1)}:function(e,t,n){var r="on"+t;e.detachEvent&&(typeof e[r]===i&&(e[r]=null),e.detachEvent(r,n))},x.Event=function(e,n){return this instanceof x.Event?(e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||e.returnValue===!1||e.getPreventDefault&&e.getPreventDefault()?it:ot):this.type=e,n&&x.extend(this,n),this.timeStamp=e&&e.timeStamp||x.now(),this[x.expando]=!0,t):new x.Event(e,n)},x.Event.prototype={isDefaultPrevented:ot,isPropagationStopped:ot,isImmediatePropagationStopped:ot,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=it,e&&(e.preventDefault?e.preventDefault():e.returnValue=!1)},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=it,e&&(e.stopPropagation&&e.stopPropagation(),e.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=it,this.stopPropagation()}},x.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(e,t){x.event.special[e]={delegateType:t,bindType:t,handle:function(e){var n,r=this,i=e.relatedTarget,o=e.handleObj;return(!i||i!==r&&!x.contains(r,i))&&(e.type=o.origType,n=o.handler.apply(this,arguments),e.type=t),n}}}),x.support.submitBubbles||(x.event.special.submit={setup:function(){return x.nodeName(this,"form")?!1:(x.event.add(this,"click._submit keypress._submit",function(e){var n=e.target,r=x.nodeName(n,"input")||x.nodeName(n,"button")?n.form:t;r&&!x._data(r,"submitBubbles")&&(x.event.add(r,"submit._submit",function(e){e._submit_bubble=!0}),x._data(r,"submitBubbles",!0))}),t)},postDispatch:function(e){e._submit_bubble&&(delete e._submit_bubble,this.parentNode&&!e.isTrigger&&x.event.simulate("submit",this.parentNode,e,!0))},teardown:function(){return x.nodeName(this,"form")?!1:(x.event.remove(this,"._submit"),t)}}),x.support.changeBubbles||(x.event.special.change={setup:function(){return Z.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(x.event.add(this,"propertychange._change",function(e){"checked"===e.originalEvent.propertyName&&(this._just_changed=!0)}),x.event.add(this,"click._change",function(e){this._just_changed&&!e.isTrigger&&(this._just_changed=!1),x.event.simulate("change",this,e,!0)})),!1):(x.event.add(this,"beforeactivate._change",function(e){var t=e.target;Z.test(t.nodeName)&&!x._data(t,"changeBubbles")&&(x.event.add(t,"change._change",function(e){!this.parentNode||e.isSimulated||e.isTrigger||x.event.simulate("change",this.parentNode,e,!0)}),x._data(t,"changeBubbles",!0))}),t)},handle:function(e){var n=e.target;return this!==n||e.isSimulated||e.isTrigger||"radio"!==n.type&&"checkbox"!==n.type?e.handleObj.handler.apply(this,arguments):t},teardown:function(){return x.event.remove(this,"._change"),!Z.test(this.nodeName)}}),x.support.focusinBubbles||x.each({focus:"focusin",blur:"focusout"},function(e,t){var n=0,r=function(e){x.event.simulate(t,e.target,x.event.fix(e),!0)};x.event.special[t]={setup:function(){0===n++&&a.addEventListener(e,r,!0)},teardown:function(){0===--n&&a.removeEventListener(e,r,!0)}}}),x.fn.extend({on:function(e,n,r,i,o){var a,s;if("object"==typeof e){"string"!=typeof n&&(r=r||n,n=t);for(a in e)this.on(a,n,r,e[a],o);return this}if(null==r&&null==i?(i=n,r=n=t):null==i&&("string"==typeof n?(i=r,r=t):(i=r,r=n,n=t)),i===!1)i=ot;else if(!i)return this;return 1===o&&(s=i,i=function(e){return x().off(e),s.apply(this,arguments)},i.guid=s.guid||(s.guid=x.guid++)),this.each(function(){x.event.add(this,e,i,r,n)})},one:function(e,t,n,r){return this.on(e,t,n,r,1)},off:function(e,n,r){var i,o;if(e&&e.preventDefault&&e.handleObj)return i=e.handleObj,x(e.delegateTarget).off(i.namespace?i.origType+"."+i.namespace:i.origType,i.selector,i.handler),this;if("object"==typeof e){for(o in e)this.off(o,n,e[o]);return this}return(n===!1||"function"==typeof n)&&(r=n,n=t),r===!1&&(r=ot),this.each(function(){x.event.remove(this,e,r,n)})},trigger:function(e,t){return this.each(function(){x.event.trigger(e,t,this)})},triggerHandler:function(e,n){var r=this[0];return r?x.event.trigger(e,n,r,!0):t}});var st=/^.[^:#\[\.,]*$/,lt=/^(?:parents|prev(?:Until|All))/,ut=x.expr.match.needsContext,ct={children:!0,contents:!0,next:!0,prev:!0};x.fn.extend({find:function(e){var t,n=[],r=this,i=r.length;if("string"!=typeof e)return this.pushStack(x(e).filter(function(){for(t=0;i>t;t++)if(x.contains(r[t],this))return!0}));for(t=0;i>t;t++)x.find(e,r[t],n);return n=this.pushStack(i>1?x.unique(n):n),n.selector=this.selector?this.selector+" "+e:e,n},has:function(e){var t,n=x(e,this),r=n.length;return this.filter(function(){for(t=0;r>t;t++)if(x.contains(this,n[t]))return!0})},not:function(e){return this.pushStack(ft(this,e||[],!0))},filter:function(e){return this.pushStack(ft(this,e||[],!1))},is:function(e){return!!ft(this,"string"==typeof e&&ut.test(e)?x(e):e||[],!1).length},closest:function(e,t){var n,r=0,i=this.length,o=[],a=ut.test(e)||"string"!=typeof e?x(e,t||this.context):0;for(;i>r;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(11>n.nodeType&&(a?a.index(n)>-1:1===n.nodeType&&x.find.matchesSelector(n,e))){n=o.push(n);break}return this.pushStack(o.length>1?x.unique(o):o)},index:function(e){return e?"string"==typeof e?x.inArray(this[0],x(e)):x.inArray(e.jquery?e[0]:e,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){var n="string"==typeof e?x(e,t):x.makeArray(e&&e.nodeType?[e]:e),r=x.merge(this.get(),n);return this.pushStack(x.unique(r))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}});function pt(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}x.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return x.dir(e,"parentNode")},parentsUntil:function(e,t,n){return x.dir(e,"parentNode",n)},next:function(e){return pt(e,"nextSibling")},prev:function(e){return pt(e,"previousSibling")},nextAll:function(e){return x.dir(e,"nextSibling")},prevAll:function(e){return x.dir(e,"previousSibling")},nextUntil:function(e,t,n){return x.dir(e,"nextSibling",n)},prevUntil:function(e,t,n){return x.dir(e,"previousSibling",n)},siblings:function(e){return x.sibling((e.parentNode||{}).firstChild,e)},children:function(e){return x.sibling(e.firstChild)},contents:function(e){return x.nodeName(e,"iframe")?e.contentDocument||e.contentWindow.document:x.merge([],e.childNodes)}},function(e,t){x.fn[e]=function(n,r){var i=x.map(this,t,n);return"Until"!==e.slice(-5)&&(r=n),r&&"string"==typeof r&&(i=x.filter(r,i)),this.length>1&&(ct[e]||(i=x.unique(i)),lt.test(e)&&(i=i.reverse())),this.pushStack(i)}}),x.extend({filter:function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?x.find.matchesSelector(r,e)?[r]:[]:x.find.matches(e,x.grep(t,function(e){return 1===e.nodeType}))},dir:function(e,n,r){var i=[],o=e[n];while(o&&9!==o.nodeType&&(r===t||1!==o.nodeType||!x(o).is(r)))1===o.nodeType&&i.push(o),o=o[n];return i},sibling:function(e,t){var n=[];for(;e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n}});function ft(e,t,n){if(x.isFunction(t))return x.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return x.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(st.test(t))return x.filter(t,e,n);t=x.filter(t,e)}return x.grep(e,function(e){return x.inArray(e,t)>=0!==n})}function dt(e){var t=ht.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}var ht="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",gt=/ jQuery\d+="(?:null|\d+)"/g,mt=RegExp("<(?:"+ht+")[\\s/>]","i"),yt=/^\s+/,vt=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,bt=/<([\w:]+)/,xt=/\s*$/g,At={option:[1,""],legend:[1,"
          ","
          "],area:[1,"",""],param:[1,"",""],thead:[1,"","
          "],tr:[2,"","
          "],col:[2,"","
          "],td:[3,"","
          "],_default:x.support.htmlSerialize?[0,"",""]:[1,"X
          ","
          "]},jt=dt(a),Dt=jt.appendChild(a.createElement("div"));At.optgroup=At.option,At.tbody=At.tfoot=At.colgroup=At.caption=At.thead,At.th=At.td,x.fn.extend({text:function(e){return x.access(this,function(e){return e===t?x.text(this):this.empty().append((this[0]&&this[0].ownerDocument||a).createTextNode(e))},null,e,arguments.length)},append:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.appendChild(e)}})},prepend:function(){return this.domManip(arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=Lt(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return this.domManip(arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},remove:function(e,t){var n,r=e?x.filter(e,this):this,i=0;for(;null!=(n=r[i]);i++)t||1!==n.nodeType||x.cleanData(Ft(n)),n.parentNode&&(t&&x.contains(n.ownerDocument,n)&&_t(Ft(n,"script")),n.parentNode.removeChild(n));return this},empty:function(){var e,t=0;for(;null!=(e=this[t]);t++){1===e.nodeType&&x.cleanData(Ft(e,!1));while(e.firstChild)e.removeChild(e.firstChild);e.options&&x.nodeName(e,"select")&&(e.options.length=0)}return this},clone:function(e,t){return e=null==e?!1:e,t=null==t?e:t,this.map(function(){return x.clone(this,e,t)})},html:function(e){return x.access(this,function(e){var n=this[0]||{},r=0,i=this.length;if(e===t)return 1===n.nodeType?n.innerHTML.replace(gt,""):t;if(!("string"!=typeof e||Tt.test(e)||!x.support.htmlSerialize&&mt.test(e)||!x.support.leadingWhitespace&&yt.test(e)||At[(bt.exec(e)||["",""])[1].toLowerCase()])){e=e.replace(vt,"<$1>");try{for(;i>r;r++)n=this[r]||{},1===n.nodeType&&(x.cleanData(Ft(n,!1)),n.innerHTML=e);n=0}catch(o){}}n&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var e=x.map(this,function(e){return[e.nextSibling,e.parentNode]}),t=0;return this.domManip(arguments,function(n){var r=e[t++],i=e[t++];i&&(r&&r.parentNode!==i&&(r=this.nextSibling),x(this).remove(),i.insertBefore(n,r))},!0),t?this:this.remove()},detach:function(e){return this.remove(e,!0)},domManip:function(e,t,n){e=d.apply([],e);var r,i,o,a,s,l,u=0,c=this.length,p=this,f=c-1,h=e[0],g=x.isFunction(h);if(g||!(1>=c||"string"!=typeof h||x.support.checkClone)&&Nt.test(h))return this.each(function(r){var i=p.eq(r);g&&(e[0]=h.call(this,r,i.html())),i.domManip(e,t,n)});if(c&&(l=x.buildFragment(e,this[0].ownerDocument,!1,!n&&this),r=l.firstChild,1===l.childNodes.length&&(l=r),r)){for(a=x.map(Ft(l,"script"),Ht),o=a.length;c>u;u++)i=l,u!==f&&(i=x.clone(i,!0,!0),o&&x.merge(a,Ft(i,"script"))),t.call(this[u],i,u);if(o)for(s=a[a.length-1].ownerDocument,x.map(a,qt),u=0;o>u;u++)i=a[u],kt.test(i.type||"")&&!x._data(i,"globalEval")&&x.contains(s,i)&&(i.src?x._evalUrl(i.src):x.globalEval((i.text||i.textContent||i.innerHTML||"").replace(St,"")));l=r=null}return this}});function Lt(e,t){return x.nodeName(e,"table")&&x.nodeName(1===t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function Ht(e){return e.type=(null!==x.find.attr(e,"type"))+"/"+e.type,e}function qt(e){var t=Et.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function _t(e,t){var n,r=0;for(;null!=(n=e[r]);r++)x._data(n,"globalEval",!t||x._data(t[r],"globalEval"))}function Mt(e,t){if(1===t.nodeType&&x.hasData(e)){var n,r,i,o=x._data(e),a=x._data(t,o),s=o.events;if(s){delete a.handle,a.events={};for(n in s)for(r=0,i=s[n].length;i>r;r++)x.event.add(t,n,s[n][r])}a.data&&(a.data=x.extend({},a.data))}}function Ot(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!x.support.noCloneEvent&&t[x.expando]){i=x._data(t);for(r in i.events)x.removeEvent(t,r,i.handle);t.removeAttribute(x.expando)}"script"===n&&t.text!==e.text?(Ht(t).text=e.text,qt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),x.support.html5Clone&&e.innerHTML&&!x.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&Ct.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}x.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,t){x.fn[e]=function(e){var n,r=0,i=[],o=x(e),a=o.length-1;for(;a>=r;r++)n=r===a?this:this.clone(!0),x(o[r])[t](n),h.apply(i,n.get());return this.pushStack(i)}});function Ft(e,n){var r,o,a=0,s=typeof e.getElementsByTagName!==i?e.getElementsByTagName(n||"*"):typeof e.querySelectorAll!==i?e.querySelectorAll(n||"*"):t;if(!s)for(s=[],r=e.childNodes||e;null!=(o=r[a]);a++)!n||x.nodeName(o,n)?s.push(o):x.merge(s,Ft(o,n));return n===t||n&&x.nodeName(e,n)?x.merge([e],s):s}function Bt(e){Ct.test(e.type)&&(e.defaultChecked=e.checked)}x.extend({clone:function(e,t,n){var r,i,o,a,s,l=x.contains(e.ownerDocument,e);if(x.support.html5Clone||x.isXMLDoc(e)||!mt.test("<"+e.nodeName+">")?o=e.cloneNode(!0):(Dt.innerHTML=e.outerHTML,Dt.removeChild(o=Dt.firstChild)),!(x.support.noCloneEvent&&x.support.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||x.isXMLDoc(e)))for(r=Ft(o),s=Ft(e),a=0;null!=(i=s[a]);++a)r[a]&&Ot(i,r[a]);if(t)if(n)for(s=s||Ft(e),r=r||Ft(o),a=0;null!=(i=s[a]);a++)Mt(i,r[a]);else Mt(e,o);return r=Ft(o,"script"),r.length>0&&_t(r,!l&&Ft(e,"script")),r=s=i=null,o},buildFragment:function(e,t,n,r){var i,o,a,s,l,u,c,p=e.length,f=dt(t),d=[],h=0;for(;p>h;h++)if(o=e[h],o||0===o)if("object"===x.type(o))x.merge(d,o.nodeType?[o]:o);else if(wt.test(o)){s=s||f.appendChild(t.createElement("div")),l=(bt.exec(o)||["",""])[1].toLowerCase(),c=At[l]||At._default,s.innerHTML=c[1]+o.replace(vt,"<$1>")+c[2],i=c[0];while(i--)s=s.lastChild;if(!x.support.leadingWhitespace&&yt.test(o)&&d.push(t.createTextNode(yt.exec(o)[0])),!x.support.tbody){o="table"!==l||xt.test(o)?""!==c[1]||xt.test(o)?0:s:s.firstChild,i=o&&o.childNodes.length;while(i--)x.nodeName(u=o.childNodes[i],"tbody")&&!u.childNodes.length&&o.removeChild(u)}x.merge(d,s.childNodes),s.textContent="";while(s.firstChild)s.removeChild(s.firstChild);s=f.lastChild}else d.push(t.createTextNode(o));s&&f.removeChild(s),x.support.appendChecked||x.grep(Ft(d,"input"),Bt),h=0;while(o=d[h++])if((!r||-1===x.inArray(o,r))&&(a=x.contains(o.ownerDocument,o),s=Ft(f.appendChild(o),"script"),a&&_t(s),n)){i=0;while(o=s[i++])kt.test(o.type||"")&&n.push(o)}return s=null,f},cleanData:function(e,t){var n,r,o,a,s=0,l=x.expando,u=x.cache,c=x.support.deleteExpando,f=x.event.special;for(;null!=(n=e[s]);s++)if((t||x.acceptData(n))&&(o=n[l],a=o&&u[o])){if(a.events)for(r in a.events)f[r]?x.event.remove(n,r):x.removeEvent(n,r,a.handle); u[o]&&(delete u[o],c?delete n[l]:typeof n.removeAttribute!==i?n.removeAttribute(l):n[l]=null,p.push(o))}},_evalUrl:function(e){return x.ajax({url:e,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})}}),x.fn.extend({wrapAll:function(e){if(x.isFunction(e))return this.each(function(t){x(this).wrapAll(e.call(this,t))});if(this[0]){var t=x(e,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstChild&&1===e.firstChild.nodeType)e=e.firstChild;return e}).append(this)}return this},wrapInner:function(e){return x.isFunction(e)?this.each(function(t){x(this).wrapInner(e.call(this,t))}):this.each(function(){var t=x(this),n=t.contents();n.length?n.wrapAll(e):t.append(e)})},wrap:function(e){var t=x.isFunction(e);return this.each(function(n){x(this).wrapAll(t?e.call(this,n):e)})},unwrap:function(){return this.parent().each(function(){x.nodeName(this,"body")||x(this).replaceWith(this.childNodes)}).end()}});var Pt,Rt,Wt,$t=/alpha\([^)]*\)/i,It=/opacity\s*=\s*([^)]*)/,zt=/^(top|right|bottom|left)$/,Xt=/^(none|table(?!-c[ea]).+)/,Ut=/^margin/,Vt=RegExp("^("+w+")(.*)$","i"),Yt=RegExp("^("+w+")(?!px)[a-z%]+$","i"),Jt=RegExp("^([+-])=("+w+")","i"),Gt={BODY:"block"},Qt={position:"absolute",visibility:"hidden",display:"block"},Kt={letterSpacing:0,fontWeight:400},Zt=["Top","Right","Bottom","Left"],en=["Webkit","O","Moz","ms"];function tn(e,t){if(t in e)return t;var n=t.charAt(0).toUpperCase()+t.slice(1),r=t,i=en.length;while(i--)if(t=en[i]+n,t in e)return t;return r}function nn(e,t){return e=t||e,"none"===x.css(e,"display")||!x.contains(e.ownerDocument,e)}function rn(e,t){var n,r,i,o=[],a=0,s=e.length;for(;s>a;a++)r=e[a],r.style&&(o[a]=x._data(r,"olddisplay"),n=r.style.display,t?(o[a]||"none"!==n||(r.style.display=""),""===r.style.display&&nn(r)&&(o[a]=x._data(r,"olddisplay",ln(r.nodeName)))):o[a]||(i=nn(r),(n&&"none"!==n||!i)&&x._data(r,"olddisplay",i?n:x.css(r,"display"))));for(a=0;s>a;a++)r=e[a],r.style&&(t&&"none"!==r.style.display&&""!==r.style.display||(r.style.display=t?o[a]||"":"none"));return e}x.fn.extend({css:function(e,n){return x.access(this,function(e,n,r){var i,o,a={},s=0;if(x.isArray(n)){for(o=Rt(e),i=n.length;i>s;s++)a[n[s]]=x.css(e,n[s],!1,o);return a}return r!==t?x.style(e,n,r):x.css(e,n)},e,n,arguments.length>1)},show:function(){return rn(this,!0)},hide:function(){return rn(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){nn(this)?x(this).show():x(this).hide()})}}),x.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Wt(e,"opacity");return""===n?"1":n}}}},cssNumber:{columnCount:!0,fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":x.support.cssFloat?"cssFloat":"styleFloat"},style:function(e,n,r,i){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var o,a,s,l=x.camelCase(n),u=e.style;if(n=x.cssProps[l]||(x.cssProps[l]=tn(u,l)),s=x.cssHooks[n]||x.cssHooks[l],r===t)return s&&"get"in s&&(o=s.get(e,!1,i))!==t?o:u[n];if(a=typeof r,"string"===a&&(o=Jt.exec(r))&&(r=(o[1]+1)*o[2]+parseFloat(x.css(e,n)),a="number"),!(null==r||"number"===a&&isNaN(r)||("number"!==a||x.cssNumber[l]||(r+="px"),x.support.clearCloneStyle||""!==r||0!==n.indexOf("background")||(u[n]="inherit"),s&&"set"in s&&(r=s.set(e,r,i))===t)))try{u[n]=r}catch(c){}}},css:function(e,n,r,i){var o,a,s,l=x.camelCase(n);return n=x.cssProps[l]||(x.cssProps[l]=tn(e.style,l)),s=x.cssHooks[n]||x.cssHooks[l],s&&"get"in s&&(a=s.get(e,!0,r)),a===t&&(a=Wt(e,n,i)),"normal"===a&&n in Kt&&(a=Kt[n]),""===r||r?(o=parseFloat(a),r===!0||x.isNumeric(o)?o||0:a):a}}),e.getComputedStyle?(Rt=function(t){return e.getComputedStyle(t,null)},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s.getPropertyValue(n)||s[n]:t,u=e.style;return s&&(""!==l||x.contains(e.ownerDocument,e)||(l=x.style(e,n)),Yt.test(l)&&Ut.test(n)&&(i=u.width,o=u.minWidth,a=u.maxWidth,u.minWidth=u.maxWidth=u.width=l,l=s.width,u.width=i,u.minWidth=o,u.maxWidth=a)),l}):a.documentElement.currentStyle&&(Rt=function(e){return e.currentStyle},Wt=function(e,n,r){var i,o,a,s=r||Rt(e),l=s?s[n]:t,u=e.style;return null==l&&u&&u[n]&&(l=u[n]),Yt.test(l)&&!zt.test(n)&&(i=u.left,o=e.runtimeStyle,a=o&&o.left,a&&(o.left=e.currentStyle.left),u.left="fontSize"===n?"1em":l,l=u.pixelLeft+"px",u.left=i,a&&(o.left=a)),""===l?"auto":l});function on(e,t,n){var r=Vt.exec(t);return r?Math.max(0,r[1]-(n||0))+(r[2]||"px"):t}function an(e,t,n,r,i){var o=n===(r?"border":"content")?4:"width"===t?1:0,a=0;for(;4>o;o+=2)"margin"===n&&(a+=x.css(e,n+Zt[o],!0,i)),r?("content"===n&&(a-=x.css(e,"padding"+Zt[o],!0,i)),"margin"!==n&&(a-=x.css(e,"border"+Zt[o]+"Width",!0,i))):(a+=x.css(e,"padding"+Zt[o],!0,i),"padding"!==n&&(a+=x.css(e,"border"+Zt[o]+"Width",!0,i)));return a}function sn(e,t,n){var r=!0,i="width"===t?e.offsetWidth:e.offsetHeight,o=Rt(e),a=x.support.boxSizing&&"border-box"===x.css(e,"boxSizing",!1,o);if(0>=i||null==i){if(i=Wt(e,t,o),(0>i||null==i)&&(i=e.style[t]),Yt.test(i))return i;r=a&&(x.support.boxSizingReliable||i===e.style[t]),i=parseFloat(i)||0}return i+an(e,t,n||(a?"border":"content"),r,o)+"px"}function ln(e){var t=a,n=Gt[e];return n||(n=un(e,t),"none"!==n&&n||(Pt=(Pt||x("