diff options
79 files changed, 11240 insertions, 2846 deletions
diff --git a/3rdparty/libconfig/LICENSE b/3rdparty/libconfig/LICENSE new file mode 100644 index 000000000..94a9ed024 --- /dev/null +++ b/3rdparty/libconfig/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + 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. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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 <http://www.gnu.org/licenses/>. + +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: + + <program> Copyright (C) <year> <name of author> + 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 +<http://www.gnu.org/licenses/>. + + 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 +<http://www.gnu.org/philosophy/why-not-lgpl.html>. diff --git a/3rdparty/libconfig/Makefile.in b/3rdparty/libconfig/Makefile.in new file mode 100644 index 000000000..22642413d --- /dev/null +++ b/3rdparty/libconfig/Makefile.in @@ -0,0 +1,24 @@ +
+LIBCONFIG_OBJ = libconfig.o grammar.o scanctx.o scanner.o strbuf.o
+LIBCONFIG_H = libconfig.h grammar.h parsectx.h scanctx.h scanner.h strbuf.h wincompat.h
+
+@SET_MAKE@
+
+#####################################################################
+.PHONY : all clean help
+
+all: $(LIBCONFIG_OBJ)
+
+clean:
+ rm -rf *.o
+
+help:
+ @echo "possible targets are 'all' 'clean' 'help'"
+ @echo "'all' - builds $(LIBCONFIG_OBJ)"
+ @echo "'clean' - deletes $(LIBCONFIG_OBJ)"
+ @echo "'help' - outputs this message"
+
+#####################################################################
+
+%.o: %.c $(LIBCONFIG_H)
+ @CC@ @CFLAGS@ @LDFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
diff --git a/3rdparty/libconfig/grammar.c b/3rdparty/libconfig/grammar.c new file mode 100644 index 000000000..e95a569f6 --- /dev/null +++ b/3rdparty/libconfig/grammar.c @@ -0,0 +1,2001 @@ + +/* A Bison parser, made by GNU Bison 2.4.1. */ + +/* Skeleton implementation for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + 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 <http://www.gnu.org/licenses/>. */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + +/* C LALR(1) parser skeleton written by Richard Stallman, by + simplifying the original so-called "semantic" parser. */ + +/* All symbols defined below should begin with yy or YY, to avoid + infringing on user name space. This should be done even for local + variables, as they might otherwise be expanded by user macros. + There are some unavoidable exceptions within include files to + define necessary library symbols; they are noted "INFRINGES ON + USER NAME SPACE" below. */ + +/* Identify Bison output. */ +#define YYBISON 1 + +/* Bison version. */ +#define YYBISON_VERSION "2.4.1" + +/* Skeleton name. */ +#define YYSKELETON_NAME "yacc.c" + +/* Pure parsers. */ +#define YYPURE 1 + +/* Push parsers. */ +#define YYPUSH 0 + +/* Pull parsers. */ +#define YYPULL 1 + +/* Using locations. */ +#define YYLSP_NEEDED 0 + +/* Substitute the variable and function names. */ +#define yyparse libconfig_yyparse +#define yylex libconfig_yylex +#define yyerror libconfig_yyerror +#define yylval libconfig_yylval +#define yychar libconfig_yychar +#define yydebug libconfig_yydebug +#define yynerrs libconfig_yynerrs + + +/* Copy the first part of user declarations. */ + +/* Line 189 of yacc.c */ +#line 32 "grammar.y" + +#include <string.h> +#include <stdlib.h> +#include "libconfig.h" +#ifdef WIN32 +#include "wincompat.h" + +/* prevent warnings about redefined malloc/free in generated code: */ +#ifndef _STDLIB_H +#define _STDLIB_H +#endif + +#include <malloc.h> +#endif +#include "parsectx.h" +#include "scanctx.h" + +/* these delcarations are provided to suppress compiler warnings */ +extern int libconfig_yylex(); +extern int libconfig_yyget_lineno(); + +static const char *err_array_elem_type = "mismatched element type in array"; +static const char *err_duplicate_setting = "duplicate setting name"; + +#define _delete(P) free((void *)(P)) + +#define IN_ARRAY() \ + (ctx->parent && (ctx->parent->type == CONFIG_TYPE_ARRAY)) + +#define IN_LIST() \ + (ctx->parent && (ctx->parent->type == CONFIG_TYPE_LIST)) + +static void capture_parse_pos(void *scanner, struct scan_context *scan_ctx, + config_setting_t *setting) +{ + setting->line = (unsigned int)libconfig_yyget_lineno(scanner); + setting->file = scanctx_current_filename(scan_ctx); +} + +#define CAPTURE_PARSE_POS(S) \ + capture_parse_pos(scanner, scan_ctx, (S)) + +void libconfig_yyerror(void *scanner, struct parse_context *ctx, + struct scan_context *scan_ctx, char const *s) +{ + if(ctx->config->error_text) return; + ctx->config->error_line = libconfig_yyget_lineno(scanner); + ctx->config->error_text = s; +} + + + +/* Line 189 of yacc.c */ +#line 134 "grammar.c" + +/* Enabling traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif + +/* Enabling verbose error messages. */ +#ifdef YYERROR_VERBOSE +# undef YYERROR_VERBOSE +# define YYERROR_VERBOSE 1 +#else +# define YYERROR_VERBOSE 0 +#endif + +/* Enabling the token table. */ +#ifndef YYTOKEN_TABLE +# define YYTOKEN_TABLE 0 +#endif + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + TOK_BOOLEAN = 258, + TOK_INTEGER = 259, + TOK_HEX = 260, + TOK_INTEGER64 = 261, + TOK_HEX64 = 262, + TOK_FLOAT = 263, + TOK_STRING = 264, + TOK_NAME = 265, + TOK_EQUALS = 266, + TOK_NEWLINE = 267, + TOK_ARRAY_START = 268, + TOK_ARRAY_END = 269, + TOK_LIST_START = 270, + TOK_LIST_END = 271, + TOK_COMMA = 272, + TOK_GROUP_START = 273, + TOK_GROUP_END = 274, + TOK_SEMICOLON = 275, + TOK_GARBAGE = 276, + TOK_ERROR = 277 + }; +#endif +/* Tokens. */ +#define TOK_BOOLEAN 258 +#define TOK_INTEGER 259 +#define TOK_HEX 260 +#define TOK_INTEGER64 261 +#define TOK_HEX64 262 +#define TOK_FLOAT 263 +#define TOK_STRING 264 +#define TOK_NAME 265 +#define TOK_EQUALS 266 +#define TOK_NEWLINE 267 +#define TOK_ARRAY_START 268 +#define TOK_ARRAY_END 269 +#define TOK_LIST_START 270 +#define TOK_LIST_END 271 +#define TOK_COMMA 272 +#define TOK_GROUP_START 273 +#define TOK_GROUP_END 274 +#define TOK_SEMICOLON 275 +#define TOK_GARBAGE 276 +#define TOK_ERROR 277 + + + + +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE +{ + +/* Line 214 of yacc.c */ +#line 85 "grammar.y" + + int ival; + long long llval; + double fval; + char *sval; + + + +/* Line 214 of yacc.c */ +#line 223 "grammar.c" +} YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +#endif + + +/* Copy the second part of user declarations. */ + + +/* Line 264 of yacc.c */ +#line 235 "grammar.c" + +#ifdef short +# undef short +#endif + +#ifdef YYTYPE_UINT8 +typedef YYTYPE_UINT8 yytype_uint8; +#else +typedef unsigned char yytype_uint8; +#endif + +#ifdef YYTYPE_INT8 +typedef YYTYPE_INT8 yytype_int8; +#elif (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +typedef signed char yytype_int8; +#else +typedef short int yytype_int8; +#endif + +#ifdef YYTYPE_UINT16 +typedef YYTYPE_UINT16 yytype_uint16; +#else +typedef unsigned short int yytype_uint16; +#endif + +#ifdef YYTYPE_INT16 +typedef YYTYPE_INT16 yytype_int16; +#else +typedef short int yytype_int16; +#endif + +#ifndef YYSIZE_T +# ifdef __SIZE_TYPE__ +# define YYSIZE_T __SIZE_TYPE__ +# elif defined size_t +# define YYSIZE_T size_t +# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include <stddef.h> /* INFRINGES ON USER NAME SPACE */ +# define YYSIZE_T size_t +# else +# define YYSIZE_T unsigned int +# endif +#endif + +#define YYSIZE_MAXIMUM ((YYSIZE_T) -1) + +#ifndef YY_ +# if YYENABLE_NLS +# if ENABLE_NLS +# include <libintl.h> /* INFRINGES ON USER NAME SPACE */ +# define YY_(msgid) dgettext ("bison-runtime", msgid) +# endif +# endif +# ifndef YY_ +# define YY_(msgid) msgid +# endif +#endif + +/* Suppress unused-variable warnings by "using" E. */ +#if ! defined lint || defined __GNUC__ +# define YYUSE(e) ((void) (e)) +#else +# define YYUSE(e) /* empty */ +#endif + +/* Identity function, used to suppress warnings about constant conditions. */ +#ifndef lint +# define YYID(n) (n) +#else +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static int +YYID (int yyi) +#else +static int +YYID (yyi) + int yyi; +#endif +{ + return yyi; +} +#endif + +#if ! defined yyoverflow || YYERROR_VERBOSE + +/* The parser invokes alloca or malloc; define the necessary symbols. */ + +# ifdef YYSTACK_USE_ALLOCA +# if YYSTACK_USE_ALLOCA +# ifdef __GNUC__ +# define YYSTACK_ALLOC __builtin_alloca +# elif defined __BUILTIN_VA_ARG_INCR +# include <alloca.h> /* INFRINGES ON USER NAME SPACE */ +# elif defined _AIX +# define YYSTACK_ALLOC __alloca +# elif defined _MSC_VER +# include <malloc.h> /* INFRINGES ON USER NAME SPACE */ +# define alloca _alloca +# else +# define YYSTACK_ALLOC alloca +# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# endif +# endif +# endif + +# ifdef YYSTACK_ALLOC + /* Pacify GCC's `empty if-body' warning. */ +# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0)) +# ifndef YYSTACK_ALLOC_MAXIMUM + /* The OS might guarantee only one guard page at the bottom of the stack, + and a page size can be as small as 4096 bytes. So we cannot safely + invoke alloca (N) if N exceeds 4096. Use a slightly smaller number + to allow for a few compiler-allocated temporary stack slots. */ +# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */ +# endif +# else +# define YYSTACK_ALLOC YYMALLOC +# define YYSTACK_FREE YYFREE +# ifndef YYSTACK_ALLOC_MAXIMUM +# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM +# endif +# if (defined __cplusplus && ! defined _STDLIB_H \ + && ! ((defined YYMALLOC || defined malloc) \ + && (defined YYFREE || defined free))) +# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */ +# ifndef _STDLIB_H +# define _STDLIB_H 1 +# endif +# endif +# ifndef YYMALLOC +# define YYMALLOC malloc +# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# ifndef YYFREE +# define YYFREE free +# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +void free (void *); /* INFRINGES ON USER NAME SPACE */ +# endif +# endif +# endif +#endif /* ! defined yyoverflow || YYERROR_VERBOSE */ + + +#if (! defined yyoverflow \ + && (! defined __cplusplus \ + || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) + +/* A type that is properly aligned for any stack member. */ +union yyalloc +{ + yytype_int16 yyss_alloc; + YYSTYPE yyvs_alloc; +}; + +/* The size of the maximum gap between one aligned stack and the next. */ +# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) + +/* The size of an array large to enough to hold all stacks, each with + N elements. */ +# define YYSTACK_BYTES(N) \ + ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \ + + YYSTACK_GAP_MAXIMUM) + +/* Copy COUNT objects from FROM to TO. The source and destination do + not overlap. */ +# ifndef YYCOPY +# if defined __GNUC__ && 1 < __GNUC__ +# define YYCOPY(To, From, Count) \ + __builtin_memcpy (To, From, (Count) * sizeof (*(From))) +# else +# define YYCOPY(To, From, Count) \ + do \ + { \ + YYSIZE_T yyi; \ + for (yyi = 0; yyi < (Count); yyi++) \ + (To)[yyi] = (From)[yyi]; \ + } \ + while (YYID (0)) +# endif +# endif + +/* Relocate STACK from its old location to the new one. The + local variables YYSIZE and YYSTACKSIZE give the old and new number of + elements in the stack, and YYPTR gives the new location of the + stack. Advance YYPTR to a properly aligned location for the next + stack. */ +# define YYSTACK_RELOCATE(Stack_alloc, Stack) \ + do \ + { \ + YYSIZE_T yynewbytes; \ + YYCOPY (&yyptr->Stack_alloc, Stack, yysize); \ + Stack = &yyptr->Stack_alloc; \ + yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ + yyptr += yynewbytes / sizeof (*yyptr); \ + } \ + while (YYID (0)) + +#endif + +/* YYFINAL -- State number of the termination state. */ +#define YYFINAL 6 +/* YYLAST -- Last index in YYTABLE. */ +#define YYLAST 35 + +/* YYNTOKENS -- Number of terminals. */ +#define YYNTOKENS 23 +/* YYNNTS -- Number of nonterminals. */ +#define YYNNTS 20 +/* YYNRULES -- Number of rules. */ +#define YYNRULES 39 +/* YYNRULES -- Number of states. */ +#define YYNSTATES 47 + +/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ +#define YYUNDEFTOK 2 +#define YYMAXUTOK 277 + +#define YYTRANSLATE(YYX) \ + ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) + +/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ +static const yytype_uint8 yytranslate[] = +{ + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22 +}; + +#if YYDEBUG +/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in + YYRHS. */ +static const yytype_uint8 yyprhs[] = +{ + 0, 0, 3, 4, 6, 8, 11, 12, 14, 15, + 17, 19, 20, 26, 27, 32, 33, 38, 40, 42, + 44, 46, 48, 51, 53, 55, 57, 59, 61, 63, + 65, 67, 71, 72, 74, 76, 80, 81, 83, 84 +}; + +/* YYRHS -- A `-1'-separated list of the rules' RHS. */ +static const yytype_int8 yyrhs[] = +{ + 24, 0, -1, -1, 25, -1, 28, -1, 25, 28, + -1, -1, 25, -1, -1, 20, -1, 17, -1, -1, + 10, 29, 11, 34, 27, -1, -1, 13, 31, 40, + 14, -1, -1, 15, 33, 38, 16, -1, 36, -1, + 30, -1, 32, -1, 41, -1, 9, -1, 35, 9, + -1, 3, -1, 4, -1, 6, -1, 5, -1, 7, + -1, 8, -1, 35, -1, 34, -1, 37, 17, 34, + -1, -1, 37, -1, 36, -1, 39, 17, 36, -1, + -1, 39, -1, -1, 18, 42, 26, 19, -1 +}; + +/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ +static const yytype_uint16 yyrline[] = +{ + 0, 100, 100, 102, 106, 107, 110, 112, 115, 117, + 118, 123, 122, 142, 141, 165, 164, 187, 188, 189, + 190, 194, 195, 199, 219, 241, 263, 285, 307, 325, + 353, 354, 357, 359, 363, 364, 367, 369, 374, 373 +}; +#endif + +#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE +/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. + First, the terminals, then, starting at YYNTOKENS, nonterminals. */ +static const char *const yytname[] = +{ + "$end", "error", "$undefined", "TOK_BOOLEAN", "TOK_INTEGER", "TOK_HEX", + "TOK_INTEGER64", "TOK_HEX64", "TOK_FLOAT", "TOK_STRING", "TOK_NAME", + "TOK_EQUALS", "TOK_NEWLINE", "TOK_ARRAY_START", "TOK_ARRAY_END", + "TOK_LIST_START", "TOK_LIST_END", "TOK_COMMA", "TOK_GROUP_START", + "TOK_GROUP_END", "TOK_SEMICOLON", "TOK_GARBAGE", "TOK_ERROR", "$accept", + "configuration", "setting_list", "setting_list_optional", + "setting_terminator", "setting", "$@1", "array", "$@2", "list", "$@3", + "value", "string", "simple_value", "value_list", "value_list_optional", + "simple_value_list", "simple_value_list_optional", "group", "$@4", 0 +}; +#endif + +# ifdef YYPRINT +/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to + token YYLEX-NUM. */ +static const yytype_uint16 yytoknum[] = +{ + 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, + 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, + 275, 276, 277 +}; +# endif + +/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ +static const yytype_uint8 yyr1[] = +{ + 0, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 27, 29, 28, 31, 30, 33, 32, 34, 34, 34, + 34, 35, 35, 36, 36, 36, 36, 36, 36, 36, + 37, 37, 38, 38, 39, 39, 40, 40, 42, 41 +}; + +/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ +static const yytype_uint8 yyr2[] = +{ + 0, 2, 0, 1, 1, 2, 0, 1, 0, 1, + 1, 0, 5, 0, 4, 0, 4, 1, 1, 1, + 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 3, 0, 1, 1, 3, 0, 1, 0, 4 +}; + +/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state + STATE-NUM when YYTABLE doesn't specify something else to do. Zero + means the default is an error. */ +static const yytype_uint8 yydefact[] = +{ + 2, 11, 0, 3, 4, 0, 1, 5, 0, 23, + 24, 26, 25, 27, 28, 21, 13, 15, 38, 18, + 19, 8, 29, 17, 20, 36, 32, 6, 10, 9, + 12, 22, 34, 37, 0, 30, 33, 0, 7, 0, + 0, 14, 0, 16, 39, 35, 31 +}; + +/* YYDEFGOTO[NTERM-NUM]. */ +static const yytype_int8 yydefgoto[] = +{ + -1, 2, 3, 39, 30, 4, 5, 19, 25, 20, + 26, 21, 22, 23, 36, 37, 33, 34, 24, 27 +}; + +/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing + STATE-NUM. */ +#define YYPACT_NINF -26 +static const yytype_int8 yypact[] = +{ + -8, -26, 12, -8, -26, 5, -26, -26, 0, -26, + -26, -26, -26, -26, -26, -26, -26, -26, -26, -26, + -26, -6, 10, -26, -26, 23, 0, -8, -26, -26, + -26, -26, -26, 3, 7, -26, 6, 8, -8, 14, + 23, -26, 0, -26, -26, -26, -26 +}; + +/* YYPGOTO[NTERM-NUM]. */ +static const yytype_int8 yypgoto[] = +{ + -26, -26, -5, -26, -26, -3, -26, -26, -26, -26, + -26, -25, -26, -15, -26, -26, -26, -26, -26, -26 +}; + +/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If + positive, shift that token. If negative, reduce the rule which + number is the opposite. If zero, do what YYDEFACT says. + If YYTABLE_NINF, syntax error. */ +#define YYTABLE_NINF -1 +static const yytype_uint8 yytable[] = +{ + 7, 35, 1, 9, 10, 11, 12, 13, 14, 15, + 32, 28, 6, 16, 29, 17, 8, 46, 18, 31, + 40, 41, 38, 42, 43, 45, 9, 10, 11, 12, + 13, 14, 15, 44, 0, 7 +}; + +static const yytype_int8 yycheck[] = +{ + 3, 26, 10, 3, 4, 5, 6, 7, 8, 9, + 25, 17, 0, 13, 20, 15, 11, 42, 18, 9, + 17, 14, 27, 17, 16, 40, 3, 4, 5, 6, + 7, 8, 9, 19, -1, 38 +}; + +/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing + symbol of state STATE-NUM. */ +static const yytype_uint8 yystos[] = +{ + 0, 10, 24, 25, 28, 29, 0, 28, 11, 3, + 4, 5, 6, 7, 8, 9, 13, 15, 18, 30, + 32, 34, 35, 36, 41, 31, 33, 42, 17, 20, + 27, 9, 36, 39, 40, 34, 37, 38, 25, 26, + 17, 14, 17, 16, 19, 36, 34 +}; + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY (-2) +#define YYEOF 0 + +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrorlab + + +/* Like YYERROR except do call yyerror. This remains here temporarily + to ease the transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ + +#define YYFAIL goto yyerrlab + +#define YYRECOVERING() (!!yyerrstatus) + +#define YYBACKUP(Token, Value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { \ + yychar = (Token); \ + yylval = (Value); \ + yytoken = YYTRANSLATE (yychar); \ + YYPOPSTACK (1); \ + goto yybackup; \ + } \ + else \ + { \ + yyerror (scanner, ctx, scan_ctx, YY_("syntax error: cannot back up")); \ + YYERROR; \ + } \ +while (YYID (0)) + + +#define YYTERROR 1 +#define YYERRCODE 256 + + +/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. + If N is 0, then set CURRENT to the empty location which ends + the previous symbol: RHS[0] (always defined). */ + +#define YYRHSLOC(Rhs, K) ((Rhs)[K]) +#ifndef YYLLOC_DEFAULT +# define YYLLOC_DEFAULT(Current, Rhs, N) \ + do \ + if (YYID (N)) \ + { \ + (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ + (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ + (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ + (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ + } \ + else \ + { \ + (Current).first_line = (Current).last_line = \ + YYRHSLOC (Rhs, 0).last_line; \ + (Current).first_column = (Current).last_column = \ + YYRHSLOC (Rhs, 0).last_column; \ + } \ + while (YYID (0)) +#endif + + +/* YY_LOCATION_PRINT -- Print the location on the stream. + This macro was not mandated originally: define only if we know + we won't break user code: when these are the locations we know. */ + +#ifndef YY_LOCATION_PRINT +# if YYLTYPE_IS_TRIVIAL +# define YY_LOCATION_PRINT(File, Loc) \ + fprintf (File, "%d.%d-%d.%d", \ + (Loc).first_line, (Loc).first_column, \ + (Loc).last_line, (Loc).last_column) +# else +# define YY_LOCATION_PRINT(File, Loc) ((void) 0) +# endif +#endif + + +/* YYLEX -- calling `yylex' with the right arguments. */ + +#ifdef YYLEX_PARAM +# define YYLEX yylex (&yylval, YYLEX_PARAM) +#else +# define YYLEX yylex (&yylval, scanner) +#endif + +/* Enable debugging if requested. */ +#if YYDEBUG + +# ifndef YYFPRINTF +# include <stdio.h> /* INFRINGES ON USER NAME SPACE */ +# define YYFPRINTF fprintf +# endif + +# define YYDPRINTF(Args) \ +do { \ + if (yydebug) \ + YYFPRINTF Args; \ +} while (YYID (0)) + +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ +do { \ + if (yydebug) \ + { \ + YYFPRINTF (stderr, "%s ", Title); \ + yy_symbol_print (stderr, \ + Type, Value, scanner, ctx, scan_ctx); \ + YYFPRINTF (stderr, "\n"); \ + } \ +} while (YYID (0)) + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, void *scanner, struct parse_context *ctx, struct scan_context *scan_ctx) +#else +static void +yy_symbol_value_print (yyoutput, yytype, yyvaluep, scanner, ctx, scan_ctx) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; + void *scanner; + struct parse_context *ctx; + struct scan_context *scan_ctx; +#endif +{ + if (!yyvaluep) + return; + YYUSE (scanner); + YYUSE (ctx); + YYUSE (scan_ctx); +# ifdef YYPRINT + if (yytype < YYNTOKENS) + YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); +# else + YYUSE (yyoutput); +# endif + switch (yytype) + { + default: + break; + } +} + + +/*--------------------------------. +| Print this symbol on YYOUTPUT. | +`--------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, void *scanner, struct parse_context *ctx, struct scan_context *scan_ctx) +#else +static void +yy_symbol_print (yyoutput, yytype, yyvaluep, scanner, ctx, scan_ctx) + FILE *yyoutput; + int yytype; + YYSTYPE const * const yyvaluep; + void *scanner; + struct parse_context *ctx; + struct scan_context *scan_ctx; +#endif +{ + if (yytype < YYNTOKENS) + YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); + else + YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); + + yy_symbol_value_print (yyoutput, yytype, yyvaluep, scanner, ctx, scan_ctx); + YYFPRINTF (yyoutput, ")"); +} + +/*------------------------------------------------------------------. +| yy_stack_print -- Print the state stack from its BOTTOM up to its | +| TOP (included). | +`------------------------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_stack_print (yytype_int16 *yybottom, yytype_int16 *yytop) +#else +static void +yy_stack_print (yybottom, yytop) + yytype_int16 *yybottom; + yytype_int16 *yytop; +#endif +{ + YYFPRINTF (stderr, "Stack now"); + for (; yybottom <= yytop; yybottom++) + { + int yybot = *yybottom; + YYFPRINTF (stderr, " %d", yybot); + } + YYFPRINTF (stderr, "\n"); +} + +# define YY_STACK_PRINT(Bottom, Top) \ +do { \ + if (yydebug) \ + yy_stack_print ((Bottom), (Top)); \ +} while (YYID (0)) + + +/*------------------------------------------------. +| Report that the YYRULE is going to be reduced. | +`------------------------------------------------*/ + +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yy_reduce_print (YYSTYPE *yyvsp, int yyrule, void *scanner, struct parse_context *ctx, struct scan_context *scan_ctx) +#else +static void +yy_reduce_print (yyvsp, yyrule, scanner, ctx, scan_ctx) + YYSTYPE *yyvsp; + int yyrule; + void *scanner; + struct parse_context *ctx; + struct scan_context *scan_ctx; +#endif +{ + int yynrhs = yyr2[yyrule]; + int yyi; + unsigned long int yylno = yyrline[yyrule]; + YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n", + yyrule - 1, yylno); + /* The symbols being reduced. */ + for (yyi = 0; yyi < yynrhs; yyi++) + { + YYFPRINTF (stderr, " $%d = ", yyi + 1); + yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi], + &(yyvsp[(yyi + 1) - (yynrhs)]) + , scanner, ctx, scan_ctx); + YYFPRINTF (stderr, "\n"); + } +} + +# define YY_REDUCE_PRINT(Rule) \ +do { \ + if (yydebug) \ + yy_reduce_print (yyvsp, Rule, scanner, ctx, scan_ctx); \ +} while (YYID (0)) + +/* Nonzero means print parse trace. It is left uninitialized so that + multiple parsers can coexist. */ +int yydebug; +#else /* !YYDEBUG */ +# define YYDPRINTF(Args) +# define YY_SYMBOL_PRINT(Title, Type, Value, Location) +# define YY_STACK_PRINT(Bottom, Top) +# define YY_REDUCE_PRINT(Rule) +#endif /* !YYDEBUG */ + + +/* YYINITDEPTH -- initial size of the parser's stacks. */ +#ifndef YYINITDEPTH +# define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only + if the built-in stack extension method is used). + + Do not make this value too large; the results are undefined if + YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) + evaluated with infinite-precision integer arithmetic. */ + +#ifndef YYMAXDEPTH +# define YYMAXDEPTH 10000 +#endif + + + +#if YYERROR_VERBOSE + +# ifndef yystrlen +# if defined __GLIBC__ && defined _STRING_H +# define yystrlen strlen +# else +/* Return the length of YYSTR. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static YYSIZE_T +yystrlen (const char *yystr) +#else +static YYSIZE_T +yystrlen (yystr) + const char *yystr; +#endif +{ + YYSIZE_T yylen; + for (yylen = 0; yystr[yylen]; yylen++) + continue; + return yylen; +} +# endif +# endif + +# ifndef yystpcpy +# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE +# define yystpcpy stpcpy +# else +/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in + YYDEST. */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static char * +yystpcpy (char *yydest, const char *yysrc) +#else +static char * +yystpcpy (yydest, yysrc) + char *yydest; + const char *yysrc; +#endif +{ + char *yyd = yydest; + const char *yys = yysrc; + + while ((*yyd++ = *yys++) != '\0') + continue; + + return yyd - 1; +} +# endif +# endif + +# ifndef yytnamerr +/* Copy to YYRES the contents of YYSTR after stripping away unnecessary + quotes and backslashes, so that it's suitable for yyerror. The + heuristic is that double-quoting is unnecessary unless the string + contains an apostrophe, a comma, or backslash (other than + backslash-backslash). YYSTR is taken from yytname. If YYRES is + null, do not copy; instead, return the length of what the result + would have been. */ +static YYSIZE_T +yytnamerr (char *yyres, const char *yystr) +{ + if (*yystr == '"') + { + YYSIZE_T yyn = 0; + char const *yyp = yystr; + + for (;;) + switch (*++yyp) + { + case '\'': + case ',': + goto do_not_strip_quotes; + + case '\\': + if (*++yyp != '\\') + goto do_not_strip_quotes; + /* Fall through. */ + default: + if (yyres) + yyres[yyn] = *yyp; + yyn++; + break; + + case '"': + if (yyres) + yyres[yyn] = '\0'; + return yyn; + } + do_not_strip_quotes: ; + } + + if (! yyres) + return yystrlen (yystr); + + return yystpcpy (yyres, yystr) - yyres; +} +# endif + +/* Copy into YYRESULT an error message about the unexpected token + YYCHAR while in state YYSTATE. Return the number of bytes copied, + including the terminating null byte. If YYRESULT is null, do not + copy anything; just return the number of bytes that would be + copied. As a special case, return 0 if an ordinary "syntax error" + message will do. Return YYSIZE_MAXIMUM if overflow occurs during + size calculation. */ +static YYSIZE_T +yysyntax_error (char *yyresult, int yystate, int yychar) +{ + int yyn = yypact[yystate]; + + if (! (YYPACT_NINF < yyn && yyn <= YYLAST)) + return 0; + else + { + int yytype = YYTRANSLATE (yychar); + YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); + YYSIZE_T yysize = yysize0; + YYSIZE_T yysize1; + int yysize_overflow = 0; + enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 }; + char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; + int yyx; + +# if 0 + /* This is so xgettext sees the translatable formats that are + constructed on the fly. */ + YY_("syntax error, unexpected %s"); + YY_("syntax error, unexpected %s, expecting %s"); + YY_("syntax error, unexpected %s, expecting %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s"); + YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); +# endif + char *yyfmt; + char const *yyf; + static char const yyunexpected[] = "syntax error, unexpected %s"; + static char const yyexpecting[] = ", expecting %s"; + static char const yyor[] = " or %s"; + char yyformat[sizeof yyunexpected + + sizeof yyexpecting - 1 + + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) + * (sizeof yyor - 1))]; + char const *yyprefix = yyexpecting; + + /* Start YYX at -YYN if negative to avoid negative indexes in + YYCHECK. */ + int yyxbegin = yyn < 0 ? -yyn : 0; + + /* Stay within bounds of both yycheck and yytname. */ + int yychecklim = YYLAST - yyn + 1; + int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; + int yycount = 1; + + yyarg[0] = yytname[yytype]; + yyfmt = yystpcpy (yyformat, yyunexpected); + + for (yyx = yyxbegin; yyx < yyxend; ++yyx) + if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) + { + if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) + { + yycount = 1; + yysize = yysize0; + yyformat[sizeof yyunexpected - 1] = '\0'; + break; + } + yyarg[yycount++] = yytname[yyx]; + yysize1 = yysize + yytnamerr (0, yytname[yyx]); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + yyfmt = yystpcpy (yyfmt, yyprefix); + yyprefix = yyor; + } + + yyf = YY_(yyformat); + yysize1 = yysize + yystrlen (yyf); + yysize_overflow |= (yysize1 < yysize); + yysize = yysize1; + + if (yysize_overflow) + return YYSIZE_MAXIMUM; + + if (yyresult) + { + /* Avoid sprintf, as that infringes on the user's name space. + Don't have undefined behavior even if the translation + produced a string with the wrong number of "%s"s. */ + char *yyp = yyresult; + int yyi = 0; + while ((*yyp = *yyf) != '\0') + { + if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) + { + yyp += yytnamerr (yyp, yyarg[yyi++]); + yyf += 2; + } + else + { + yyp++; + yyf++; + } + } + } + return yysize; + } +} +#endif /* YYERROR_VERBOSE */ + + +/*-----------------------------------------------. +| Release the memory associated to this symbol. | +`-----------------------------------------------*/ + +/*ARGSUSED*/ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +static void +yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, void *scanner, struct parse_context *ctx, struct scan_context *scan_ctx) +#else +static void +yydestruct (yymsg, yytype, yyvaluep, scanner, ctx, scan_ctx) + const char *yymsg; + int yytype; + YYSTYPE *yyvaluep; + void *scanner; + struct parse_context *ctx; + struct scan_context *scan_ctx; +#endif +{ + YYUSE (yyvaluep); + YYUSE (scanner); + YYUSE (ctx); + YYUSE (scan_ctx); + + if (!yymsg) + yymsg = "Deleting"; + YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); + + switch (yytype) + { + + default: + break; + } +} + +/* Prevent warnings from -Wmissing-prototypes. */ +#ifdef YYPARSE_PARAM +#if defined __STDC__ || defined __cplusplus +int yyparse (void *YYPARSE_PARAM); +#else +int yyparse (); +#endif +#else /* ! YYPARSE_PARAM */ +#if defined __STDC__ || defined __cplusplus +int yyparse (void *scanner, struct parse_context *ctx, struct scan_context *scan_ctx); +#else +int yyparse (); +#endif +#endif /* ! YYPARSE_PARAM */ + + + + + +/*-------------------------. +| yyparse or yypush_parse. | +`-------------------------*/ + +#ifdef YYPARSE_PARAM +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void *YYPARSE_PARAM) +#else +int +yyparse (YYPARSE_PARAM) + void *YYPARSE_PARAM; +#endif +#else /* ! YYPARSE_PARAM */ +#if (defined __STDC__ || defined __C99__FUNC__ \ + || defined __cplusplus || defined _MSC_VER) +int +yyparse (void *scanner, struct parse_context *ctx, struct scan_context *scan_ctx) +#else +int +yyparse (scanner, ctx, scan_ctx) + void *scanner; + struct parse_context *ctx; + struct scan_context *scan_ctx; +#endif +#endif +{ +/* The lookahead symbol. */ +int yychar; + +/* The semantic value of the lookahead symbol. */ +YYSTYPE yylval; + + /* Number of syntax errors so far. */ + int yynerrs; + + int yystate; + /* Number of tokens to shift before error messages enabled. */ + int yyerrstatus; + + /* The stacks and their tools: + `yyss': related to states. + `yyvs': related to semantic values. + + Refer to the stacks thru separate pointers, to allow yyoverflow + to reallocate them elsewhere. */ + + /* The state stack. */ + yytype_int16 yyssa[YYINITDEPTH]; + yytype_int16 *yyss; + yytype_int16 *yyssp; + + /* The semantic value stack. */ + YYSTYPE yyvsa[YYINITDEPTH]; + YYSTYPE *yyvs; + YYSTYPE *yyvsp; + + YYSIZE_T yystacksize; + + int yyn; + int yyresult; + /* Lookahead token as an internal (translated) token number. */ + int yytoken; + /* The variables used to return semantic value and location from the + action routines. */ + YYSTYPE yyval; + +#if YYERROR_VERBOSE + /* Buffer for error messages, and its allocated size. */ + char yymsgbuf[128]; + char *yymsg = yymsgbuf; + YYSIZE_T yymsg_alloc = sizeof yymsgbuf; +#endif + +#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N)) + + /* The number of symbols on the RHS of the reduced rule. + Keep to zero when no symbol should be popped. */ + int yylen = 0; + + yytoken = 0; + yyss = yyssa; + yyvs = yyvsa; + yystacksize = YYINITDEPTH; + + YYDPRINTF ((stderr, "Starting parse\n")); + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + yyssp = yyss; + yyvsp = yyvs; + + goto yysetstate; + +/*------------------------------------------------------------. +| yynewstate -- Push a new state, which is found in yystate. | +`------------------------------------------------------------*/ + yynewstate: + /* In all cases, when you get here, the value and location stacks + have just been pushed. So pushing a state here evens the stacks. */ + yyssp++; + + yysetstate: + *yyssp = yystate; + + if (yyss + yystacksize - 1 <= yyssp) + { + /* Get the current used size of the three stacks, in elements. */ + YYSIZE_T yysize = yyssp - yyss + 1; + +#ifdef yyoverflow + { + /* Give user a chance to reallocate the stack. Use copies of + these so that the &'s don't force the real ones into + memory. */ + YYSTYPE *yyvs1 = yyvs; + yytype_int16 *yyss1 = yyss; + + /* Each stack pointer address is followed by the size of the + data in use in that stack, in bytes. This used to be a + conditional around just the two extra args, but that might + be undefined if yyoverflow is a macro. */ + yyoverflow (YY_("memory exhausted"), + &yyss1, yysize * sizeof (*yyssp), + &yyvs1, yysize * sizeof (*yyvsp), + &yystacksize); + + yyss = yyss1; + yyvs = yyvs1; + } +#else /* no yyoverflow */ +# ifndef YYSTACK_RELOCATE + goto yyexhaustedlab; +# else + /* Extend the stack our own way. */ + if (YYMAXDEPTH <= yystacksize) + goto yyexhaustedlab; + yystacksize *= 2; + if (YYMAXDEPTH < yystacksize) + yystacksize = YYMAXDEPTH; + + { + yytype_int16 *yyss1 = yyss; + union yyalloc *yyptr = + (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); + if (! yyptr) + goto yyexhaustedlab; + YYSTACK_RELOCATE (yyss_alloc, yyss); + YYSTACK_RELOCATE (yyvs_alloc, yyvs); +# undef YYSTACK_RELOCATE + if (yyss1 != yyssa) + YYSTACK_FREE (yyss1); + } +# endif +#endif /* no yyoverflow */ + + yyssp = yyss + yysize - 1; + yyvsp = yyvs + yysize - 1; + + YYDPRINTF ((stderr, "Stack size increased to %lu\n", + (unsigned long int) yystacksize)); + + if (yyss + yystacksize - 1 <= yyssp) + YYABORT; + } + + YYDPRINTF ((stderr, "Entering state %d\n", yystate)); + + if (yystate == YYFINAL) + YYACCEPT; + + goto yybackup; + +/*-----------. +| yybackup. | +`-----------*/ +yybackup: + + /* Do appropriate processing given the current state. Read a + lookahead token if we need one and don't already have one. */ + + /* First try to decide what to do without reference to lookahead token. */ + yyn = yypact[yystate]; + if (yyn == YYPACT_NINF) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* YYCHAR is either YYEMPTY or YYEOF or a valid lookahead symbol. */ + if (yychar == YYEMPTY) + { + YYDPRINTF ((stderr, "Reading a token: ")); + yychar = YYLEX; + } + + if (yychar <= YYEOF) + { + yychar = yytoken = YYEOF; + YYDPRINTF ((stderr, "Now at end of input.\n")); + } + else + { + yytoken = YYTRANSLATE (yychar); + YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); + } + + /* If the proper action on seeing token YYTOKEN is to reduce or to + detect an error, take that action. */ + yyn += yytoken; + if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) + goto yydefault; + yyn = yytable[yyn]; + if (yyn <= 0) + { + if (yyn == 0 || yyn == YYTABLE_NINF) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + + /* Count tokens shifted since error; after three, turn off error + status. */ + if (yyerrstatus) + yyerrstatus--; + + /* Shift the lookahead token. */ + YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); + + /* Discard the shifted token. */ + yychar = YYEMPTY; + + yystate = yyn; + *++yyvsp = yylval; + + goto yynewstate; + + +/*-----------------------------------------------------------. +| yydefault -- do the default action for the current state. | +`-----------------------------------------------------------*/ +yydefault: + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + goto yyreduce; + + +/*-----------------------------. +| yyreduce -- Do a reduction. | +`-----------------------------*/ +yyreduce: + /* yyn is the number of a rule to reduce with. */ + yylen = yyr2[yyn]; + + /* If YYLEN is nonzero, implement the default value of the action: + `$$ = $1'. + + Otherwise, the following line sets YYVAL to garbage. + This behavior is undocumented and Bison + users should not rely upon it. Assigning to YYVAL + unconditionally makes the parser a bit smaller, and it avoids a + GCC warning that YYVAL may be used uninitialized. */ + yyval = yyvsp[1-yylen]; + + + YY_REDUCE_PRINT (yyn); + switch (yyn) + { + case 11: + +/* Line 1455 of yacc.c */ +#line 123 "grammar.y" + { + ctx->setting = config_setting_add(ctx->parent, (yyvsp[(1) - (1)].sval), CONFIG_TYPE_NONE); + + if(ctx->setting == NULL) + { + libconfig_yyerror(scanner, ctx, scan_ctx, err_duplicate_setting); + YYABORT; + } + else + { + CAPTURE_PARSE_POS(ctx->setting); + } + } + break; + + case 13: + +/* Line 1455 of yacc.c */ +#line 142 "grammar.y" + { + if(IN_LIST()) + { + ctx->parent = config_setting_add(ctx->parent, NULL, CONFIG_TYPE_ARRAY); + CAPTURE_PARSE_POS(ctx->parent); + } + else + { + ctx->setting->type = CONFIG_TYPE_ARRAY; + ctx->parent = ctx->setting; + ctx->setting = NULL; + } + } + break; + + case 14: + +/* Line 1455 of yacc.c */ +#line 157 "grammar.y" + { + if(ctx->parent) + ctx->parent = ctx->parent->parent; + } + break; + + case 15: + +/* Line 1455 of yacc.c */ +#line 165 "grammar.y" + { + if(IN_LIST()) + { + ctx->parent = config_setting_add(ctx->parent, NULL, CONFIG_TYPE_LIST); + CAPTURE_PARSE_POS(ctx->parent); + } + else + { + ctx->setting->type = CONFIG_TYPE_LIST; + ctx->parent = ctx->setting; + ctx->setting = NULL; + } + } + break; + + case 16: + +/* Line 1455 of yacc.c */ +#line 180 "grammar.y" + { + if(ctx->parent) + ctx->parent = ctx->parent->parent; + } + break; + + case 21: + +/* Line 1455 of yacc.c */ +#line 194 "grammar.y" + { parsectx_append_string(ctx, (yyvsp[(1) - (1)].sval)); free((yyvsp[(1) - (1)].sval)); } + break; + + case 22: + +/* Line 1455 of yacc.c */ +#line 195 "grammar.y" + { parsectx_append_string(ctx, (yyvsp[(2) - (2)].sval)); free((yyvsp[(2) - (2)].sval)); } + break; + + case 23: + +/* Line 1455 of yacc.c */ +#line 200 "grammar.y" + { + if(IN_ARRAY() || IN_LIST()) + { + config_setting_t *e = config_setting_set_bool_elem(ctx->parent, -1, + (int)(yyvsp[(1) - (1)].ival)); + + if(! e) + { + libconfig_yyerror(scanner, ctx, scan_ctx, err_array_elem_type); + YYABORT; + } + else + { + CAPTURE_PARSE_POS(e); + } + } + else + config_setting_set_bool(ctx->setting, (int)(yyvsp[(1) - (1)].ival)); + } + break; + + case 24: + +/* Line 1455 of yacc.c */ +#line 220 "grammar.y" + { + if(IN_ARRAY() || IN_LIST()) + { + config_setting_t *e = config_setting_set_int_elem(ctx->parent, -1, (yyvsp[(1) - (1)].ival)); + if(! e) + { + libconfig_yyerror(scanner, ctx, scan_ctx, err_array_elem_type); + YYABORT; + } + else + { + config_setting_set_format(e, CONFIG_FORMAT_DEFAULT); + CAPTURE_PARSE_POS(e); + } + } + else + { + config_setting_set_int(ctx->setting, (yyvsp[(1) - (1)].ival)); + config_setting_set_format(ctx->setting, CONFIG_FORMAT_DEFAULT); + } + } + break; + + case 25: + +/* Line 1455 of yacc.c */ +#line 242 "grammar.y" + { + if(IN_ARRAY() || IN_LIST()) + { + config_setting_t *e = config_setting_set_int64_elem(ctx->parent, -1, (yyvsp[(1) - (1)].llval)); + if(! e) + { + libconfig_yyerror(scanner, ctx, scan_ctx, err_array_elem_type); + YYABORT; + } + else + { + config_setting_set_format(e, CONFIG_FORMAT_DEFAULT); + CAPTURE_PARSE_POS(e); + } + } + else + { + config_setting_set_int64(ctx->setting, (yyvsp[(1) - (1)].llval)); + config_setting_set_format(ctx->setting, CONFIG_FORMAT_DEFAULT); + } + } + break; + + case 26: + +/* Line 1455 of yacc.c */ +#line 264 "grammar.y" + { + if(IN_ARRAY() || IN_LIST()) + { + config_setting_t *e = config_setting_set_int_elem(ctx->parent, -1, (yyvsp[(1) - (1)].ival)); + if(! e) + { + libconfig_yyerror(scanner, ctx, scan_ctx, err_array_elem_type); + YYABORT; + } + else + { + config_setting_set_format(e, CONFIG_FORMAT_HEX); + CAPTURE_PARSE_POS(e); + } + } + else + { + config_setting_set_int(ctx->setting, (yyvsp[(1) - (1)].ival)); + config_setting_set_format(ctx->setting, CONFIG_FORMAT_HEX); + } + } + break; + + case 27: + +/* Line 1455 of yacc.c */ +#line 286 "grammar.y" + { + if(IN_ARRAY() || IN_LIST()) + { + config_setting_t *e = config_setting_set_int64_elem(ctx->parent, -1, (yyvsp[(1) - (1)].llval)); + if(! e) + { + libconfig_yyerror(scanner, ctx, scan_ctx, err_array_elem_type); + YYABORT; + } + else + { + config_setting_set_format(e, CONFIG_FORMAT_HEX); + CAPTURE_PARSE_POS(e); + } + } + else + { + config_setting_set_int64(ctx->setting, (yyvsp[(1) - (1)].llval)); + config_setting_set_format(ctx->setting, CONFIG_FORMAT_HEX); + } + } + break; + + case 28: + +/* Line 1455 of yacc.c */ +#line 308 "grammar.y" + { + if(IN_ARRAY() || IN_LIST()) + { + config_setting_t *e = config_setting_set_float_elem(ctx->parent, -1, (yyvsp[(1) - (1)].fval)); + if(! e) + { + libconfig_yyerror(scanner, ctx, scan_ctx, err_array_elem_type); + YYABORT; + } + else + { + CAPTURE_PARSE_POS(e); + } + } + else + config_setting_set_float(ctx->setting, (yyvsp[(1) - (1)].fval)); + } + break; + + case 29: + +/* Line 1455 of yacc.c */ +#line 326 "grammar.y" + { + if(IN_ARRAY() || IN_LIST()) + { + const char *s = parsectx_take_string(ctx); + config_setting_t *e = config_setting_set_string_elem(ctx->parent, -1, s); + _delete(s); + + if(! e) + { + libconfig_yyerror(scanner, ctx, scan_ctx, err_array_elem_type); + YYABORT; + } + else + { + CAPTURE_PARSE_POS(e); + } + } + else + { + const char *s = parsectx_take_string(ctx); + config_setting_set_string(ctx->setting, s); + _delete(s); + } + } + break; + + case 38: + +/* Line 1455 of yacc.c */ +#line 374 "grammar.y" + { + if(IN_LIST()) + { + ctx->parent = config_setting_add(ctx->parent, NULL, CONFIG_TYPE_GROUP); + CAPTURE_PARSE_POS(ctx->parent); + } + else + { + ctx->setting->type = CONFIG_TYPE_GROUP; + ctx->parent = ctx->setting; + ctx->setting = NULL; + } + } + break; + + case 39: + +/* Line 1455 of yacc.c */ +#line 389 "grammar.y" + { + if(ctx->parent) + ctx->parent = ctx->parent->parent; + } + break; + + + +/* Line 1455 of yacc.c */ +#line 1788 "grammar.c" + default: break; + } + YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc); + + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + + *++yyvsp = yyval; + + /* Now `shift' the result of the reduction. Determine what state + that goes to, based on the state we popped back to and the rule + number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; + if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTOKENS]; + + goto yynewstate; + + +/*------------------------------------. +| yyerrlab -- here on detecting error | +`------------------------------------*/ +yyerrlab: + /* If not already recovering from an error, report this error. */ + if (!yyerrstatus) + { + ++yynerrs; +#if ! YYERROR_VERBOSE + yyerror (scanner, ctx, scan_ctx, YY_("syntax error")); +#else + { + YYSIZE_T yysize = yysyntax_error (0, yystate, yychar); + if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM) + { + YYSIZE_T yyalloc = 2 * yysize; + if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM)) + yyalloc = YYSTACK_ALLOC_MAXIMUM; + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); + yymsg = (char *) YYSTACK_ALLOC (yyalloc); + if (yymsg) + yymsg_alloc = yyalloc; + else + { + yymsg = yymsgbuf; + yymsg_alloc = sizeof yymsgbuf; + } + } + + if (0 < yysize && yysize <= yymsg_alloc) + { + (void) yysyntax_error (yymsg, yystate, yychar); + yyerror (scanner, ctx, scan_ctx, yymsg); + } + else + { + yyerror (scanner, ctx, scan_ctx, YY_("syntax error")); + if (yysize != 0) + goto yyexhaustedlab; + } + } +#endif + } + + + + if (yyerrstatus == 3) + { + /* If just tried and failed to reuse lookahead token after an + error, discard it. */ + + if (yychar <= YYEOF) + { + /* Return failure if at end of input. */ + if (yychar == YYEOF) + YYABORT; + } + else + { + yydestruct ("Error: discarding", + yytoken, &yylval, scanner, ctx, scan_ctx); + yychar = YYEMPTY; + } + } + + /* Else will try to reuse lookahead token after shifting the error + token. */ + goto yyerrlab1; + + +/*---------------------------------------------------. +| yyerrorlab -- error raised explicitly by YYERROR. | +`---------------------------------------------------*/ +yyerrorlab: + + /* Pacify compilers like GCC when the user code never invokes + YYERROR and the label yyerrorlab therefore never appears in user + code. */ + if (/*CONSTCOND*/ 0) + goto yyerrorlab; + + /* Do not reclaim the symbols of the rule which action triggered + this YYERROR. */ + YYPOPSTACK (yylen); + yylen = 0; + YY_STACK_PRINT (yyss, yyssp); + yystate = *yyssp; + goto yyerrlab1; + + +/*-------------------------------------------------------------. +| yyerrlab1 -- common code for both syntax error and YYERROR. | +`-------------------------------------------------------------*/ +yyerrlab1: + yyerrstatus = 3; /* Each real token shifted decrements this. */ + + for (;;) + { + yyn = yypact[yystate]; + if (yyn != YYPACT_NINF) + { + yyn += YYTERROR; + if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) + { + yyn = yytable[yyn]; + if (0 < yyn) + break; + } + } + + /* Pop the current state because it cannot handle the error token. */ + if (yyssp == yyss) + YYABORT; + + + yydestruct ("Error: popping", + yystos[yystate], yyvsp, scanner, ctx, scan_ctx); + YYPOPSTACK (1); + yystate = *yyssp; + YY_STACK_PRINT (yyss, yyssp); + } + + *++yyvsp = yylval; + + + /* Shift the error token. */ + YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); + + yystate = yyn; + goto yynewstate; + + +/*-------------------------------------. +| yyacceptlab -- YYACCEPT comes here. | +`-------------------------------------*/ +yyacceptlab: + yyresult = 0; + goto yyreturn; + +/*-----------------------------------. +| yyabortlab -- YYABORT comes here. | +`-----------------------------------*/ +yyabortlab: + yyresult = 1; + goto yyreturn; + +#if !defined(yyoverflow) || YYERROR_VERBOSE +/*-------------------------------------------------. +| yyexhaustedlab -- memory exhaustion comes here. | +`-------------------------------------------------*/ +yyexhaustedlab: + yyerror (scanner, ctx, scan_ctx, YY_("memory exhausted")); + yyresult = 2; + /* Fall through. */ +#endif + +yyreturn: + if (yychar != YYEMPTY) + yydestruct ("Cleanup: discarding lookahead", + yytoken, &yylval, scanner, ctx, scan_ctx); + /* Do not reclaim the symbols of the rule which action triggered + this YYABORT or YYACCEPT. */ + YYPOPSTACK (yylen); + YY_STACK_PRINT (yyss, yyssp); + while (yyssp != yyss) + { + yydestruct ("Cleanup: popping", + yystos[*yyssp], yyvsp, scanner, ctx, scan_ctx); + YYPOPSTACK (1); + } +#ifndef yyoverflow + if (yyss != yyssa) + YYSTACK_FREE (yyss); +#endif +#if YYERROR_VERBOSE + if (yymsg != yymsgbuf) + YYSTACK_FREE (yymsg); +#endif + /* Make sure YYID is used. */ + return YYID (yyresult); +} + + + +/* Line 1675 of yacc.c */ +#line 395 "grammar.y" + + diff --git a/3rdparty/libconfig/grammar.h b/3rdparty/libconfig/grammar.h new file mode 100644 index 000000000..2ce199dde --- /dev/null +++ b/3rdparty/libconfig/grammar.h @@ -0,0 +1,113 @@ + +/* A Bison parser, made by GNU Bison 2.4.1. */ + +/* Skeleton interface for Bison's Yacc-like parsers in C + + Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Free Software Foundation, Inc. + + 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 <http://www.gnu.org/licenses/>. */ + +/* As a special exception, you may create a larger work that contains + part or all of the Bison parser skeleton and distribute that work + under terms of your choice, so long as that work isn't itself a + parser generator using the skeleton or a modified version thereof + as a parser skeleton. Alternatively, if you modify or redistribute + the parser skeleton itself, you may (at your option) remove this + special exception, which will cause the skeleton and the resulting + Bison output files to be licensed under the GNU General Public + License without this special exception. + + This special exception was added by the Free Software Foundation in + version 2.2 of Bison. */ + + +/* Tokens. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + /* Put the tokens into the symbol table, so that GDB and other debuggers + know about them. */ + enum yytokentype { + TOK_BOOLEAN = 258, + TOK_INTEGER = 259, + TOK_HEX = 260, + TOK_INTEGER64 = 261, + TOK_HEX64 = 262, + TOK_FLOAT = 263, + TOK_STRING = 264, + TOK_NAME = 265, + TOK_EQUALS = 266, + TOK_NEWLINE = 267, + TOK_ARRAY_START = 268, + TOK_ARRAY_END = 269, + TOK_LIST_START = 270, + TOK_LIST_END = 271, + TOK_COMMA = 272, + TOK_GROUP_START = 273, + TOK_GROUP_END = 274, + TOK_SEMICOLON = 275, + TOK_GARBAGE = 276, + TOK_ERROR = 277 + }; +#endif +/* Tokens. */ +#define TOK_BOOLEAN 258 +#define TOK_INTEGER 259 +#define TOK_HEX 260 +#define TOK_INTEGER64 261 +#define TOK_HEX64 262 +#define TOK_FLOAT 263 +#define TOK_STRING 264 +#define TOK_NAME 265 +#define TOK_EQUALS 266 +#define TOK_NEWLINE 267 +#define TOK_ARRAY_START 268 +#define TOK_ARRAY_END 269 +#define TOK_LIST_START 270 +#define TOK_LIST_END 271 +#define TOK_COMMA 272 +#define TOK_GROUP_START 273 +#define TOK_GROUP_END 274 +#define TOK_SEMICOLON 275 +#define TOK_GARBAGE 276 +#define TOK_ERROR 277 + + + + +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +typedef union YYSTYPE +{ + +/* Line 1676 of yacc.c */ +#line 85 "grammar.y" + + int ival; + long long llval; + double fval; + char *sval; + + + +/* Line 1676 of yacc.c */ +#line 105 "grammar.h" +} YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define yystype YYSTYPE /* obsolescent; will be withdrawn */ +# define YYSTYPE_IS_DECLARED 1 +#endif + + + + diff --git a/conf/import-tmpl/atcommand_conf.txt b/3rdparty/libconfig/libconfig-1.4.8 index e69de29bb..e69de29bb 100644 --- a/conf/import-tmpl/atcommand_conf.txt +++ b/3rdparty/libconfig/libconfig-1.4.8 diff --git a/3rdparty/libconfig/libconfig.c b/3rdparty/libconfig/libconfig.c new file mode 100644 index 000000000..e64213c16 --- /dev/null +++ b/3rdparty/libconfig/libconfig.c @@ -0,0 +1,1615 @@ +/* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files + Copyright (C) 2005-2010 Mark A Lindner + + This file is part of libconfig. + + This library 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 library 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 library. If not, see <http://www.gnu.org/licenses/>. + ---------------------------------------------------------------------------- +*/ + +#ifdef HAVE_CONFIG_H +#include "ac_config.h" +#endif + +#include "libconfig.h" +#include "grammar.h" +#include "scanner.h" +#include "scanctx.h" +#include "parsectx.h" +#include "wincompat.h" + +#include <locale.h> + +#ifdef HAVE_XLOCALE_H +#include <xlocale.h> +#endif + +#include <stdlib.h> +#include <string.h> +#include <ctype.h> + +#define PATH_TOKENS ":./" +#define CHUNK_SIZE 16 +#define FLOAT_PRECISION 10 + +#define _new(T) (T *)calloc(sizeof(T), 1) /* zeroed */ +#define _delete(P) free((void *)(P)) + +/* ------------------------------------------------------------------------- */ + +#ifndef LIBCONFIG_STATIC +#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) + +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + return(TRUE); +} + +#endif /* WIN32 */ +#endif /* LIBCONFIG_STATIC */ + +/* ------------------------------------------------------------------------- */ + +static const char *__io_error = "file I/O error"; + +static void __config_list_destroy(config_list_t *list); +static void __config_write_setting(const config_setting_t *setting, + FILE *stream, int depth, + unsigned short tab_width); + +extern int libconfig_yyparse(void *scanner, struct parse_context *ctx, + struct scan_context *scan_ctx); +extern int libconfig_yylex_init_extra(struct scan_context *scan_ctx, + yyscan_t *scanner); + +/* ------------------------------------------------------------------------- */ + +static void __config_locale_override(void) +{ +#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) \ + && ! defined(__MINGW32__) + + _configthreadlocale(_ENABLE_PER_THREAD_LOCALE); + setlocale(LC_NUMERIC, "C"); + +#elif defined(__APPLE__) + + locale_t loc = newlocale(LC_NUMERIC_MASK, "C", NULL); + uselocale(loc); + +#elif ((defined HAVE_NEWLOCALE) && (defined HAVE_USELOCALE)) + + locale_t loc = newlocale(LC_NUMERIC, "C", NULL); + uselocale(loc); + +#else + +#warning "No way to modify calling thread's locale!" + +#endif +} + +/* ------------------------------------------------------------------------- */ + +static void __config_locale_restore(void) +{ +#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) \ + && ! defined(__MINGW32__) + + _configthreadlocale(_DISABLE_PER_THREAD_LOCALE); + +#elif ((defined HAVE_USELOCALE) && (defined HAVE_FREELOCALE)) + + locale_t loc = uselocale(LC_GLOBAL_LOCALE); + freelocale(loc); + +#else + +#warning "No way to modify calling thread's locale!" + +#endif +} + +/* ------------------------------------------------------------------------- */ + +static int __config_name_compare(const char *a, const char *b) +{ + const char *p, *q; + + for(p = a, q = b; ; p++, q++) + { + int pd = ((! *p) || strchr(PATH_TOKENS, *p)); + int qd = ((! *q) || strchr(PATH_TOKENS, *q)); + + if(pd && qd) + break; + else if(pd) + return(-1); + else if(qd) + return(1); + else if(*p < *q) + return(-1); + else if(*p > *q) + return(1); + } + + return(0); +} + +/* ------------------------------------------------------------------------- */ + +static void __config_indent(FILE *stream, int depth, unsigned short w) +{ + if(w) + fprintf(stream, "%*s", (depth - 1) * w, " "); + else + { + int i; + for(i = 0; i < (depth - 1); ++i) + fputc('\t', stream); + } +} + +/* ------------------------------------------------------------------------- */ + +static void __config_write_value(const config_value_t *value, int type, + int format, int depth, + unsigned short tab_width, FILE *stream) +{ + char fbuf[64]; + + switch(type) + { + /* boolean */ + case CONFIG_TYPE_BOOL: + fputs(value->ival ? "true" : "false", stream); + break; + + /* int */ + case CONFIG_TYPE_INT: + switch(format) + { + case CONFIG_FORMAT_HEX: + fprintf(stream, "0x%X", value->ival); + break; + + case CONFIG_FORMAT_DEFAULT: + default: + fprintf(stream, "%d", value->ival); + break; + } + break; + + /* 64-bit int */ + case CONFIG_TYPE_INT64: + switch(format) + { + case CONFIG_FORMAT_HEX: + fprintf(stream, "0x" INT64_HEX_FMT "L", value->llval); + break; + + case CONFIG_FORMAT_DEFAULT: + default: + fprintf(stream, INT64_FMT "L", value->llval); + break; + } + break; + + /* float */ + case CONFIG_TYPE_FLOAT: + { + char *q; + + snprintf(fbuf, sizeof(fbuf) - 3, "%.*g", FLOAT_PRECISION, value->fval); + + /* check for exponent */ + q = strchr(fbuf, 'e'); + if(! q) + { + /* no exponent */ + if(! strchr(fbuf, '.')) /* no decimal point */ + strcat(fbuf, ".0"); + else + { + /* has decimal point */ + char *p; + + for(p = fbuf + strlen(fbuf) - 1; p > fbuf; --p) + { + if(*p != '0') + { + *(++p) = '\0'; + break; + } + } + } + } + + fputs(fbuf, stream); + break; + } + + /* string */ + case CONFIG_TYPE_STRING: + { + char *p; + + fputc('\"', stream); + + if(value->sval) + { + for(p = value->sval; *p; p++) + { + int c = (int)*p & 0xFF; + switch(c) + { + case '\"': + case '\\': + fputc('\\', stream); + fputc(c, stream); + break; + + case '\n': + fputs("\\n", stream); + break; + + case '\r': + fputs("\\r", stream); + break; + + case '\f': + fputs("\\f", stream); + break; + + case '\t': + fputs("\\t", stream); + break; + + default: + if(c >= ' ') + fputc(c, stream); + else + fprintf(stream, "\\x%02X", c); + } + } + } + fputc('\"', stream); + break; + } + + /* list */ + case CONFIG_TYPE_LIST: + { + config_list_t *list = value->list; + + fprintf(stream, "( "); + + if(list) + { + int len = list->length; + config_setting_t **s; + + for(s = list->elements; len--; s++) + { + __config_write_value(&((*s)->value), (*s)->type, + config_setting_get_format(*s), + depth + 1, tab_width, stream); + + if(len) + fputc(',', stream); + + fputc(' ', stream); + } + } + + fputc(')', stream); + break; + } + + /* array */ + case CONFIG_TYPE_ARRAY: + { + config_list_t *list = value->list; + + fprintf(stream, "[ "); + + if(list) + { + int len = list->length; + config_setting_t **s; + + for(s = list->elements; len--; s++) + { + __config_write_value(&((*s)->value), (*s)->type, + config_setting_get_format(*s), + depth + 1, tab_width, stream); + + if(len) + fputc(',', stream); + + fputc(' ', stream); + } + } + + fputc(']', stream); + break; + } + + /* group */ + case CONFIG_TYPE_GROUP: + { + config_list_t *list = value->list; + + if(depth > 0) + { +#ifdef K_AND_R_STYLE /* Horrendous, but many people like it. */ + fputc(' ', stream); +#else + fputc('\n', stream); + + if(depth > 1) + __config_indent(stream, depth, tab_width); +#endif + fprintf(stream, "{\n"); + } + + if(list) + { + int len = list->length; + config_setting_t **s; + + for(s = list->elements; len--; s++) + __config_write_setting(*s, stream, depth + 1, tab_width); + } + + if(depth > 1) + __config_indent(stream, depth, tab_width); + + if(depth > 0) + fputc('}', stream); + + break; + } + + default: + /* this shouldn't happen, but handle it gracefully... */ + fputs("???", stream); + break; + } +} + +/* ------------------------------------------------------------------------- */ + +static void __config_list_add(config_list_t *list, config_setting_t *setting) +{ + if((list->length % CHUNK_SIZE) == 0) + { + list->elements = (config_setting_t **)realloc( + list->elements, + (list->length + CHUNK_SIZE) * sizeof(config_setting_t *)); + } + + list->elements[list->length] = setting; + list->length++; +} + +/* ------------------------------------------------------------------------- */ + +static config_setting_t *__config_list_search(config_list_t *list, + const char *name, + unsigned int *idx) +{ + config_setting_t **found = NULL; + unsigned int i; + + if(! list) + return(NULL); + + for(i = 0, found = list->elements; i < list->length; i++, found++) + { + if(! (*found)->name) + continue; + + if(! __config_name_compare(name, (*found)->name)) + { + if(idx) + *idx = i; + + return(*found); + } + } + + return(NULL); +} + +/* ------------------------------------------------------------------------- */ + +static config_setting_t *__config_list_remove(config_list_t *list, int idx) +{ + config_setting_t *removed = *(list->elements + idx); + int offset = (idx * sizeof(config_setting_t *)); + int len = list->length - 1 - idx; + char *base = (char *)list->elements + offset; + + memmove(base, base + sizeof(config_setting_t *), + len * sizeof(config_setting_t *)); + + list->length--; + + /* possibly realloc smaller? */ + + return(removed); +} + +/* ------------------------------------------------------------------------- */ + +static void __config_setting_destroy(config_setting_t *setting) +{ + if(setting) + { + if(setting->name) + _delete(setting->name); + + if(setting->type == CONFIG_TYPE_STRING) + _delete(setting->value.sval); + + else if((setting->type == CONFIG_TYPE_GROUP) + || (setting->type == CONFIG_TYPE_ARRAY) + || (setting->type == CONFIG_TYPE_LIST)) + { + if(setting->value.list) + __config_list_destroy(setting->value.list); + } + + if(setting->hook && setting->config->destructor) + setting->config->destructor(setting->hook); + + _delete(setting); + } +} + +/* ------------------------------------------------------------------------- */ + +static void __config_list_destroy(config_list_t *list) +{ + config_setting_t **p; + unsigned int i; + + if(! list) + return; + + if(list->elements) + { + for(p = list->elements, i = 0; i < list->length; p++, i++) + __config_setting_destroy(*p); + + _delete(list->elements); + } + + _delete(list); +} + +/* ------------------------------------------------------------------------- */ + +static int __config_vector_checktype(const config_setting_t *vector, int type) +{ + /* if the array is empty, then it has no type yet */ + + if(! vector->value.list) + return(CONFIG_TRUE); + + if(vector->value.list->length == 0) + return(CONFIG_TRUE); + + /* if it's a list, any type is allowed */ + + if(vector->type == CONFIG_TYPE_LIST) + return(CONFIG_TRUE); + + /* otherwise the first element added determines the type of the array */ + + return((vector->value.list->elements[0]->type == type) + ? CONFIG_TRUE : CONFIG_FALSE); +} + +/* ------------------------------------------------------------------------- */ + +static int __config_validate_name(const char *name) +{ + const char *p = name; + + if(*p == '\0') + return(CONFIG_FALSE); + + if(! isalpha(*p) && (*p != '*')) + return(CONFIG_FALSE); + + for(++p; *p; ++p) + { + if(! (isalpha(*p) || isdigit(*p) || strchr("*_-", (int)*p))) + return(CONFIG_FALSE); + } + + return(CONFIG_TRUE); +} + +/* ------------------------------------------------------------------------- */ + +static int __config_read(config_t *config, FILE *stream, const char *filename, + const char *str) +{ + yyscan_t scanner; + struct scan_context scan_ctx; + struct parse_context parse_ctx; + YY_BUFFER_STATE buffer = NULL; + int r; + + /* Reinitialize the config */ + void (*destructor)(void *) = config->destructor; + const char *include_dir = config->include_dir; + unsigned short tab_width = config->tab_width; + unsigned short flags = config->flags; + + config->include_dir = NULL; + config_destroy(config); + config_init(config); + + config->destructor = destructor; + config->include_dir = include_dir; + config->tab_width = tab_width; + config->flags = flags; + + parsectx_init(&parse_ctx); + parse_ctx.config = config; + parse_ctx.parent = config->root; + parse_ctx.setting = config->root; + + __config_locale_override(); + + scanctx_init(&scan_ctx, filename); + scan_ctx.config = config; + libconfig_yylex_init_extra(&scan_ctx, &scanner); + + if(stream) + libconfig_yyrestart(stream, scanner); + else /* read from string */ + buffer = libconfig_yy_scan_string(str, scanner); + + libconfig_yyset_lineno(1, scanner); + r = libconfig_yyparse(scanner, &parse_ctx, &scan_ctx); + + if(r != 0) + { + YY_BUFFER_STATE buf; + + config->error_file = scanctx_current_filename(&scan_ctx); + config->error_type = CONFIG_ERR_PARSE; + + /* Unwind the include stack, freeing the buffers and closing the files. */ + while((buf = (YY_BUFFER_STATE)scanctx_pop_include(&scan_ctx)) != NULL) + libconfig_yy_delete_buffer(buf, scanner); + } + + libconfig_yylex_destroy(scanner); + config->filenames = scanctx_cleanup(&scan_ctx, &(config->num_filenames)); + parsectx_cleanup(&parse_ctx); + + __config_locale_restore(); + + return(r == 0 ? CONFIG_TRUE : CONFIG_FALSE); +} + +/* ------------------------------------------------------------------------- */ + +int config_read(config_t *config, FILE *stream) +{ + return(__config_read(config, stream, NULL, NULL)); +} + +/* ------------------------------------------------------------------------- */ + +int config_read_string(config_t *config, const char *str) +{ + return(__config_read(config, NULL, NULL, str)); +} + +/* ------------------------------------------------------------------------- */ + +static void __config_write_setting(const config_setting_t *setting, + FILE *stream, int depth, + unsigned short tab_width) +{ + if(depth > 1) + __config_indent(stream, depth, tab_width); + + if(setting->name) + { + fputs(setting->name, stream); + fprintf(stream, " %c ", (setting->type == CONFIG_TYPE_GROUP ? ':' : '=')); + } + + __config_write_value(&(setting->value), setting->type, + config_setting_get_format(setting), + depth, tab_width, stream); + + if(depth > 0) + { + fputc(';', stream); + fputc('\n', stream); + } +} + +/* ------------------------------------------------------------------------- */ + +void config_write(const config_t *config, FILE *stream) +{ + __config_locale_override(); + + __config_write_setting(config->root, stream, 0, config->tab_width); + + __config_locale_restore(); +} + +/* ------------------------------------------------------------------------- */ + +int config_read_file(config_t *config, const char *filename) +{ + int ret; + FILE *stream = fopen(filename, "rt"); + if(! stream) + { + config->error_text = __io_error; + config->error_type = CONFIG_ERR_FILE_IO; + return(CONFIG_FALSE); + } + + ret = __config_read(config, stream, filename, NULL); + fclose(stream); + + return(ret); +} + +/* ------------------------------------------------------------------------- */ + +int config_write_file(config_t *config, const char *filename) +{ + FILE *f = fopen(filename, "wt"); + if(! f) + { + config->error_text = __io_error; + config->error_type = CONFIG_ERR_FILE_IO; + return(CONFIG_FALSE); + } + + config_write(config, f); + fclose(f); + config->error_type = CONFIG_ERR_NONE; + return(CONFIG_TRUE); +} + +/* ------------------------------------------------------------------------- */ + +void config_destroy(config_t *config) +{ + unsigned int count = config->num_filenames; + const char **f; + + __config_setting_destroy(config->root); + + for(f = config->filenames; count > 0; ++f, --count) + _delete(*f); + + _delete(config->filenames); + _delete(config->include_dir); + + memset((void *)config, 0, sizeof(config_t)); +} + +/* ------------------------------------------------------------------------- */ + +void config_init(config_t *config) +{ + memset((void *)config, 0, sizeof(config_t)); + + config->root = _new(config_setting_t); + config->root->type = CONFIG_TYPE_GROUP; + config->root->config = config; + config->tab_width = 2; +} + +/* ------------------------------------------------------------------------- */ + +void config_set_auto_convert(config_t *config, int flag) +{ + if(flag) + config->flags |= CONFIG_OPTION_AUTOCONVERT; + else + config->flags &= ~CONFIG_OPTION_AUTOCONVERT; +} + +/* ------------------------------------------------------------------------- */ + +int config_get_auto_convert(const config_t *config) +{ + return((config->flags & CONFIG_OPTION_AUTOCONVERT) != 0); +} + +/* ------------------------------------------------------------------------- */ + +static config_setting_t *config_setting_create(config_setting_t *parent, + const char *name, int type) +{ + config_setting_t *setting; + config_list_t *list; + + if((parent->type != CONFIG_TYPE_GROUP) + && (parent->type != CONFIG_TYPE_ARRAY) + && (parent->type != CONFIG_TYPE_LIST)) + return(NULL); + + setting = _new(config_setting_t); + setting->parent = parent; + setting->name = (name == NULL) ? NULL : strdup(name); + setting->type = type; + setting->config = parent->config; + setting->hook = NULL; + setting->line = 0; + + list = parent->value.list; + + if(! list) + list = parent->value.list = _new(config_list_t); + + __config_list_add(list, setting); + + return(setting); +} + +/* ------------------------------------------------------------------------- */ + +static int __config_setting_get_int(const config_setting_t *setting, + int *value) +{ + switch(setting->type) + { + case CONFIG_TYPE_INT: + *value = setting->value.ival; + return(CONFIG_TRUE); + + case CONFIG_TYPE_INT64: + if((setting->value.llval > INT32_MAX) + || (setting->value.llval < INT32_MIN)) + *value = 0; + else + *value = (int)(setting->value.llval); + return(CONFIG_TRUE); + + case CONFIG_TYPE_FLOAT: + if((setting->config->flags & CONFIG_OPTION_AUTOCONVERT) != 0) + { + *value = (int)(setting->value.fval); + return(CONFIG_TRUE); + } + else + { /* fall through */ } + + default: + return(CONFIG_FALSE); + } +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_get_int(const config_setting_t *setting) +{ + int value = 0; + __config_setting_get_int(setting, &value); + return(value); +} + +/* ------------------------------------------------------------------------- */ + +static int __config_setting_get_int64(const config_setting_t *setting, + long long *value) +{ + switch(setting->type) + { + case CONFIG_TYPE_INT64: + *value = setting->value.llval; + return(CONFIG_TRUE); + + case CONFIG_TYPE_INT: + *value = (long long)(setting->value.ival); + return(CONFIG_TRUE); + + case CONFIG_TYPE_FLOAT: + if((setting->config->flags & CONFIG_OPTION_AUTOCONVERT) != 0) + { + *value = (long long)(setting->value.fval); + return(CONFIG_TRUE); + } + else + { /* fall through */ } + + default: + return(CONFIG_FALSE); + } +} + +/* ------------------------------------------------------------------------- */ + +long long config_setting_get_int64(const config_setting_t *setting) +{ + long long value = 0; + __config_setting_get_int64(setting, &value); + return(value); +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_lookup_int(const config_setting_t *setting, + const char *name, int *value) +{ + config_setting_t *member = config_setting_get_member(setting, name); + if(! member) + return(CONFIG_FALSE); + + return(__config_setting_get_int(member, value)); +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_lookup_int64(const config_setting_t *setting, + const char *name, long long *value) +{ + config_setting_t *member = config_setting_get_member(setting, name); + if(! member) + return(CONFIG_FALSE); + + return(__config_setting_get_int64(member, value)); +} + +/* ------------------------------------------------------------------------- */ + +static int __config_setting_get_float(const config_setting_t *setting, + double *value) +{ + switch(setting->type) + { + case CONFIG_TYPE_FLOAT: + *value = setting->value.fval; + return(CONFIG_TRUE); + + case CONFIG_TYPE_INT: + if(config_get_auto_convert(setting->config)) + { + *value = (double)(setting->value.ival); + return(CONFIG_TRUE); + } + else + return(CONFIG_FALSE); + + case CONFIG_TYPE_INT64: + if(config_get_auto_convert(setting->config)) + { + *value = (double)(setting->value.llval); + return(CONFIG_TRUE); + } + else + { /* fall through */ } + + default: + return(CONFIG_FALSE); + } +} + +/* ------------------------------------------------------------------------- */ + +double config_setting_get_float(const config_setting_t *setting) +{ + double value = 0.0; + __config_setting_get_float(setting, &value); + return(value); +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_lookup_float(const config_setting_t *setting, + const char *name, double *value) +{ + config_setting_t *member = config_setting_get_member(setting, name); + if(! member) + return(CONFIG_FALSE); + + return(__config_setting_get_float(member, value)); +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_lookup_string(const config_setting_t *setting, + const char *name, const char **value) +{ + config_setting_t *member = config_setting_get_member(setting, name); + if(! member) + return(CONFIG_FALSE); + + if(config_setting_type(member) != CONFIG_TYPE_STRING) + return(CONFIG_FALSE); + + *value = config_setting_get_string(member); + return(CONFIG_TRUE); +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_lookup_bool(const config_setting_t *setting, + const char *name, int *value) +{ + config_setting_t *member = config_setting_get_member(setting, name); + if(! member) + return(CONFIG_FALSE); + + if(config_setting_type(member) != CONFIG_TYPE_BOOL) + return(CONFIG_FALSE); + + *value = config_setting_get_bool(member); + return(CONFIG_TRUE); +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_set_int(config_setting_t *setting, int value) +{ + switch(setting->type) + { + case CONFIG_TYPE_NONE: + setting->type = CONFIG_TYPE_INT; + /* fall through */ + + case CONFIG_TYPE_INT: + setting->value.ival = value; + return(CONFIG_TRUE); + + case CONFIG_TYPE_FLOAT: + if(config_get_auto_convert(setting->config)) + { + setting->value.fval = (float)value; + return(CONFIG_TRUE); + } + else + return(CONFIG_FALSE); + + default: + return(CONFIG_FALSE); + } +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_set_int64(config_setting_t *setting, long long value) +{ + switch(setting->type) + { + case CONFIG_TYPE_NONE: + setting->type = CONFIG_TYPE_INT64; + /* fall through */ + + case CONFIG_TYPE_INT64: + setting->value.llval = value; + return(CONFIG_TRUE); + + case CONFIG_TYPE_INT: + if((value > INT32_MAX) || (value < INT32_MIN)) + setting->value.ival = 0; + else + setting->value.ival = (int)value; + return(CONFIG_TRUE); + + case CONFIG_TYPE_FLOAT: + if(config_get_auto_convert(setting->config)) + { + setting->value.fval = (float)value; + return(CONFIG_TRUE); + } + else + return(CONFIG_FALSE); + + default: + return(CONFIG_FALSE); + } +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_set_float(config_setting_t *setting, double value) +{ + switch(setting->type) + { + case CONFIG_TYPE_NONE: + setting->type = CONFIG_TYPE_FLOAT; + /* fall through */ + + case CONFIG_TYPE_FLOAT: + setting->value.fval = value; + return(CONFIG_TRUE); + + case CONFIG_TYPE_INT: + if((setting->config->flags & CONFIG_OPTION_AUTOCONVERT) != 0) + { + setting->value.ival = (int)value; + return(CONFIG_TRUE); + } + else + return(CONFIG_FALSE); + + case CONFIG_TYPE_INT64: + if((setting->config->flags & CONFIG_OPTION_AUTOCONVERT) != 0) + { + setting->value.llval = (long long)value; + return(CONFIG_TRUE); + } + else + return(CONFIG_FALSE); + + default: + return(CONFIG_FALSE); + } +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_get_bool(const config_setting_t *setting) +{ + return((setting->type == CONFIG_TYPE_BOOL) ? setting->value.ival : 0); +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_set_bool(config_setting_t *setting, int value) +{ + if(setting->type == CONFIG_TYPE_NONE) + setting->type = CONFIG_TYPE_BOOL; + else if(setting->type != CONFIG_TYPE_BOOL) + return(CONFIG_FALSE); + + setting->value.ival = value; + return(CONFIG_TRUE); +} + +/* ------------------------------------------------------------------------- */ + +const char *config_setting_get_string(const config_setting_t *setting) +{ + return((setting->type == CONFIG_TYPE_STRING) ? setting->value.sval : NULL); +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_set_string(config_setting_t *setting, const char *value) +{ + if(setting->type == CONFIG_TYPE_NONE) + setting->type = CONFIG_TYPE_STRING; + else if(setting->type != CONFIG_TYPE_STRING) + return(CONFIG_FALSE); + + if(setting->value.sval) + _delete(setting->value.sval); + + setting->value.sval = (value == NULL) ? NULL : strdup(value); + return(CONFIG_TRUE); +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_set_format(config_setting_t *setting, short format) +{ + if(((setting->type != CONFIG_TYPE_INT) + && (setting->type != CONFIG_TYPE_INT64)) + || ((format != CONFIG_FORMAT_DEFAULT) && (format != CONFIG_FORMAT_HEX))) + return(CONFIG_FALSE); + + setting->format = format; + + return(CONFIG_TRUE); +} + +/* ------------------------------------------------------------------------- */ + +short config_setting_get_format(const config_setting_t *setting) +{ + return(setting->format != 0 ? setting->format + : setting->config->default_format); +} + +/* ------------------------------------------------------------------------- */ + +config_setting_t *config_lookup_from(config_setting_t *setting, + const char *path) +{ + const char *p = path; + config_setting_t *found; + + for(;;) + { + while(*p && strchr(PATH_TOKENS, *p)) + p++; + + if(! *p) + break; + + if(*p == '[') + found = config_setting_get_elem(setting, atoi(++p)); + else + found = config_setting_get_member(setting, p); + + if(! found) + break; + + setting = found; + + while(! strchr(PATH_TOKENS, *p)) + p++; + } + + return(*p ? NULL : setting); +} + +/* ------------------------------------------------------------------------- */ + +config_setting_t *config_lookup(const config_t *config, const char *path) +{ + return(config_lookup_from(config->root, path)); +} + +/* ------------------------------------------------------------------------- */ + +int config_lookup_string(const config_t *config, const char *path, + const char **value) +{ + const config_setting_t *s = config_lookup(config, path); + if(! s) + return(CONFIG_FALSE); + + if(config_setting_type(s) != CONFIG_TYPE_STRING) + return(CONFIG_FALSE); + + *value = config_setting_get_string(s); + + return(CONFIG_TRUE); +} + +/* ------------------------------------------------------------------------- */ + +int config_lookup_int(const config_t *config, const char *path, + int *value) +{ + const config_setting_t *s = config_lookup(config, path); + if(! s) + return(CONFIG_FALSE); + + return(__config_setting_get_int(s, value)); +} + +/* ------------------------------------------------------------------------- */ + +int config_lookup_int64(const config_t *config, const char *path, + long long *value) +{ + const config_setting_t *s = config_lookup(config, path); + if(! s) + return(CONFIG_FALSE); + + return(__config_setting_get_int64(s, value)); +} + +/* ------------------------------------------------------------------------- */ + +int config_lookup_float(const config_t *config, const char *path, + double *value) +{ + const config_setting_t *s = config_lookup(config, path); + if(! s) + return(CONFIG_FALSE); + + return(__config_setting_get_float(s, value)); +} + +/* ------------------------------------------------------------------------- */ + +int config_lookup_bool(const config_t *config, const char *path, int *value) +{ + const config_setting_t *s = config_lookup(config, path); + if(! s) + return(CONFIG_FALSE); + + if(config_setting_type(s) != CONFIG_TYPE_BOOL) + return(CONFIG_FALSE); + + *value = config_setting_get_bool(s); + return(CONFIG_TRUE); +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_get_int_elem(const config_setting_t *vector, int idx) +{ + const config_setting_t *element = config_setting_get_elem(vector, idx); + + return(element ? config_setting_get_int(element) : 0); +} + +/* ------------------------------------------------------------------------- */ + +config_setting_t *config_setting_set_int_elem(config_setting_t *vector, + int idx, int value) +{ + config_setting_t *element = NULL; + + if((vector->type != CONFIG_TYPE_ARRAY) && (vector->type != CONFIG_TYPE_LIST)) + return(NULL); + + if(idx < 0) + { + if(! __config_vector_checktype(vector, CONFIG_TYPE_INT)) + return(NULL); + + element = config_setting_create(vector, NULL, CONFIG_TYPE_INT); + } + else + { + element = config_setting_get_elem(vector, idx); + + if(! element) + return(NULL); + } + + if(! config_setting_set_int(element, value)) + return(NULL); + + return(element); +} + +/* ------------------------------------------------------------------------- */ + +long long config_setting_get_int64_elem(const config_setting_t *vector, + int idx) +{ + const config_setting_t *element = config_setting_get_elem(vector, idx); + + return(element ? config_setting_get_int64(element) : 0); +} + +/* ------------------------------------------------------------------------- */ + +config_setting_t *config_setting_set_int64_elem(config_setting_t *vector, + int idx, long long value) +{ + config_setting_t *element = NULL; + + if((vector->type != CONFIG_TYPE_ARRAY) && (vector->type != CONFIG_TYPE_LIST)) + return(NULL); + + if(idx < 0) + { + if(! __config_vector_checktype(vector, CONFIG_TYPE_INT64)) + return(NULL); + + element = config_setting_create(vector, NULL, CONFIG_TYPE_INT64); + } + else + { + element = config_setting_get_elem(vector, idx); + + if(! element) + return(NULL); + } + + if(! config_setting_set_int64(element, value)) + return(NULL); + + return(element); +} + +/* ------------------------------------------------------------------------- */ + +double config_setting_get_float_elem(const config_setting_t *vector, int idx) +{ + config_setting_t *element = config_setting_get_elem(vector, idx); + + return(element ? config_setting_get_float(element) : 0.0); +} + +/* ------------------------------------------------------------------------- */ + +config_setting_t *config_setting_set_float_elem(config_setting_t *vector, + int idx, double value) +{ + config_setting_t *element = NULL; + + if((vector->type != CONFIG_TYPE_ARRAY) && (vector->type != CONFIG_TYPE_LIST)) + return(NULL); + + if(idx < 0) + { + if(! __config_vector_checktype(vector, CONFIG_TYPE_FLOAT)) + return(NULL); + + element = config_setting_create(vector, NULL, CONFIG_TYPE_FLOAT); + } + else + element = config_setting_get_elem(vector, idx); + + if(! element) + return(NULL); + + if(! config_setting_set_float(element, value)) + return(NULL); + + return(element); +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_get_bool_elem(const config_setting_t *vector, int idx) +{ + config_setting_t *element = config_setting_get_elem(vector, idx); + + if(! element) + return(CONFIG_FALSE); + + if(element->type != CONFIG_TYPE_BOOL) + return(CONFIG_FALSE); + + return(element->value.ival); +} + +/* ------------------------------------------------------------------------- */ + +config_setting_t *config_setting_set_bool_elem(config_setting_t *vector, + int idx, int value) +{ + config_setting_t *element = NULL; + + if((vector->type != CONFIG_TYPE_ARRAY) && (vector->type != CONFIG_TYPE_LIST)) + return(NULL); + + if(idx < 0) + { + if(! __config_vector_checktype(vector, CONFIG_TYPE_BOOL)) + return(NULL); + + element = config_setting_create(vector, NULL, CONFIG_TYPE_BOOL); + } + else + element = config_setting_get_elem(vector, idx); + + if(! element) + return(NULL); + + if(! config_setting_set_bool(element, value)) + return(NULL); + + return(element); +} + +/* ------------------------------------------------------------------------- */ + +const char *config_setting_get_string_elem(const config_setting_t *vector, + int idx) +{ + config_setting_t *element = config_setting_get_elem(vector, idx); + + if(! element) + return(NULL); + + if(element->type != CONFIG_TYPE_STRING) + return(NULL); + + return(element->value.sval); +} + +/* ------------------------------------------------------------------------- */ + +config_setting_t *config_setting_set_string_elem(config_setting_t *vector, + int idx, const char *value) +{ + config_setting_t *element = NULL; + + if((vector->type != CONFIG_TYPE_ARRAY) && (vector->type != CONFIG_TYPE_LIST)) + return(NULL); + + if(idx < 0) + { + if(! __config_vector_checktype(vector, CONFIG_TYPE_STRING)) + return(NULL); + + element = config_setting_create(vector, NULL, CONFIG_TYPE_STRING); + } + else + element = config_setting_get_elem(vector, idx); + + if(! element) + return(NULL); + + if(! config_setting_set_string(element, value)) + return(NULL); + + return(element); +} + +/* ------------------------------------------------------------------------- */ + +config_setting_t *config_setting_get_elem(const config_setting_t *vector, + unsigned int idx) +{ + config_list_t *list = vector->value.list; + + if(((vector->type != CONFIG_TYPE_ARRAY) + && (vector->type != CONFIG_TYPE_LIST) + && (vector->type != CONFIG_TYPE_GROUP)) || ! list) + return(NULL); + + if(idx >= list->length) + return(NULL); + + return(list->elements[idx]); +} + +/* ------------------------------------------------------------------------- */ + +config_setting_t *config_setting_get_member(const config_setting_t *setting, + const char *name) +{ + if(setting->type != CONFIG_TYPE_GROUP) + return(NULL); + + return(__config_list_search(setting->value.list, name, NULL)); +} + +/* ------------------------------------------------------------------------- */ + +void config_set_destructor(config_t *config, void (*destructor)(void *)) +{ + config->destructor = destructor; +} + +/* ------------------------------------------------------------------------- */ + +void config_set_include_dir(config_t *config, const char *include_dir) +{ + _delete(config->include_dir); + config->include_dir = strdup(include_dir); +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_length(const config_setting_t *setting) +{ + if((setting->type != CONFIG_TYPE_GROUP) + && (setting->type != CONFIG_TYPE_ARRAY) + && (setting->type != CONFIG_TYPE_LIST)) + return(0); + + if(! setting->value.list) + return(0); + + return(setting->value.list->length); +} + +/* ------------------------------------------------------------------------- */ + +void config_setting_set_hook(config_setting_t *setting, void *hook) +{ + setting->hook = hook; +} + +/* ------------------------------------------------------------------------- */ + +config_setting_t *config_setting_add(config_setting_t *parent, + const char *name, int type) +{ + if((type < CONFIG_TYPE_NONE) || (type > CONFIG_TYPE_LIST)) + return(NULL); + + if(! parent) + return(NULL); + + if((parent->type == CONFIG_TYPE_ARRAY) || (parent->type == CONFIG_TYPE_LIST)) + name = NULL; + + if(name) + { + if(! __config_validate_name(name)) + return(NULL); + } + + if(config_setting_get_member(parent, name) != NULL) + return(NULL); /* already exists */ + + return(config_setting_create(parent, name, type)); +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_remove(config_setting_t *parent, const char *name) +{ + unsigned int idx; + config_setting_t *setting; + + if(! parent) + return(CONFIG_FALSE); + + if(parent->type != CONFIG_TYPE_GROUP) + return(CONFIG_FALSE); + + if(! (setting = __config_list_search(parent->value.list, name, &idx))) + return(CONFIG_FALSE); + + __config_list_remove(parent->value.list, idx); + __config_setting_destroy(setting); + + return(CONFIG_TRUE); +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_remove_elem(config_setting_t *parent, unsigned int idx) +{ + config_list_t *list; + config_setting_t *removed = NULL; + + if(! parent) + return(CONFIG_FALSE); + + list = parent->value.list; + + if(((parent->type != CONFIG_TYPE_ARRAY) + && (parent->type != CONFIG_TYPE_LIST) + && (parent->type != CONFIG_TYPE_GROUP)) || ! list) + return(CONFIG_FALSE); + + if(idx >= list->length) + return(CONFIG_FALSE); + + removed = __config_list_remove(list, idx); + __config_setting_destroy(removed); + + return(CONFIG_TRUE); +} + +/* ------------------------------------------------------------------------- */ + +int config_setting_index(const config_setting_t *setting) +{ + config_setting_t **found = NULL; + config_list_t *list; + int i; + + if(! setting->parent) + return(-1); + + list = setting->parent->value.list; + + for(i = 0, found = list->elements; i < (int)list->length; ++i, ++found) + { + if(*found == setting) + return(i); + } + + return(-1); +} + +/* ------------------------------------------------------------------------- */ +/* eof */ diff --git a/3rdparty/libconfig/libconfig.h b/3rdparty/libconfig/libconfig.h new file mode 100644 index 000000000..683bda80b --- /dev/null +++ b/3rdparty/libconfig/libconfig.h @@ -0,0 +1,320 @@ +/* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files + Copyright (C) 2005-2010 Mark A Lindner + + This file is part of libconfig. + + This library 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 library 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 library. If not, see <http://www.gnu.org/licenses/>. + ---------------------------------------------------------------------------- +*/ + +#ifndef __libconfig_h +#define __libconfig_h + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +#if defined(LIBCONFIG_STATIC) +#define LIBCONFIG_API +#elif defined(LIBCONFIG_EXPORTS) +#define LIBCONFIG_API __declspec(dllexport) +#else /* ! LIBCONFIG_EXPORTS */ +#define LIBCONFIG_API __declspec(dllimport) +#endif /* LIBCONFIG_STATIC */ +#else /* ! WIN32 */ +#define LIBCONFIG_API +#endif /* WIN32 */ + +#define LIBCONFIG_VER_MAJOR 1 +#define LIBCONFIG_VER_MINOR 4 +#define LIBCONFIG_VER_REVISION 8 + +#include <stdio.h> + +#define CONFIG_TYPE_NONE 0 +#define CONFIG_TYPE_GROUP 1 +#define CONFIG_TYPE_INT 2 +#define CONFIG_TYPE_INT64 3 +#define CONFIG_TYPE_FLOAT 4 +#define CONFIG_TYPE_STRING 5 +#define CONFIG_TYPE_BOOL 6 +#define CONFIG_TYPE_ARRAY 7 +#define CONFIG_TYPE_LIST 8 + +#define CONFIG_FORMAT_DEFAULT 0 +#define CONFIG_FORMAT_HEX 1 + +#define CONFIG_OPTION_AUTOCONVERT 0x01 + +#define CONFIG_TRUE (1) +#define CONFIG_FALSE (0) + +typedef union config_value_t +{ + int ival; + long long llval; + double fval; + char *sval; + struct config_list_t *list; +} config_value_t; + +typedef struct config_setting_t +{ + char *name; + short type; + short format; + config_value_t value; + struct config_setting_t *parent; + struct config_t *config; + void *hook; + unsigned int line; + const char *file; +} config_setting_t; + +typedef enum +{ + CONFIG_ERR_NONE = 0, + CONFIG_ERR_FILE_IO = 1, + CONFIG_ERR_PARSE = 2 +} config_error_t; + +typedef struct config_list_t +{ + unsigned int length; + config_setting_t **elements; +} config_list_t; + +typedef struct config_t +{ + config_setting_t *root; + void (*destructor)(void *); + unsigned short flags; + unsigned short tab_width; + short default_format; + const char *include_dir; + const char *error_text; + const char *error_file; + int error_line; + config_error_t error_type; + const char **filenames; + unsigned int num_filenames; +} config_t; + +extern LIBCONFIG_API int config_read(config_t *config, FILE *stream); +extern LIBCONFIG_API void config_write(const config_t *config, FILE *stream); + +extern LIBCONFIG_API void config_set_default_format(config_t *config, + short format); + +extern LIBCONFIG_API void config_set_auto_convert(config_t *config, int flag); +extern LIBCONFIG_API int config_get_auto_convert(const config_t *config); + +extern LIBCONFIG_API int config_read_string(config_t *config, const char *str); + +extern LIBCONFIG_API int config_read_file(config_t *config, + const char *filename); +extern LIBCONFIG_API int config_write_file(config_t *config, + const char *filename); + +extern LIBCONFIG_API void config_set_destructor(config_t *config, + void (*destructor)(void *)); +extern LIBCONFIG_API void config_set_include_dir(config_t *config, + const char *include_dir); + +extern LIBCONFIG_API void config_init(config_t *config); +extern LIBCONFIG_API void config_destroy(config_t *config); + +extern LIBCONFIG_API int config_setting_get_int( + const config_setting_t *setting); +extern LIBCONFIG_API long long config_setting_get_int64( + const config_setting_t *setting); +extern LIBCONFIG_API double config_setting_get_float( + const config_setting_t *setting); +extern LIBCONFIG_API int config_setting_get_bool( + const config_setting_t *setting); +extern LIBCONFIG_API const char *config_setting_get_string( + const config_setting_t *setting); + +extern LIBCONFIG_API int config_setting_lookup_int( + const config_setting_t *setting, const char *name, int *value); +extern LIBCONFIG_API int config_setting_lookup_int64( + const config_setting_t *setting, const char *name, long long *value); +extern LIBCONFIG_API int config_setting_lookup_float( + const config_setting_t *setting, const char *name, double *value); +extern LIBCONFIG_API int config_setting_lookup_bool( + const config_setting_t *setting, const char *name, int *value); +extern LIBCONFIG_API int config_setting_lookup_string( + const config_setting_t *setting, const char *name, const char **value); + +extern LIBCONFIG_API int config_setting_set_int(config_setting_t *setting, + int value); +extern LIBCONFIG_API int config_setting_set_int64(config_setting_t *setting, + long long value); +extern LIBCONFIG_API int config_setting_set_float(config_setting_t *setting, + double value); +extern LIBCONFIG_API int config_setting_set_bool(config_setting_t *setting, + int value); +extern LIBCONFIG_API int config_setting_set_string(config_setting_t *setting, + const char *value); + +extern LIBCONFIG_API int config_setting_set_format(config_setting_t *setting, + short format); +extern LIBCONFIG_API short config_setting_get_format( + const config_setting_t *setting); + +extern LIBCONFIG_API int config_setting_get_int_elem( + const config_setting_t *setting, int idx); +extern LIBCONFIG_API long long config_setting_get_int64_elem( + const config_setting_t *setting, int idx); +extern LIBCONFIG_API double config_setting_get_float_elem( + const config_setting_t *setting, int idx); +extern LIBCONFIG_API int config_setting_get_bool_elem( + const config_setting_t *setting, int idx); +extern LIBCONFIG_API const char *config_setting_get_string_elem( + const config_setting_t *setting, int idx); + +extern LIBCONFIG_API config_setting_t *config_setting_set_int_elem( + config_setting_t *setting, int idx, int value); +extern LIBCONFIG_API config_setting_t *config_setting_set_int64_elem( + config_setting_t *setting, int idx, long long value); +extern LIBCONFIG_API config_setting_t *config_setting_set_float_elem( + config_setting_t *setting, int idx, double value); +extern LIBCONFIG_API config_setting_t *config_setting_set_bool_elem( + config_setting_t *setting, int idx, int value); +extern LIBCONFIG_API config_setting_t *config_setting_set_string_elem( + config_setting_t *setting, int idx, const char *value); + +#define /* const char * */ config_get_include_dir(/* const config_t * */ C) \ + ((C)->include_dir) + +#define /* int */ config_setting_type(/* const config_setting_t * */ S) \ + ((S)->type) + +#define /* int */ config_setting_is_group(/* const config_setting_t * */ S) \ + ((S)->type == CONFIG_TYPE_GROUP) +#define /* int */ config_setting_is_array(/* const config_setting_t * */ S) \ + ((S)->type == CONFIG_TYPE_ARRAY) +#define /* int */ config_setting_is_list(/* const config_setting_t * */ S) \ + ((S)->type == CONFIG_TYPE_LIST) + +#define /* int */ config_setting_is_aggregate( \ + /* const config_setting_t * */ S) \ + (((S)->type == CONFIG_TYPE_GROUP) || ((S)->type == CONFIG_TYPE_LIST) \ + || ((S)->type == CONFIG_TYPE_ARRAY)) + +#define /* int */ config_setting_is_number(/* const config_setting_t * */ S) \ + (((S)->type == CONFIG_TYPE_INT) \ + || ((S)->type == CONFIG_TYPE_INT64) \ + || ((S)->type == CONFIG_TYPE_FLOAT)) + +#define /* int */ config_setting_is_scalar(/* const config_setting_t * */ S) \ + (((S)->type == CONFIG_TYPE_BOOL) || ((S)->type == CONFIG_TYPE_STRING) \ + || config_setting_is_number(S)) + +#define /* const char * */ config_setting_name( \ + /* const config_setting_t * */ S) \ + ((S)->name) + +#define /* config_setting_t * */ config_setting_parent( \ + /* const config_setting_t * */ S) \ + ((S)->parent) + +#define /* int */ config_setting_is_root( \ + /* const config_setting_t * */ S) \ + ((S)->parent ? CONFIG_FALSE : CONFIG_TRUE) + +extern LIBCONFIG_API int config_setting_index(const config_setting_t *setting); + +extern LIBCONFIG_API int config_setting_length( + const config_setting_t *setting); +extern LIBCONFIG_API config_setting_t *config_setting_get_elem( + const config_setting_t *setting, unsigned int idx); + +extern LIBCONFIG_API config_setting_t *config_setting_get_member( + const config_setting_t *setting, const char *name); + +extern LIBCONFIG_API config_setting_t *config_setting_add( + config_setting_t *parent, const char *name, int type); +extern LIBCONFIG_API int config_setting_remove(config_setting_t *parent, + const char *name); +extern LIBCONFIG_API int config_setting_remove_elem(config_setting_t *parent, + unsigned int idx); +extern LIBCONFIG_API void config_setting_set_hook(config_setting_t *setting, + void *hook); + +#define config_setting_get_hook(S) ((S)->hook) + +extern LIBCONFIG_API config_setting_t *config_lookup(const config_t *config, + const char *path); +extern LIBCONFIG_API config_setting_t *config_lookup_from( + config_setting_t *setting, const char *path); + +extern LIBCONFIG_API int config_lookup_int(const config_t *config, + const char *path, int *value); +extern LIBCONFIG_API int config_lookup_int64(const config_t *config, + const char *path, + long long *value); +extern LIBCONFIG_API int config_lookup_float(const config_t *config, + const char *path, double *value); +extern LIBCONFIG_API int config_lookup_bool(const config_t *config, + const char *path, int *value); +extern LIBCONFIG_API int config_lookup_string(const config_t *config, + const char *path, + const char **value); + +#define /* config_setting_t * */ config_root_setting( \ + /* const config_t * */ C) \ + ((C)->root) + +#define /* void */ config_set_default_format(/* config_t * */ C, \ + /* short */ F) \ + (C)->default_format = (F) + +#define /* short */ config_get_default_format(/* config_t * */ C) \ + ((C)->default_format) + +#define /* void */ config_set_tab_width(/* config_t * */ C, \ + /* unsigned short */ W) \ + (C)->tab_width = ((W) & 0x0F) + +#define /* unsigned char */ config_get_tab_width(/* const config_t * */ C) \ + ((C)->tab_width) + +#define /* unsigned short */ config_setting_source_line( \ + /* const config_setting_t * */ S) \ + ((S)->line) + +#define /* const char */ config_setting_source_file( \ + /* const config_setting_t * */ S) \ + ((S)->file) + +#define /* const char * */ config_error_text(/* const config_t * */ C) \ + ((C)->error_text) + +#define /* const char * */ config_error_file(/* const config_t * */ C) \ + ((C)->error_file) + +#define /* int */ config_error_line(/* const config_t * */ C) \ + ((C)->error_line) + +#define /* config_error_t */ config_error_type(/* const config_t * */ C) \ + ((C)->error_type) + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __libconfig_h */ diff --git a/3rdparty/libconfig/parsectx.h b/3rdparty/libconfig/parsectx.h new file mode 100644 index 000000000..0beb1111c --- /dev/null +++ b/3rdparty/libconfig/parsectx.h @@ -0,0 +1,47 @@ +/* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files + Copyright (C) 2005-2010 Mark A Lindner + + This file is part of libconfig. + + This library 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 library 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 library. If not, see <http://www.gnu.org/licenses/>. + ---------------------------------------------------------------------------- +*/ + +#ifndef __libconfig_parsectx_h +#define __libconfig_parsectx_h + +#include "libconfig.h" +#include "strbuf.h" + +struct parse_context +{ + config_t *config; + config_setting_t *parent; + config_setting_t *setting; + char *name; + strbuf_t string; +}; + +#define parsectx_init(C) \ + memset((C), 0, sizeof(struct parse_context)) +#define parsectx_cleanup(C) \ + free((void *)(strbuf_release(&((C)->string)))) + +#define parsectx_append_string(C, S) \ + strbuf_append(&((C)->string), (S)) +#define parsectx_take_string(C) \ + strbuf_release(&((C)->string)) + +#endif /* __libconfig_parsectx_h */ diff --git a/3rdparty/libconfig/scanctx.c b/3rdparty/libconfig/scanctx.c new file mode 100644 index 000000000..7d7f4994c --- /dev/null +++ b/3rdparty/libconfig/scanctx.c @@ -0,0 +1,170 @@ +/* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files + Copyright (C) 2005-2010 Mark A Lindner + + This file is part of libconfig. + + This library 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 library 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 library. If not, see <http://www.gnu.org/licenses/>. + ---------------------------------------------------------------------------- +*/ + +#include "scanctx.h" +#include "wincompat.h" + +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +#define STRING_BLOCK_SIZE 64 +#define CHUNK_SIZE 32 + +/* ------------------------------------------------------------------------- */ + +static const char *err_bad_include = "cannot open include file"; +static const char *err_include_too_deep = "include file nesting too deep"; + +/* ------------------------------------------------------------------------- */ + +static const char *__scanctx_add_filename(struct scan_context *ctx, + const char *filename) +{ + unsigned int count = ctx->num_filenames; + const char **f; + + for(f = ctx->filenames; count > 0; ++f, --count) + { + if(!strcmp(*f, filename)) + { + free((void *)filename); + return(*f); /* already in list */ + } + } + + if((ctx->num_filenames % CHUNK_SIZE) == 0) + { + ctx->filenames = (const char **)realloc( + (void *)ctx->filenames, + (ctx->num_filenames + CHUNK_SIZE) * sizeof(const char *)); + } + + ctx->filenames[ctx->num_filenames] = filename; + ++ctx->num_filenames; + return(filename); +} + +/* ------------------------------------------------------------------------- */ + +void scanctx_init(struct scan_context *ctx, const char *top_filename) +{ + memset(ctx, 0, sizeof(struct scan_context)); + if(top_filename) + ctx->top_filename = __scanctx_add_filename(ctx, strdup(top_filename)); +} + +/* ------------------------------------------------------------------------- */ + +const char **scanctx_cleanup(struct scan_context *ctx, + unsigned int *num_filenames) +{ + int i; + + for(i = 0; i < ctx->depth; ++i) + fclose(ctx->streams[i]); + + free((void *)(strbuf_release(&(ctx->string)))); + + *num_filenames = ctx->num_filenames; + return(ctx->filenames); +} + +/* ------------------------------------------------------------------------- */ + +FILE *scanctx_push_include(struct scan_context *ctx, void *buffer, + const char **error) +{ + FILE *fp = NULL; + const char *file; + char *full_file = NULL; + + *error = NULL; + + if(ctx->depth == MAX_INCLUDE_DEPTH) + { + *error = err_include_too_deep; + return(NULL); + } + + file = scanctx_take_string(ctx); + if(ctx->config->include_dir) + { + full_file = (char *)malloc(strlen(ctx->config->include_dir) + strlen(file) + + 2); + strcpy(full_file, ctx->config->include_dir); + strcat(full_file, FILE_SEPARATOR); + strcat(full_file, file); + } + + fp = fopen(full_file ? full_file : file, "rt"); + free((void *)full_file); + + if(fp) + { + ctx->streams[ctx->depth] = fp; + ctx->files[ctx->depth] = __scanctx_add_filename(ctx, file); + ctx->buffers[ctx->depth] = buffer; + ++(ctx->depth); + } + else + { + free((void *)file); + *error = err_bad_include; + } + + return(fp); +} + +/* ------------------------------------------------------------------------- */ + +void *scanctx_pop_include(struct scan_context *ctx) +{ + void *buffer; + + if(ctx->depth == 0) + return(NULL); /* stack underflow */ + + --(ctx->depth); + buffer = ctx->buffers[ctx->depth]; + fclose(ctx->streams[ctx->depth]); + + return(buffer); +} + +/* ------------------------------------------------------------------------- */ + +char *scanctx_take_string(struct scan_context *ctx) +{ + char *r = strbuf_release(&(ctx->string)); + + return(r ? r : strdup("")); +} + +/* ------------------------------------------------------------------------- */ + +const char *scanctx_current_filename(struct scan_context *ctx) +{ + return((ctx->depth == 0) ? ctx->top_filename : ctx->files[ctx->depth - 1]); +} + +/* ------------------------------------------------------------------------- */ +/* eof */ diff --git a/3rdparty/libconfig/scanctx.h b/3rdparty/libconfig/scanctx.h new file mode 100644 index 000000000..b8cc11e3d --- /dev/null +++ b/3rdparty/libconfig/scanctx.h @@ -0,0 +1,61 @@ +/* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files + Copyright (C) 2005-2010 Mark A Lindner + + This file is part of libconfig. + + This library 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 library 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 library. If not, see <http://www.gnu.org/licenses/>. + ---------------------------------------------------------------------------- +*/ + +#ifndef __libconfig_scanctx_h +#define __libconfig_scanctx_h + +#include "libconfig.h" +#include "strbuf.h" + +#include <stdio.h> +#include <sys/types.h> + +#define MAX_INCLUDE_DEPTH 10 + +struct scan_context +{ + config_t *config; + const char *top_filename; + const char *files[MAX_INCLUDE_DEPTH]; + void *buffers[MAX_INCLUDE_DEPTH]; + FILE *streams[MAX_INCLUDE_DEPTH]; + int depth; + strbuf_t string; + const char **filenames; + unsigned int num_filenames; +}; + +extern void scanctx_init(struct scan_context *ctx, const char *top_filename); +extern const char **scanctx_cleanup(struct scan_context *ctx, + unsigned int *num_filenames); + +extern FILE *scanctx_push_include(struct scan_context *ctx, void *prev_buffer, + const char **error); +extern void *scanctx_pop_include(struct scan_context *ctx); + +#define scanctx_append_string(C, S) \ + strbuf_append(&((C)->string), (S)) + +extern char *scanctx_take_string(struct scan_context *ctx); + +extern const char *scanctx_current_filename(struct scan_context *ctx); + +#endif /* __libconfig_scanctx_h */ diff --git a/3rdparty/libconfig/scanner.c b/3rdparty/libconfig/scanner.c new file mode 100644 index 000000000..c2eb7d188 --- /dev/null +++ b/3rdparty/libconfig/scanner.c @@ -0,0 +1,2362 @@ +#line 2 "scanner.c" + +#line 4 "scanner.c" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 35 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */ + +#if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include <inttypes.h> +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! C99 */ + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +/* C99 requires __STDC__ to be defined as 1. */ +#if defined (__STDC__) + +#define YY_USE_CONST + +#endif /* defined (__STDC__) */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* An opaque pointer. */ +#ifndef YY_TYPEDEF_YY_SCANNER_T +#define YY_TYPEDEF_YY_SCANNER_T +typedef void* yyscan_t; +#endif + +/* For convenience, these vars (plus the bison vars far below) + are macros in the reentrant scanner. */ +#define yyin yyg->yyin_r +#define yyout yyg->yyout_r +#define yyextra yyg->yyextra_r +#define yyleng yyg->yyleng_r +#define yytext yyg->yytext_r +#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) +#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) +#define yy_flex_debug yyg->yy_flex_debug_r + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yyg->yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yyg->yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE libconfig_yyrestart(yyin ,yyscanner ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#ifndef YY_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k. + * Moreover, YY_BUF_SIZE is 2*YY_READ_BUF_SIZE in the general case. + * Ditto for the __ia64__ case accordingly. + */ +#define YY_BUF_SIZE 32768 +#else +#define YY_BUF_SIZE 16384 +#endif /* __ia64__ */ +#endif + +/* The state buf must be large enough to hold one state per character in the main buffer. + */ +#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type)) + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + + /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires + * access to the local variable yy_act. Since yyless() is a macro, it would break + * existing scanners that call yyless() from OUTSIDE libconfig_yylex. + * One obvious solution it to make yy_act a global. I tried that, and saw + * a 5% performance hit in a non-yylineno scanner, because yy_act is + * normally declared as a register variable-- so it is not worth it. + */ + #define YY_LESS_LINENO(n) \ + do { \ + int yyl;\ + for ( yyl = n; yyl < yyleng; ++yyl )\ + if ( yytext[yyl] == '\n' )\ + --yylineno;\ + }while(0) + +/* Return all but the first "n" matched characters back to the input stream. */ +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + *yy_cp = yyg->yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner ) + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef size_t yy_size_t; +#endif + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via libconfig_yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + * + * Returns the top of the stack, or NULL. + */ +#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \ + ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \ + : NULL) + +/* Same as previous macro, but useful when we know that the buffer stack is not + * NULL or when we need an lvalue. For internal use only. + */ +#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] + +void libconfig_yyrestart (FILE *input_file ,yyscan_t yyscanner ); +void libconfig_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); +YY_BUFFER_STATE libconfig_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner ); +void libconfig_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); +void libconfig_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); +void libconfig_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); +void libconfig_yypop_buffer_state (yyscan_t yyscanner ); + +static void libconfig_yyensure_buffer_stack (yyscan_t yyscanner ); +static void libconfig_yy_load_buffer_state (yyscan_t yyscanner ); +static void libconfig_yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner ); + +#define YY_FLUSH_BUFFER libconfig_yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner) + +YY_BUFFER_STATE libconfig_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner ); +YY_BUFFER_STATE libconfig_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner ); +YY_BUFFER_STATE libconfig_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner ); + +void *libconfig_yyalloc (yy_size_t ,yyscan_t yyscanner ); +void *libconfig_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner ); +void libconfig_yyfree (void * ,yyscan_t yyscanner ); + +#define yy_new_buffer libconfig_yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! YY_CURRENT_BUFFER ){ \ + libconfig_yyensure_buffer_stack (yyscanner); \ + YY_CURRENT_BUFFER_LVALUE = \ + libconfig_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! YY_CURRENT_BUFFER ){\ + libconfig_yyensure_buffer_stack (yyscanner); \ + YY_CURRENT_BUFFER_LVALUE = \ + libconfig_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \ + } \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol) + +#define libconfig_yywrap(n) 1 +#define YY_SKIP_YYWRAP + +typedef unsigned char YY_CHAR; + +typedef int yy_state_type; + +#define yytext_ptr yytext_r + +static yy_state_type yy_get_previous_state (yyscan_t yyscanner ); +static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner); +static int yy_get_next_buffer (yyscan_t yyscanner ); +static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner ); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yyg->yytext_ptr = yy_bp; \ + yyleng = (size_t) (yy_cp - yy_bp); \ + yyg->yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yyg->yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 41 +#define YY_END_OF_BUFFER 42 +/* This struct is not used in this scanner, + but its presence is necessary. */ +struct yy_trans_info + { + flex_int32_t yy_verify; + flex_int32_t yy_nxt; + }; +static yyconst flex_int16_t yy_accept[103] = + { 0, + 0, 0, 0, 0, 0, 0, 0, 0, 42, 40, + 21, 20, 20, 5, 40, 36, 37, 28, 40, 23, + 29, 40, 30, 30, 22, 38, 28, 28, 34, 35, + 24, 25, 21, 40, 3, 4, 3, 6, 14, 41, + 16, 19, 41, 21, 0, 39, 28, 29, 30, 29, + 0, 1, 0, 29, 0, 31, 0, 28, 28, 21, + 0, 0, 2, 6, 12, 0, 11, 10, 7, 8, + 9, 16, 18, 17, 0, 29, 29, 0, 0, 29, + 31, 32, 28, 28, 0, 0, 0, 29, 33, 28, + 26, 0, 13, 33, 27, 0, 0, 0, 0, 0, + + 15, 0 + } ; + +static yyconst flex_int32_t yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 4, 5, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 1, 6, 7, 1, 1, 1, 1, 8, + 9, 10, 11, 12, 13, 14, 15, 16, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 18, 19, 1, + 20, 1, 1, 21, 22, 23, 23, 23, 24, 25, + 26, 26, 26, 26, 26, 27, 26, 26, 26, 26, + 26, 28, 29, 30, 31, 26, 26, 32, 26, 26, + 33, 34, 35, 1, 36, 1, 22, 23, 37, 38, + + 39, 40, 26, 26, 41, 26, 26, 42, 26, 43, + 26, 26, 26, 44, 29, 45, 46, 26, 26, 32, + 26, 26, 47, 1, 48, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst flex_int32_t yy_meta[49] = + { 0, + 1, 1, 1, 1, 1, 2, 1, 1, 1, 3, + 1, 1, 3, 1, 1, 4, 4, 1, 1, 1, + 1, 4, 4, 4, 4, 3, 3, 3, 3, 3, + 3, 3, 1, 2, 1, 3, 4, 4, 4, 4, + 3, 3, 3, 3, 3, 3, 1, 1 + } ; + +static yyconst flex_int16_t yy_base[113] = + { 0, + 0, 47, 47, 48, 46, 47, 48, 49, 203, 204, + 200, 204, 204, 204, 198, 204, 204, 0, 45, 204, + 47, 50, 60, 74, 204, 204, 178, 28, 204, 204, + 204, 204, 64, 158, 204, 204, 183, 0, 204, 63, + 0, 204, 83, 195, 193, 204, 0, 88, 102, 98, + 62, 204, 190, 104, 119, 162, 0, 67, 65, 121, + 127, 124, 204, 0, 204, 0, 204, 204, 204, 204, + 204, 0, 204, 204, 108, 117, 122, 134, 132, 136, + 204, 139, 136, 116, 126, 0, 140, 142, 135, 130, + 0, 102, 204, 204, 0, 85, 72, 63, 98, 158, + + 204, 204, 169, 173, 177, 181, 183, 187, 191, 89, + 66, 63 + } ; + +static yyconst flex_int16_t yy_def[113] = + { 0, + 102, 1, 103, 103, 104, 104, 105, 105, 102, 102, + 102, 102, 102, 102, 106, 102, 102, 107, 102, 102, + 102, 102, 102, 102, 102, 102, 107, 107, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 108, 102, 102, + 109, 102, 102, 102, 106, 102, 107, 102, 102, 102, + 102, 102, 106, 102, 102, 102, 110, 107, 107, 102, + 102, 102, 102, 108, 102, 111, 102, 102, 102, 102, + 102, 109, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 110, 107, 107, 102, 112, 102, 102, 102, 107, + 107, 102, 102, 102, 107, 102, 102, 102, 102, 102, + + 102, 0, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102 + } ; + +static yyconst flex_int16_t yy_nxt[253] = + { 0, + 10, 11, 12, 13, 13, 14, 15, 16, 17, 18, + 19, 20, 19, 21, 22, 23, 24, 25, 26, 25, + 10, 18, 18, 18, 27, 18, 18, 18, 18, 28, + 18, 18, 29, 10, 30, 10, 18, 18, 18, 27, + 18, 18, 18, 18, 28, 18, 31, 32, 33, 36, + 36, 39, 39, 42, 42, 59, 37, 37, 48, 52, + 49, 49, 50, 50, 53, 60, 93, 34, 65, 86, + 51, 59, 75, 54, 75, 49, 49, 76, 76, 40, + 40, 43, 43, 55, 61, 51, 56, 54, 73, 49, + 49, 57, 82, 83, 66, 84, 67, 55, 55, 100, + + 56, 99, 68, 50, 50, 69, 70, 71, 83, 98, + 84, 51, 55, 50, 50, 54, 74, 49, 49, 77, + 77, 51, 60, 76, 76, 55, 51, 78, 56, 79, + 97, 79, 76, 76, 80, 80, 51, 77, 77, 91, + 55, 61, 78, 96, 87, 78, 87, 80, 80, 88, + 88, 80, 80, 95, 91, 88, 88, 88, 88, 100, + 78, 94, 92, 101, 90, 89, 85, 62, 95, 35, + 35, 35, 35, 38, 38, 38, 38, 41, 41, 41, + 41, 45, 45, 45, 45, 47, 47, 64, 81, 64, + 64, 72, 46, 72, 72, 46, 44, 63, 62, 58, + + 46, 44, 102, 9, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102 + } ; + +static yyconst flex_int16_t yy_chk[253] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 4, 5, 6, 7, 8, 28, 3, 4, 19, 22, + 19, 19, 21, 21, 22, 33, 112, 2, 40, 111, + 21, 28, 51, 23, 51, 23, 23, 51, 51, 5, + 6, 7, 8, 23, 33, 21, 23, 24, 43, 24, + 24, 23, 110, 58, 40, 59, 40, 24, 23, 99, + + 24, 98, 40, 48, 48, 40, 40, 40, 58, 97, + 59, 48, 24, 50, 50, 49, 43, 49, 49, 54, + 54, 50, 60, 75, 75, 49, 48, 54, 49, 55, + 96, 55, 76, 76, 55, 55, 50, 77, 77, 84, + 49, 60, 54, 92, 78, 77, 78, 79, 79, 78, + 78, 80, 80, 90, 84, 87, 87, 88, 88, 100, + 77, 89, 85, 100, 83, 82, 62, 61, 90, 103, + 103, 103, 103, 104, 104, 104, 104, 105, 105, 105, + 105, 106, 106, 106, 106, 107, 107, 108, 56, 108, + 108, 109, 53, 109, 109, 45, 44, 37, 34, 27, + + 15, 11, 9, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102 + } ; + +/* Table of booleans, true if rule could match eol. */ +static yyconst flex_int32_t yy_rule_can_match_eol[42] = + { 0, +0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, }; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +#line 1 "scanner.l" +/* -*- mode: C -*- */ +/* -------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files + Copyright (C) 2005-2010 Mark A Lindner + + This file is part of libconfig. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License + as published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, see + <http://www.gnu.org/licenses/>. + ---------------------------------------------------------------------------- +*/ +#define YY_NO_UNISTD_H 1 +#line 35 "scanner.l" + +#ifdef _MSC_VER +#pragma warning (disable: 4996) +#endif + +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include "grammar.h" +#include "wincompat.h" +#include "parsectx.h" +#include "scanctx.h" + +#define YY_NO_INPUT // Suppress generation of useless input() function + +static unsigned long long fromhex(const char *s) +{ +#ifdef __MINGW32__ + + /* MinGW's strtoull() seems to be broken; it only returns the lower + * 32 bits... + */ + + const char *p = s; + unsigned long long val = 0; + + if(*p != '0') + return(0); + + ++p; + + if(*p != 'x' && *p != 'X') + return(0); + + for(++p; isxdigit(*p); ++p) + { + val <<= 4; + val |= ((*p < 'A') ? (*p & 0xF) : (9 + (*p & 0x7))); + } + + return(val); + +#else /* ! __MINGW32__ */ + + return(strtoull(s, NULL, 16)); + +#endif /* __MINGW32__ */ +} + + +#line 626 "scanner.c" + +#define INITIAL 0 +#define COMMENT 1 +#define STRING 2 +#define INCLUDE 3 + +#ifndef YY_NO_UNISTD_H +/* Special case for "unistd.h", since it is non-ANSI. We include it way + * down here because we want the user's section 1 to have been scanned first. + * The user has a chance to override it with an option. + */ +#include <unistd.h> +#endif + +#define YY_EXTRA_TYPE struct scan_context * + +/* Holds the entire state of the reentrant scanner. */ +struct yyguts_t + { + + /* User-defined. Not touched by flex. */ + YY_EXTRA_TYPE yyextra_r; + + /* The rest are the same as the globals declared in the non-reentrant scanner. */ + FILE *yyin_r, *yyout_r; + size_t yy_buffer_stack_top; /**< index of top of stack. */ + size_t yy_buffer_stack_max; /**< capacity of stack. */ + YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */ + char yy_hold_char; + int yy_n_chars; + int yyleng_r; + char *yy_c_buf_p; + int yy_init; + int yy_start; + int yy_did_buffer_switch_on_eof; + int yy_start_stack_ptr; + int yy_start_stack_depth; + int *yy_start_stack; + yy_state_type yy_last_accepting_state; + char* yy_last_accepting_cpos; + + int yylineno_r; + int yy_flex_debug_r; + + char *yytext_r; + int yy_more_flag; + int yy_more_len; + + YYSTYPE * yylval_r; + + }; /* end struct yyguts_t */ + +static int yy_init_globals (yyscan_t yyscanner ); + + /* This must go here because YYSTYPE and YYLTYPE are included + * from bison output in section 1.*/ + # define yylval yyg->yylval_r + +int libconfig_yylex_init (yyscan_t* scanner); + +int libconfig_yylex_init_extra (YY_EXTRA_TYPE user_defined,yyscan_t* scanner); + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int libconfig_yylex_destroy (yyscan_t yyscanner ); + +int libconfig_yyget_debug (yyscan_t yyscanner ); + +void libconfig_yyset_debug (int debug_flag ,yyscan_t yyscanner ); + +YY_EXTRA_TYPE libconfig_yyget_extra (yyscan_t yyscanner ); + +void libconfig_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner ); + +FILE *libconfig_yyget_in (yyscan_t yyscanner ); + +void libconfig_yyset_in (FILE * in_str ,yyscan_t yyscanner ); + +FILE *libconfig_yyget_out (yyscan_t yyscanner ); + +void libconfig_yyset_out (FILE * out_str ,yyscan_t yyscanner ); + +int libconfig_yyget_leng (yyscan_t yyscanner ); + +char *libconfig_yyget_text (yyscan_t yyscanner ); + +int libconfig_yyget_lineno (yyscan_t yyscanner ); + +void libconfig_yyset_lineno (int line_number ,yyscan_t yyscanner ); + +YYSTYPE * libconfig_yyget_lval (yyscan_t yyscanner ); + +void libconfig_yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int libconfig_yywrap (yyscan_t yyscanner ); +#else +extern int libconfig_yywrap (yyscan_t yyscanner ); +#endif +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner); +#endif + +#ifndef YY_NO_INPUT + +#ifdef __cplusplus +static int yyinput (yyscan_t yyscanner ); +#else +static int input (yyscan_t yyscanner ); +#endif + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#ifdef __ia64__ +/* On IA-64, the buffer size is 16k, not 8k */ +#define YY_READ_BUF_SIZE 16384 +#else +#define YY_READ_BUF_SIZE 8192 +#endif /* __ia64__ */ +#endif + +/* Copy whatever the last rule matched to the standard output. */ +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO do { if (fwrite( yytext, yyleng, 1, yyout )) {} } while (0) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \ + { \ + int c = '*'; \ + size_t n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else \ + { \ + errno=0; \ + while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \ + { \ + if( errno != EINTR) \ + { \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + break; \ + } \ + errno=0; \ + clearerr(yyin); \ + } \ + }\ +\ + +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner) +#endif + +/* end tables serialization structures and prototypes */ + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int libconfig_yylex \ + (YYSTYPE * yylval_param ,yyscan_t yyscanner); + +#define YY_DECL int libconfig_yylex \ + (YYSTYPE * yylval_param , yyscan_t yyscanner) +#endif /* !YY_DECL */ + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + if ( yyleng > 0 ) \ + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \ + (yytext[yyleng - 1] == '\n'); \ + YY_USER_ACTION + +/** The main scanner function which does all the work. + */ +YY_DECL +{ + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + +#line 100 "scanner.l" + + +#line 869 "scanner.c" + + yylval = yylval_param; + + if ( !yyg->yy_init ) + { + yyg->yy_init = 1; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yyg->yy_start ) + yyg->yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! YY_CURRENT_BUFFER ) { + libconfig_yyensure_buffer_stack (yyscanner); + YY_CURRENT_BUFFER_LVALUE = + libconfig_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); + } + + libconfig_yy_load_buffer_state(yyscanner ); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yyg->yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yyg->yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yyg->yy_start; + yy_current_state += YY_AT_BOL(); +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 103 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 204 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + + if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] ) + { + int yyl; + for ( yyl = 0; yyl < yyleng; ++yyl ) + if ( yytext[yyl] == '\n' ) + + do{ yylineno++; + yycolumn=0; + }while(0) +; + } + +do_action: /* This label is used only to access EOF actions. */ + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yyg->yy_hold_char; + yy_cp = yyg->yy_last_accepting_cpos; + yy_current_state = yyg->yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 102 "scanner.l" +{ BEGIN COMMENT; } + YY_BREAK +case 2: +YY_RULE_SETUP +#line 103 "scanner.l" +{ BEGIN INITIAL; } + YY_BREAK +case 3: +YY_RULE_SETUP +#line 104 "scanner.l" +{ /* ignore */ } + YY_BREAK +case 4: +/* rule 4 can match eol */ +YY_RULE_SETUP +#line 105 "scanner.l" +{ /* ignore */ } + YY_BREAK +case 5: +YY_RULE_SETUP +#line 107 "scanner.l" +{ BEGIN STRING; } + YY_BREAK +case 6: +/* rule 6 can match eol */ +YY_RULE_SETUP +#line 108 "scanner.l" +{ scanctx_append_string(yyextra, yytext); } + YY_BREAK +case 7: +YY_RULE_SETUP +#line 109 "scanner.l" +{ scanctx_append_string(yyextra, "\n"); } + YY_BREAK +case 8: +YY_RULE_SETUP +#line 110 "scanner.l" +{ scanctx_append_string(yyextra, "\r"); } + YY_BREAK +case 9: +YY_RULE_SETUP +#line 111 "scanner.l" +{ scanctx_append_string(yyextra, "\t"); } + YY_BREAK +case 10: +YY_RULE_SETUP +#line 112 "scanner.l" +{ scanctx_append_string(yyextra, "\f"); } + YY_BREAK +case 11: +YY_RULE_SETUP +#line 113 "scanner.l" +{ scanctx_append_string(yyextra, "\\"); } + YY_BREAK +case 12: +YY_RULE_SETUP +#line 114 "scanner.l" +{ scanctx_append_string(yyextra, "\""); } + YY_BREAK +case 13: +YY_RULE_SETUP +#line 115 "scanner.l" +{ + char c[2] = { (char)(strtol(yytext + 2, NULL, 16) & 0xFF), + 0 }; + scanctx_append_string(yyextra, c); + } + YY_BREAK +case 14: +YY_RULE_SETUP +#line 120 "scanner.l" +{ + yylval->sval = scanctx_take_string(yyextra); + BEGIN INITIAL; + return(TOK_STRING); + } + YY_BREAK +case 15: +YY_RULE_SETUP +#line 126 "scanner.l" +{ BEGIN INCLUDE; } + YY_BREAK +case 16: +/* rule 16 can match eol */ +YY_RULE_SETUP +#line 127 "scanner.l" +{ scanctx_append_string(yyextra, yytext); } + YY_BREAK +case 17: +YY_RULE_SETUP +#line 128 "scanner.l" +{ scanctx_append_string(yyextra, "\\"); } + YY_BREAK +case 18: +YY_RULE_SETUP +#line 129 "scanner.l" +{ scanctx_append_string(yyextra, "\""); } + YY_BREAK +case 19: +YY_RULE_SETUP +#line 130 "scanner.l" +{ + const char *error; + FILE *fp = scanctx_push_include(yyextra, + (void *)YY_CURRENT_BUFFER, + &error); + if(fp) + { + yyin = fp; + libconfig_yy_switch_to_buffer(libconfig_yy_create_buffer(yyin,YY_BUF_SIZE,yyscanner),yyscanner); + } + else + { + yyextra->config->error_text = error; + yyextra->config->error_file = scanctx_current_filename( + yyextra); + yyextra->config->error_line = libconfig_yyget_lineno( + yyscanner); + return TOK_ERROR; + } + BEGIN INITIAL; + } + YY_BREAK +case 20: +/* rule 20 can match eol */ +YY_RULE_SETUP +#line 154 "scanner.l" +{ /* ignore */ } + YY_BREAK +case 21: +YY_RULE_SETUP +#line 155 "scanner.l" +{ /* ignore */ } + YY_BREAK +case 22: +YY_RULE_SETUP +#line 157 "scanner.l" +{ return(TOK_EQUALS); } + YY_BREAK +case 23: +YY_RULE_SETUP +#line 158 "scanner.l" +{ return(TOK_COMMA); } + YY_BREAK +case 24: +YY_RULE_SETUP +#line 159 "scanner.l" +{ return(TOK_GROUP_START); } + YY_BREAK +case 25: +YY_RULE_SETUP +#line 160 "scanner.l" +{ return(TOK_GROUP_END); } + YY_BREAK +case 26: +YY_RULE_SETUP +#line 161 "scanner.l" +{ yylval->ival = 1; return(TOK_BOOLEAN); } + YY_BREAK +case 27: +YY_RULE_SETUP +#line 162 "scanner.l" +{ yylval->ival = 0; return(TOK_BOOLEAN); } + YY_BREAK +case 28: +YY_RULE_SETUP +#line 163 "scanner.l" +{ yylval->sval = yytext; return(TOK_NAME); } + YY_BREAK +case 29: +YY_RULE_SETUP +#line 164 "scanner.l" +{ yylval->fval = atof(yytext); return(TOK_FLOAT); } + YY_BREAK +case 30: +YY_RULE_SETUP +#line 165 "scanner.l" +{ yylval->ival = atoi(yytext); return(TOK_INTEGER); } + YY_BREAK +case 31: +YY_RULE_SETUP +#line 166 "scanner.l" +{ yylval->llval = atoll(yytext); return(TOK_INTEGER64); } + YY_BREAK +case 32: +YY_RULE_SETUP +#line 167 "scanner.l" +{ + yylval->ival = strtoul(yytext, NULL, 16); + return(TOK_HEX); + } + YY_BREAK +case 33: +YY_RULE_SETUP +#line 171 "scanner.l" +{ yylval->llval = fromhex(yytext); return(TOK_HEX64); } + YY_BREAK +case 34: +YY_RULE_SETUP +#line 172 "scanner.l" +{ return(TOK_ARRAY_START); } + YY_BREAK +case 35: +YY_RULE_SETUP +#line 173 "scanner.l" +{ return(TOK_ARRAY_END); } + YY_BREAK +case 36: +YY_RULE_SETUP +#line 174 "scanner.l" +{ return(TOK_LIST_START); } + YY_BREAK +case 37: +YY_RULE_SETUP +#line 175 "scanner.l" +{ return(TOK_LIST_END); } + YY_BREAK +case 38: +YY_RULE_SETUP +#line 176 "scanner.l" +{ return(TOK_SEMICOLON); } + YY_BREAK +case 39: +*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */ +yyg->yy_c_buf_p = yy_cp -= 1; +YY_DO_BEFORE_ACTION; /* set up yytext again */ +YY_RULE_SETUP +#line 177 "scanner.l" +{ /* ignore */ } + YY_BREAK +case 40: +YY_RULE_SETUP +#line 178 "scanner.l" +{ return(TOK_GARBAGE); } + YY_BREAK +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(COMMENT): +case YY_STATE_EOF(STRING): +case YY_STATE_EOF(INCLUDE): +#line 180 "scanner.l" +{ + YY_BUFFER_STATE buf = (YY_BUFFER_STATE)scanctx_pop_include( + yyextra); + if(buf) + { + libconfig_yy_delete_buffer(YY_CURRENT_BUFFER,yyscanner); + libconfig_yy_switch_to_buffer(buf,yyscanner); + } + else + yyterminate(); + } + YY_BREAK +case 41: +YY_RULE_SETUP +#line 191 "scanner.l" +ECHO; + YY_BREAK +#line 1227 "scanner.c" + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yyg->yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * libconfig_yylex(). If so, then we have to assure + * consistency between YY_CURRENT_BUFFER and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( yyscanner ); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner); + + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yyg->yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yyg->yy_c_buf_p; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer( yyscanner ) ) + { + case EOB_ACT_END_OF_FILE: + { + yyg->yy_did_buffer_switch_on_eof = 0; + + if ( libconfig_yywrap(yyscanner ) ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yyg->yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yyg->yy_c_buf_p = + yyg->yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state( yyscanner ); + + yy_cp = yyg->yy_c_buf_p; + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yyg->yy_c_buf_p = + &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars]; + + yy_current_state = yy_get_previous_state( yyscanner ); + + yy_cp = yyg->yy_c_buf_p; + yy_bp = yyg->yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ +} /* end of libconfig_yylex */ + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ +static int yy_get_next_buffer (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf; + register char *source = yyg->yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0; + + else + { + int num_to_read = + YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = YY_CURRENT_BUFFER; + + int yy_c_buf_p_offset = + (int) (yyg->yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + libconfig_yyrealloc((void *) b->yy_ch_buf,b->yy_buf_size + 2 ,yyscanner ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yyg->yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = YY_CURRENT_BUFFER_LVALUE->yy_buf_size - + number_to_move - 1; + + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), + yyg->yy_n_chars, (size_t) num_to_read ); + + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + if ( yyg->yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + libconfig_yyrestart(yyin ,yyscanner); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + if ((yy_size_t) (yyg->yy_n_chars + number_to_move) > YY_CURRENT_BUFFER_LVALUE->yy_buf_size) { + /* Extend the array by 50%, plus the number we really need. */ + yy_size_t new_size = yyg->yy_n_chars + number_to_move + (yyg->yy_n_chars >> 1); + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf = (char *) libconfig_yyrealloc((void *) YY_CURRENT_BUFFER_LVALUE->yy_ch_buf,new_size ,yyscanner ); + if ( ! YY_CURRENT_BUFFER_LVALUE->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_get_next_buffer()" ); + } + + yyg->yy_n_chars += number_to_move; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR; + YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0]; + + return ret_val; +} + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + + static yy_state_type yy_get_previous_state (yyscan_t yyscanner) +{ + register yy_state_type yy_current_state; + register char *yy_cp; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + yy_current_state = yyg->yy_start; + yy_current_state += YY_AT_BOL(); + + for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 103 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; +} + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner) +{ + register int yy_is_jam; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */ + register char *yy_cp = yyg->yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yyg->yy_last_accepting_state = yy_current_state; + yyg->yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 103 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 102); + + return yy_is_jam ? 0 : yy_current_state; +} + +#ifndef YY_NO_INPUT +#ifdef __cplusplus + static int yyinput (yyscan_t yyscanner) +#else + static int input (yyscan_t yyscanner) +#endif + +{ + int c; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + *yyg->yy_c_buf_p = yyg->yy_hold_char; + + if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] ) + /* This was really a NUL. */ + *yyg->yy_c_buf_p = '\0'; + + else + { /* need more input */ + int offset = yyg->yy_c_buf_p - yyg->yytext_ptr; + ++yyg->yy_c_buf_p; + + switch ( yy_get_next_buffer( yyscanner ) ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + libconfig_yyrestart(yyin ,yyscanner); + + /*FALLTHROUGH*/ + + case EOB_ACT_END_OF_FILE: + { + if ( libconfig_yywrap(yyscanner ) ) + return EOF; + + if ( ! yyg->yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(yyscanner); +#else + return input(yyscanner); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yyg->yy_c_buf_p = yyg->yytext_ptr + offset; + break; + } + } + } + + c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */ + *yyg->yy_c_buf_p = '\0'; /* preserve yytext */ + yyg->yy_hold_char = *++yyg->yy_c_buf_p; + + YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n'); + if ( YY_CURRENT_BUFFER_LVALUE->yy_at_bol ) + + do{ yylineno++; + yycolumn=0; + }while(0) +; + + return c; +} +#endif /* ifndef YY_NO_INPUT */ + +/** Immediately switch to a different input stream. + * @param input_file A readable stream. + * @param yyscanner The scanner object. + * @note This function does not reset the start condition to @c INITIAL . + */ + void libconfig_yyrestart (FILE * input_file , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if ( ! YY_CURRENT_BUFFER ){ + libconfig_yyensure_buffer_stack (yyscanner); + YY_CURRENT_BUFFER_LVALUE = + libconfig_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); + } + + libconfig_yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner); + libconfig_yy_load_buffer_state(yyscanner ); +} + +/** Switch to a different input buffer. + * @param new_buffer The new input buffer. + * @param yyscanner The scanner object. + */ + void libconfig_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* TODO. We should be able to replace this entire function body + * with + * libconfig_yypop_buffer_state(); + * libconfig_yypush_buffer_state(new_buffer); + */ + libconfig_yyensure_buffer_stack (yyscanner); + if ( YY_CURRENT_BUFFER == new_buffer ) + return; + + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *yyg->yy_c_buf_p = yyg->yy_hold_char; + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + YY_CURRENT_BUFFER_LVALUE = new_buffer; + libconfig_yy_load_buffer_state(yyscanner ); + + /* We don't actually know whether we did this switch during + * EOF (libconfig_yywrap()) processing, but the only time this flag + * is looked at is after libconfig_yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yyg->yy_did_buffer_switch_on_eof = 1; +} + +static void libconfig_yy_load_buffer_state (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars; + yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos; + yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file; + yyg->yy_hold_char = *yyg->yy_c_buf_p; +} + +/** Allocate and initialize an input buffer state. + * @param file A readable stream. + * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE. + * @param yyscanner The scanner object. + * @return the allocated buffer state. + */ + YY_BUFFER_STATE libconfig_yy_create_buffer (FILE * file, int size , yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) libconfig_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in libconfig_yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) libconfig_yyalloc(b->yy_buf_size + 2 ,yyscanner ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in libconfig_yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + libconfig_yy_init_buffer(b,file ,yyscanner); + + return b; +} + +/** Destroy the buffer. + * @param b a buffer created with libconfig_yy_create_buffer() + * @param yyscanner The scanner object. + */ + void libconfig_yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if ( ! b ) + return; + + if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */ + YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + libconfig_yyfree((void *) b->yy_ch_buf ,yyscanner ); + + libconfig_yyfree((void *) b ,yyscanner ); +} + +#ifndef __cplusplus +extern int isatty (int ); +#endif /* __cplusplus */ + +/* Initializes or reinitializes a buffer. + * This function is sometimes called more than once on the same buffer, + * such as during a libconfig_yyrestart() or at EOF. + */ + static void libconfig_yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner) + +{ + int oerrno = errno; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + libconfig_yy_flush_buffer(b ,yyscanner); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + + /* If b is the current buffer, then libconfig_yy_init_buffer was _probably_ + * called from libconfig_yyrestart() or through yy_get_next_buffer. + * In that case, we don't want to reset the lineno or column. + */ + if (b != YY_CURRENT_BUFFER){ + b->yy_bs_lineno = 1; + b->yy_bs_column = 0; + } + + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; + + errno = oerrno; +} + +/** Discard all buffered characters. On the next scan, YY_INPUT will be called. + * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER. + * @param yyscanner The scanner object. + */ + void libconfig_yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == YY_CURRENT_BUFFER ) + libconfig_yy_load_buffer_state(yyscanner ); +} + +/** Pushes the new state onto the stack. The new state becomes + * the current state. This function will allocate the stack + * if necessary. + * @param new_buffer The new state. + * @param yyscanner The scanner object. + */ +void libconfig_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if (new_buffer == NULL) + return; + + libconfig_yyensure_buffer_stack(yyscanner); + + /* This block is copied from libconfig_yy_switch_to_buffer. */ + if ( YY_CURRENT_BUFFER ) + { + /* Flush out information for old buffer. */ + *yyg->yy_c_buf_p = yyg->yy_hold_char; + YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p; + YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars; + } + + /* Only push if top exists. Otherwise, replace top. */ + if (YY_CURRENT_BUFFER) + yyg->yy_buffer_stack_top++; + YY_CURRENT_BUFFER_LVALUE = new_buffer; + + /* copied from libconfig_yy_switch_to_buffer. */ + libconfig_yy_load_buffer_state(yyscanner ); + yyg->yy_did_buffer_switch_on_eof = 1; +} + +/** Removes and deletes the top of the stack, if present. + * The next element becomes the new top. + * @param yyscanner The scanner object. + */ +void libconfig_yypop_buffer_state (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + if (!YY_CURRENT_BUFFER) + return; + + libconfig_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner); + YY_CURRENT_BUFFER_LVALUE = NULL; + if (yyg->yy_buffer_stack_top > 0) + --yyg->yy_buffer_stack_top; + + if (YY_CURRENT_BUFFER) { + libconfig_yy_load_buffer_state(yyscanner ); + yyg->yy_did_buffer_switch_on_eof = 1; + } +} + +/* Allocates the stack if it does not exist. + * Guarantees space for at least one push. + */ +static void libconfig_yyensure_buffer_stack (yyscan_t yyscanner) +{ + int num_to_alloc; + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (!yyg->yy_buffer_stack) { + + /* First allocation is just for 2 elements, since we don't know if this + * scanner will even need a stack. We use 2 instead of 1 to avoid an + * immediate realloc on the next call. + */ + num_to_alloc = 1; + yyg->yy_buffer_stack = (struct yy_buffer_state**)libconfig_yyalloc + (num_to_alloc * sizeof(struct yy_buffer_state*) + , yyscanner); + if ( ! yyg->yy_buffer_stack ) + YY_FATAL_ERROR( "out of dynamic memory in libconfig_yyensure_buffer_stack()" ); + + memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*)); + + yyg->yy_buffer_stack_max = num_to_alloc; + yyg->yy_buffer_stack_top = 0; + return; + } + + if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){ + + /* Increase the buffer to prepare for a possible push. */ + int grow_size = 8 /* arbitrary grow size */; + + num_to_alloc = yyg->yy_buffer_stack_max + grow_size; + yyg->yy_buffer_stack = (struct yy_buffer_state**)libconfig_yyrealloc + (yyg->yy_buffer_stack, + num_to_alloc * sizeof(struct yy_buffer_state*) + , yyscanner); + if ( ! yyg->yy_buffer_stack ) + YY_FATAL_ERROR( "out of dynamic memory in libconfig_yyensure_buffer_stack()" ); + + /* zero only the new slots.*/ + memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*)); + yyg->yy_buffer_stack_max = num_to_alloc; + } +} + +/** Setup the input buffer state to scan directly from a user-specified character buffer. + * @param base the character buffer + * @param size the size in bytes of the character buffer + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE libconfig_yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) libconfig_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in libconfig_yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + libconfig_yy_switch_to_buffer(b ,yyscanner ); + + return b; +} + +/** Setup the input buffer state to scan a string. The next call to libconfig_yylex() will + * scan from a @e copy of @a str. + * @param yystr a NUL-terminated string to scan + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + * @note If you want to scan bytes that may contain NUL values, then use + * libconfig_yy_scan_bytes() instead. + */ +YY_BUFFER_STATE libconfig_yy_scan_string (yyconst char * yystr , yyscan_t yyscanner) +{ + + return libconfig_yy_scan_bytes(yystr,strlen(yystr) ,yyscanner); +} + +/** Setup the input buffer state to scan the given bytes. The next call to libconfig_yylex() will + * scan from a @e copy of @a bytes. + * @param yybytes the byte buffer to scan + * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes. + * @param yyscanner The scanner object. + * @return the newly allocated buffer state object. + */ +YY_BUFFER_STATE libconfig_yy_scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner) +{ + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = _yybytes_len + 2; + buf = (char *) libconfig_yyalloc(n ,yyscanner ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in libconfig_yy_scan_bytes()" ); + + for ( i = 0; i < _yybytes_len; ++i ) + buf[i] = yybytes[i]; + + buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR; + + b = libconfig_yy_scan_buffer(buf,n ,yyscanner); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in libconfig_yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; +} + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner) +{ + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); +} + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + int yyless_macro_arg = (n); \ + YY_LESS_LINENO(yyless_macro_arg);\ + yytext[yyleng] = yyg->yy_hold_char; \ + yyg->yy_c_buf_p = yytext + yyless_macro_arg; \ + yyg->yy_hold_char = *yyg->yy_c_buf_p; \ + *yyg->yy_c_buf_p = '\0'; \ + yyleng = yyless_macro_arg; \ + } \ + while ( 0 ) + +/* Accessor methods (get/set functions) to struct members. */ + +/** Get the user-defined data for this scanner. + * @param yyscanner The scanner object. + */ +YY_EXTRA_TYPE libconfig_yyget_extra (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyextra; +} + +/** Get the current line number. + * @param yyscanner The scanner object. + */ +int libconfig_yyget_lineno (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (! YY_CURRENT_BUFFER) + return 0; + + return yylineno; +} + +/** Get the current column number. + * @param yyscanner The scanner object. + */ +int libconfig_yyget_column (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + if (! YY_CURRENT_BUFFER) + return 0; + + return yycolumn; +} + +/** Get the input stream. + * @param yyscanner The scanner object. + */ +FILE *libconfig_yyget_in (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyin; +} + +/** Get the output stream. + * @param yyscanner The scanner object. + */ +FILE *libconfig_yyget_out (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyout; +} + +/** Get the length of the current token. + * @param yyscanner The scanner object. + */ +int libconfig_yyget_leng (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yyleng; +} + +/** Get the current token. + * @param yyscanner The scanner object. + */ + +char *libconfig_yyget_text (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yytext; +} + +/** Set the user-defined data. This data is never touched by the scanner. + * @param user_defined The data to be associated with this scanner. + * @param yyscanner The scanner object. + */ +void libconfig_yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyextra = user_defined ; +} + +/** Set the current line number. + * @param line_number + * @param yyscanner The scanner object. + */ +void libconfig_yyset_lineno (int line_number , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* lineno is only valid if an input buffer exists. */ + if (! YY_CURRENT_BUFFER ) + yy_fatal_error( "libconfig_yyset_lineno called with no buffer" , yyscanner); + + yylineno = line_number; +} + +/** Set the current column. + * @param line_number + * @param yyscanner The scanner object. + */ +void libconfig_yyset_column (int column_no , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* column is only valid if an input buffer exists. */ + if (! YY_CURRENT_BUFFER ) + yy_fatal_error( "libconfig_yyset_column called with no buffer" , yyscanner); + + yycolumn = column_no; +} + +/** Set the input stream. This does not discard the current + * input buffer. + * @param in_str A readable stream. + * @param yyscanner The scanner object. + * @see libconfig_yy_switch_to_buffer + */ +void libconfig_yyset_in (FILE * in_str , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyin = in_str ; +} + +void libconfig_yyset_out (FILE * out_str , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yyout = out_str ; +} + +int libconfig_yyget_debug (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yy_flex_debug; +} + +void libconfig_yyset_debug (int bdebug , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yy_flex_debug = bdebug ; +} + +/* Accessor methods for yylval and yylloc */ + +YYSTYPE * libconfig_yyget_lval (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + return yylval; +} + +void libconfig_yyset_lval (YYSTYPE * yylval_param , yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + yylval = yylval_param; +} + +/* User-visible API */ + +/* libconfig_yylex_init is special because it creates the scanner itself, so it is + * the ONLY reentrant function that doesn't take the scanner as the last argument. + * That's why we explicitly handle the declaration, instead of using our macros. + */ + +int libconfig_yylex_init(yyscan_t* ptr_yy_globals) + +{ + if (ptr_yy_globals == NULL){ + errno = EINVAL; + return 1; + } + + *ptr_yy_globals = (yyscan_t) libconfig_yyalloc ( sizeof( struct yyguts_t ), NULL ); + + if (*ptr_yy_globals == NULL){ + errno = ENOMEM; + return 1; + } + + /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */ + memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); + + return yy_init_globals ( *ptr_yy_globals ); +} + +/* libconfig_yylex_init_extra has the same functionality as libconfig_yylex_init, but follows the + * convention of taking the scanner as the last argument. Note however, that + * this is a *pointer* to a scanner, as it will be allocated by this call (and + * is the reason, too, why this function also must handle its own declaration). + * The user defined value in the first argument will be available to libconfig_yyalloc in + * the yyextra field. + */ + +int libconfig_yylex_init_extra(YY_EXTRA_TYPE yy_user_defined,yyscan_t* ptr_yy_globals ) + +{ + struct yyguts_t dummy_yyguts; + + libconfig_yyset_extra (yy_user_defined, &dummy_yyguts); + + if (ptr_yy_globals == NULL){ + errno = EINVAL; + return 1; + } + + *ptr_yy_globals = (yyscan_t) libconfig_yyalloc ( sizeof( struct yyguts_t ), &dummy_yyguts ); + + if (*ptr_yy_globals == NULL){ + errno = ENOMEM; + return 1; + } + + /* By setting to 0xAA, we expose bugs in + yy_init_globals. Leave at 0x00 for releases. */ + memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t)); + + libconfig_yyset_extra (yy_user_defined, *ptr_yy_globals); + + return yy_init_globals ( *ptr_yy_globals ); +} + +static int yy_init_globals (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + /* Initialization is the same as for the non-reentrant scanner. + * This function is called from libconfig_yylex_destroy(), so don't allocate here. + */ + + yyg->yy_buffer_stack = 0; + yyg->yy_buffer_stack_top = 0; + yyg->yy_buffer_stack_max = 0; + yyg->yy_c_buf_p = (char *) 0; + yyg->yy_init = 0; + yyg->yy_start = 0; + + yyg->yy_start_stack_ptr = 0; + yyg->yy_start_stack_depth = 0; + yyg->yy_start_stack = NULL; + +/* Defined in main.c */ +#ifdef YY_STDINIT + yyin = stdin; + yyout = stdout; +#else + yyin = (FILE *) 0; + yyout = (FILE *) 0; +#endif + + /* For future reference: Set errno on error, since we are called by + * libconfig_yylex_init() + */ + return 0; +} + +/* libconfig_yylex_destroy is for both reentrant and non-reentrant scanners. */ +int libconfig_yylex_destroy (yyscan_t yyscanner) +{ + struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; + + /* Pop the buffer stack, destroying each element. */ + while(YY_CURRENT_BUFFER){ + libconfig_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner ); + YY_CURRENT_BUFFER_LVALUE = NULL; + libconfig_yypop_buffer_state(yyscanner); + } + + /* Destroy the stack itself. */ + libconfig_yyfree(yyg->yy_buffer_stack ,yyscanner); + yyg->yy_buffer_stack = NULL; + + /* Destroy the start condition stack. */ + libconfig_yyfree(yyg->yy_start_stack ,yyscanner ); + yyg->yy_start_stack = NULL; + + /* Reset the globals. This is important in a non-reentrant scanner so the next time + * libconfig_yylex() is called, initialization will occur. */ + yy_init_globals( yyscanner); + + /* Destroy the main struct (reentrant only). */ + libconfig_yyfree ( yyscanner , yyscanner ); + yyscanner = NULL; + return 0; +} + +/* + * Internal utility routines. + */ + +#ifndef yytext_ptr +static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner) +{ + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; +} +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner) +{ + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; +} +#endif + +void *libconfig_yyalloc (yy_size_t size , yyscan_t yyscanner) +{ + return (void *) malloc( size ); +} + +void *libconfig_yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner) +{ + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); +} + +void libconfig_yyfree (void * ptr , yyscan_t yyscanner) +{ + free( (char *) ptr ); /* see libconfig_yyrealloc() for (char *) cast */ +} + +#define YYTABLES_NAME "yytables" + +#line 191 "scanner.l" diff --git a/3rdparty/libconfig/scanner.h b/3rdparty/libconfig/scanner.h new file mode 100644 index 000000000..baa6f771f --- /dev/null +++ b/3rdparty/libconfig/scanner.h @@ -0,0 +1,326 @@ +#ifndef libconfig_yyHEADER_H +#define libconfig_yyHEADER_H 1 +#define libconfig_yyIN_HEADER 1 + +#line 6 "scanner.h" + +#line 8 "scanner.h" + +#define YY_INT_ALIGNED short int + +/* A lexical scanner generated by flex */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 +#define YY_FLEX_SUBMINOR_VERSION 33 +#if YY_FLEX_SUBMINOR_VERSION > 0 +#define FLEX_BETA +#endif + +/* First, we deal with platform-specific or compiler-specific issues. */ + +/* begin standard C headers. */ +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> + +/* end standard C headers. */ + +/* flex integer type definitions */ + +#ifndef FLEXINT_H +#define FLEXINT_H + +/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */ + +#if __STDC_VERSION__ >= 199901L + +/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h, + * if you want the limit (max/min) macros for int types. + */ +#ifndef __STDC_LIMIT_MACROS +#define __STDC_LIMIT_MACROS 1 +#endif + +#include <inttypes.h> +typedef int8_t flex_int8_t; +typedef uint8_t flex_uint8_t; +typedef int16_t flex_int16_t; +typedef uint16_t flex_uint16_t; +typedef int32_t flex_int32_t; +typedef uint32_t flex_uint32_t; +#else +typedef signed char flex_int8_t; +typedef short int flex_int16_t; +typedef int flex_int32_t; +typedef unsigned char flex_uint8_t; +typedef unsigned short int flex_uint16_t; +typedef unsigned int flex_uint32_t; +#endif /* ! C99 */ + +/* Limits of integral types. */ +#ifndef INT8_MIN +#define INT8_MIN (-128) +#endif +#ifndef INT16_MIN +#define INT16_MIN (-32767-1) +#endif +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif +#ifndef INT8_MAX +#define INT8_MAX (127) +#endif +#ifndef INT16_MAX +#define INT16_MAX (32767) +#endif +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif +#ifndef UINT8_MAX +#define UINT8_MAX (255U) +#endif +#ifndef UINT16_MAX +#define UINT16_MAX (65535U) +#endif +#ifndef UINT32_MAX +#define UINT32_MAX (4294967295U) +#endif + +#endif /* ! FLEXINT_H */ + +#ifdef __cplusplus + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#if __STDC__ + +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + +/* An opaque pointer. */ +#ifndef YY_TYPEDEF_YY_SCANNER_T +#define YY_TYPEDEF_YY_SCANNER_T +typedef void* yyscan_t; +#endif + +/* For convenience, these vars (plus the bison vars far below) + are macros in the reentrant scanner. */ +#define yyin yyg->yyin_r +#define yyout yyg->yyout_r +#define yyextra yyg->yyextra_r +#define yyleng yyg->yyleng_r +#define yytext yyg->yytext_r +#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno) +#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column) +#define yy_flex_debug yyg->yy_flex_debug_r + +int libconfig_yylex_init (yyscan_t* scanner); + +#ifndef YY_TYPEDEF_YY_BUFFER_STATE +#define YY_TYPEDEF_YY_BUFFER_STATE +typedef struct yy_buffer_state *YY_BUFFER_STATE; +#endif + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ + +#ifndef YY_TYPEDEF_YY_SIZE_T +#define YY_TYPEDEF_YY_SIZE_T +typedef unsigned int yy_size_t; +#endif + +#ifndef YY_STRUCT_YY_BUFFER_STATE +#define YY_STRUCT_YY_BUFFER_STATE +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + int yy_bs_lineno; /**< The line count. */ + int yy_bs_column; /**< The column count. */ + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; + + }; +#endif /* !YY_STRUCT_YY_BUFFER_STATE */ + +void libconfig_yyrestart (FILE *input_file ,yyscan_t yyscanner ); +void libconfig_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); +YY_BUFFER_STATE libconfig_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner ); +void libconfig_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); +void libconfig_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner ); +void libconfig_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner ); +void libconfig_yypop_buffer_state (yyscan_t yyscanner ); + +YY_BUFFER_STATE libconfig_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner ); +YY_BUFFER_STATE libconfig_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner ); +YY_BUFFER_STATE libconfig_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner ); + +void *libconfig_yyalloc (yy_size_t ,yyscan_t yyscanner ); +void *libconfig_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner ); +void libconfig_yyfree (void * ,yyscan_t yyscanner ); + +#define libconfig_yywrap(n) 1 +#define YY_SKIP_YYWRAP + +#define yytext_ptr yytext_r + +#ifdef YY_HEADER_EXPORT_START_CONDITIONS +#define INITIAL 0 +#define COMMENT 1 + +#endif + +#ifndef YY_EXTRA_TYPE +#define YY_EXTRA_TYPE void * +#endif + +/* Accessor methods to globals. + These are made visible to non-reentrant scanners for convenience. */ + +int libconfig_yylex_destroy (yyscan_t yyscanner ); + +int libconfig_yyget_debug (yyscan_t yyscanner ); + +void libconfig_yyset_debug (int debug_flag ,yyscan_t yyscanner ); + +YY_EXTRA_TYPE libconfig_yyget_extra (yyscan_t yyscanner ); + +void libconfig_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner ); + +FILE *libconfig_yyget_in (yyscan_t yyscanner ); + +void libconfig_yyset_in (FILE * in_str ,yyscan_t yyscanner ); + +FILE *libconfig_yyget_out (yyscan_t yyscanner ); + +void libconfig_yyset_out (FILE * out_str ,yyscan_t yyscanner ); + +int libconfig_yyget_leng (yyscan_t yyscanner ); + +char *libconfig_yyget_text (yyscan_t yyscanner ); + +int libconfig_yyget_lineno (yyscan_t yyscanner ); + +void libconfig_yyset_lineno (int line_number ,yyscan_t yyscanner ); + +YYSTYPE * libconfig_yyget_lval (yyscan_t yyscanner ); + +void libconfig_yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner ); + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int libconfig_yywrap (yyscan_t yyscanner ); +#else +extern int libconfig_yywrap (yyscan_t yyscanner ); +#endif +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner); +#endif + +#ifndef YY_NO_INPUT + +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL_IS_OURS 1 + +extern int libconfig_yylex (YYSTYPE * yylval_param ,yyscan_t yyscanner); + +#define YY_DECL int libconfig_yylex (YYSTYPE * yylval_param , yyscan_t yyscanner) +#endif /* !YY_DECL */ + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +#undef YY_NEW_FILE +#undef YY_FLUSH_BUFFER +#undef yy_set_bol +#undef yy_new_buffer +#undef yy_set_interactive +#undef YY_DO_BEFORE_ACTION + +#ifdef YY_DECL_IS_OURS +#undef YY_DECL_IS_OURS +#undef YY_DECL +#endif + +#line 130 "scanner.l" + +#line 325 "scanner.h" +#undef libconfig_yyIN_HEADER +#endif /* libconfig_yyHEADER_H */ diff --git a/3rdparty/libconfig/strbuf.c b/3rdparty/libconfig/strbuf.c new file mode 100644 index 000000000..d2a667a7c --- /dev/null +++ b/3rdparty/libconfig/strbuf.c @@ -0,0 +1,57 @@ +/* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files + Copyright (C) 2005-2010 Mark A Lindner + + This file is part of libconfig. + + This library 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 library 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 library. If not, see <http://www.gnu.org/licenses/>. + ---------------------------------------------------------------------------- +*/ + +#include "strbuf.h" + +#include <string.h> +#include <stdlib.h> + +#define STRING_BLOCK_SIZE 64 + +/* ------------------------------------------------------------------------- */ + +char *strbuf_release(strbuf_t *buf) +{ + char *r = buf->string; + memset(buf, 0, sizeof(strbuf_t)); + return(r); +} + +/* ------------------------------------------------------------------------- */ + +void strbuf_append(strbuf_t *buf, const char *text) +{ + static const size_t mask = ~(STRING_BLOCK_SIZE - 1); + size_t len = strlen(text); + size_t newlen = buf->length + len + 1; /* add 1 for NUL */ + + if(newlen > buf->capacity) + { + buf->capacity = (newlen + (STRING_BLOCK_SIZE - 1)) & mask; + buf->string = (char *)realloc(buf->string, buf->capacity); + } + + strcpy(buf->string + buf->length, text); + buf->length += len; +} + +/* ------------------------------------------------------------------------- */ +/* eof */ diff --git a/3rdparty/libconfig/strbuf.h b/3rdparty/libconfig/strbuf.h new file mode 100644 index 000000000..90afd44c8 --- /dev/null +++ b/3rdparty/libconfig/strbuf.h @@ -0,0 +1,39 @@ +/* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files + Copyright (C) 2005-2010 Mark A Lindner + + This file is part of libconfig. + + This library 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 library 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 library. If not, see <http://www.gnu.org/licenses/>. + ---------------------------------------------------------------------------- +*/ + +#ifndef __libconfig_strbuf_h +#define __libconfig_strbuf_h + +#include <string.h> +#include <sys/types.h> + +typedef struct +{ + char *string; + size_t length; + size_t capacity; +} strbuf_t; + +char *strbuf_release(strbuf_t *buf); + +void strbuf_append(strbuf_t *buf, const char *text); + +#endif /* __libconfig_strbuf_h */ diff --git a/3rdparty/libconfig/wincompat.h b/3rdparty/libconfig/wincompat.h new file mode 100644 index 000000000..cfea2ec33 --- /dev/null +++ b/3rdparty/libconfig/wincompat.h @@ -0,0 +1,89 @@ +/* ---------------------------------------------------------------------------- + libconfig - A library for processing structured configuration files + Copyright (C) 2005-2010 Mark A Lindner + + This file is part of libconfig. + + This library 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 library 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 library. If not, see <http://www.gnu.org/licenses/>. + ---------------------------------------------------------------------------- +*/ + +#ifndef __wincompat_h +#define __wincompat_h + +#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) + +#ifdef _MSC_VER +#pragma warning (disable: 4996) +#endif + +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +#define snprintf _snprintf + +#ifndef __MINGW32__ +#define atoll _atoi64 +#define strtoull _strtoui64 +#endif /* __MINGW32__ */ + +#endif + +#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) \ + || defined(__MINGW32__)) + +/* Why does gcc on MinGW use the Visual C++ style format directives + * for 64-bit integers? Inquiring minds want to know.... + */ + +#define INT64_FMT "%I64d" +#define UINT64_FMT "%I64u" + +#define INT64_HEX_FMT "%I64X" + +#define FILE_SEPARATOR "\\" + +#else /* defined(WIN32) || defined(__MINGW32__) */ + +#define INT64_FMT "%lld" +#define UINT64_FMT "%llu" + +#define INT64_HEX_FMT "%llX" + +#define FILE_SEPARATOR "/" + +#endif /* defined(WIN32) || defined(__MINGW32__) */ + +#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) \ + && ! defined(__MINGW32__) + +#define INT64_CONST(I) (I ## i64) +#define UINT64_CONST(I) (I ## Ui64) + +#ifndef INT32_MAX +#define INT32_MAX (2147483647) +#endif + +#ifndef INT32_MIN +#define INT32_MIN (-2147483647-1) +#endif + +#else /* defined(WIN32) && ! defined(__MINGW32__) */ + +#define INT64_CONST(I) (I ## LL) +#define UINT64_CONST(I) (I ## ULL) + +#endif /* defined(WIN32) && ! defined(__MINGW32__) */ + +#endif /* __wincompat_h */ diff --git a/Makefile.in b/Makefile.in index 02ca9b987..6fd5fff26 100644 --- a/Makefile.in +++ b/Makefile.in @@ -4,10 +4,10 @@ HAVE_MYSQL=@HAVE_MYSQL@ ifeq ($(HAVE_MYSQL),yes) ALL_DEPENDS=common_sql login_sql char_sql map_sql tools import SQL_DEPENDS=common_sql login_sql char_sql map_sql import - COMMON_SQL_DEPENDS=mt19937ar - LOGIN_SQL_DEPENDS=mt19937ar common_sql - CHAR_SQL_DEPENDS=mt19937ar common_sql - MAP_SQL_DEPENDS=mt19937ar common_sql + COMMON_SQL_DEPENDS=mt19937ar libconfig + LOGIN_SQL_DEPENDS=mt19937ar libconfig common_sql + CHAR_SQL_DEPENDS=mt19937ar libconfig common_sql + MAP_SQL_DEPENDS=mt19937ar libconfig common_sql CONVERTERS_DEPENDS=common_sql else ALL_DEPENDS=needs_mysql @@ -47,6 +47,9 @@ common_sql: $(COMMON_SQL_DEPENDS) mt19937ar: @$(MAKE) -C 3rdparty/mt19937ar +libconfig: + @$(MAKE) -C 3rdparty/libconfig + login_sql: $(LOGIN_SQL_DEPENDS) @$(MAKE) -C src/login sql @@ -74,6 +77,7 @@ import: clean: @$(MAKE) -C src/common $@ @$(MAKE) -C 3rdparty/mt19937ar $@ + @$(MAKE) -C 3rdparty/libconfig $@ @$(MAKE) -C src/login $@ @$(MAKE) -C src/char $@ @$(MAKE) -C src/map $@ @@ -85,6 +89,7 @@ help: @echo "possible targets are:" @echo "'common_sql' - builds object files used in SQL servers" @echo "'mt19937ar' - builds object file of Mersenne Twister MT19937" + @echo "'libconfig' - builds object files of libconfig @echo "'login_sql' - builds login server (SQL version)" @echo "'char_sql' - builds char server (SQL version)" @echo "'map_sql' - builds map server (SQL version)" diff --git a/conf/atcommand_athena.conf b/conf/atcommand_athena.conf index ce06e2b37..58813c1c7 100644 --- a/conf/atcommand_athena.conf +++ b/conf/atcommand_athena.conf @@ -1,753 +1,60 @@ -//-------------------------------------------------------------- -// rAthena atcommand/charcommand Configuration File -//-------------------------------------------------------------- - -// The symbol that will be used to recognize commands. -// You can set any one character except control-characters (0x00-0x1f), -// '%', '$' (party/guild chat speaking) and '/' (standard client commands). -// command_symbol represents @commands used locally -// char_symbol represents #commands used on other players. -command_symbol:@ -char_symbol:# - -// The following settings in this file use the format "<command name>: level(@),level(#)". -// They define the minimum GM level required to execute the associated command. -// @ = atcommand. most work only on yourself. -// # = charcommand. remote usage only. GMs will be able to use these on other players. -// Adjust values as you like. Note that to activate commands for normal players, -// (GM level 0), you also need to change the 'atcommand_gm_only' option to 'no'. -// To completely disable a command, set its required GM level to 100. - -// Default levels were chosen so that they form the following hierarchy: -// 0: Normal player -// -> no commands accessible -// 1: Super player -// -> some minor advantage: storage, petrename, etc... -// 10: Super player+ -// -> more powerful commands, like mobsearch and changegm -// 20: Mediator -// -> GM commands for finding players and moving to them (also kicking them) -// 40: Sub-GM -// -> GM commands for basic tasks, no significant impact on other players -// 50: Sub-GM+ -// -> GM commands to spawn mobs and create guilds -// 60: GM -// -> almost all commands available (except administration and mass commands) -// 80: GM Chief -// -> can do anything, except administration commands -// 99: Administrator -// -> can do anything! -// 100: Disabled -// -> commands that will not be available to anyone - -// Syntax of file: -// command: @level,#level [<alias commands seperated by commas>] - -// Syntax Example: -// command: 40,40 [alias,alias2,alias3,alias4] -// If it has more than 4 aliases you can keep adding, just like in the example below: - -// Example: -// blvl: 60,60 [lvup,blevel,baselvl,baselvup,baselevel,baselvlup] - -//-------------------------- -// 0: normal player commands -// None for security purposes. - -//------------------------- -// 1: Super player commands - -// Displays a list of @ commands available to the player. -commands: 1,1 - -// Displays a list of # commands available to the player. -charcommands: 1,1 - -// Displays the server rates. -rates: 1,1 - -// Show server uptime since last map server restart -uptime: 1,1 - -// Shows/Hides the "there is a delay after a skill" message. -showdelay: 1,1 - -// Displays current levels and % progress. -exp: 1,40 - -// To change your (own) email -// note: this command doesn't check email itself, but check structure of the email (xxx@xxx) -// if you want be sure of each e-mail disable this option (value: 100) -email: 1,60 - -// Show Monster info (rates, stats, drops, MVP stuff) -monsterinfo: 1,1 [mobinfo, mi] - -// Show Item info (type, price, etc) -iteminfo: 1,1 [ii] - -// Show who drops an item (mobs with highest drop rate) -whodrops: 1,1 - -// Syncs the player's position on the client with the one stored on the server. -refresh: 1,40 - -// Give server time. (4 same commands) -time: 1,1 [date,serverdate,servertime] - -// Displays SVN version of the server. -version: 1,1 - -// Suicide your character. -die: 1,1 - -// Enables you to rename your pet. -petrename: 1,50 - -// Organize a new party, with you as the party leader -party: 1,1 - -// Opens your Kafra storage wherever you are -storage: 1,1 - -// Opens your mailbox -mail: 1,1 - -// Opens auctions window -auction: 1,1 - -// Locate someone on a map, returns your coordinates if the person isn't on. -where: 1,1 - -// Duel organizing commands -duel: 1,1 -invite: 1,1 -accept: 1,1 -reject: 1,1 -leave: 1,1 - -// Main chat -main: 1,1 - -// Autorejecting Deals/Invites -noask: 1,1 - -// Displays remaining jail time -jailtime: 1,40 - -// Homunculus commands for players -hominfo: 1,40 -homstats: 1,40 - -// Kill Steal Protection -noks: 1,1 - -// Set Font -font: 1,1 - -//--------------------------- -// 10: Super player+ commands - -// Displays/Hides Experience gained messages -showexp: 10,10 - -// Displays/Hides Zeny gained messages -showzeny: 10,10 - -// Warps you to predefined locations in major cities. -go: 10,10 - -// Enables/disables autolooting from killed mobs. -autoloot: 10,10 - -// Enables/disables autolooting an item. -alootid: 10,10 - -// Allows you continue vending offline. -autotrade: 10,10 [at] - -// Change Guild Master of your Guild -changegm: 10,10 - -// Change the leader of your party. -changeleader: 10,10 - -// Change the party exp- and item share rules. -partyoption: 10,10 - -// Command what the player's pet will say. -pettalk: 10,10 - -// Command what the player's homunculus will say. -homtalk: 10,10 - -// Locates and displays the position of a certain mob on the current map. -mobsearch: 10,10 -// Locates and displays the position of a certain mob on your mini-map -showmobs: 10,10 -// Prints out in which maps a monster normally spawns at (does not count script-invoked mobs) -whereis: 10,10 - -// Resets a Star Gladiator's marked maps -feelreset: 10,60 - -//---------------------- -// 20: Mediator commands - -// Displays helpfile in rAthena base directory (2 same commands). -help: 20,20 [h] -help2: 20,20 [h2] - -// Warp yourself to a person (3 same commands + /shift). -goto: 20,20 [jumpto,warpto] - -// Displays the motd file to all players -gmotd: 20,20 - -// Follow a player (including warping to them) -follow: 20,20 - -// Sends a request to all connected GMs (via the gm whisper system) -request: 20,100 - -// Disconnects a user from the server (1 command + right click menu for GM "(name) force to quit"). -kick: 20,20 - -// Changes your appearance. -model: 20,50 - -// To get a peco to (un)ride (2 same commands). -mount: 20,50 [mountpeco] - -// Returns list of logged in characters with their position (2 same commands). -who: 20,20 [whois] - -// Returns list of logged in characters with their job. -who2: 20,20 - -// Returns list of logged in characters with their party/guild. -who3: 20,20 - -// Returns list of logged in characters with their position in a specifical map. -whomap: 20,20 - -// Returns list of logged in characters with their job in a specifical map. -whomap2: 20,20 - -// Returns list of logged in characters with their party/guild in a specifical map. -whomap3: 20,20 - -// Displays GMs online. For those who are higher GM level than yourself, -// only the name is shown, for the rest, it displays the same info of -// @who+@who2+who3 -whogm: 20,20 - -// Change your appearence to other players to a mob. -disguise: 20,60 - -// Restore your normal appearance. -undisguise: 20,20 - -// Displays the text as a normal message with the format "*name message*" -// instead of "name : message" (Like the /me command in IRC) -me: 20,20 - -// Changes your name to your choice temporarily. -fakename: 20,50 - -// Changes your size. -size: 20,50 - -// Can command what other npcs (by name) can say. -npctalk: 20,100 [npctalkc] - -//-------------------- -// 40: Sub-GM commands - -// Broadcast to the whole server. Using (1 command + /nb, /b). -broadcast: 40,40 - -// Broadcast to the map you are on (1 command + /lb, /nlb). -localbroadcast: 40,40 - -// Broadcast (with or without name) -kami: 40,40 -// Same as kami but with blue color -kamib: 40,40 -// Same as kami but you can choose the color (uses different packet) -kamic: 40,40 - -// Enables GvG on a map (2 same commands). -gvgon: 40,100 [gpvpon] - -// Turns GvG (Guild vs. Guild) off on a map (2 same commands). -gvgoff: 40,100 [gpvpoff] - -// Activate/Deactivate kill steal protection on a map -allowks: 40,100 - -// Modifies your HP/SP. -heal: 40,60 - -// GM Hide (total invisibility to characters and monsters) (1 command + /hide). -hide: 40,60 - -// Changes your job to one you specify (2 same commands). -job: 40,60 [jobchange] - -// Enables you to to jump randomly on a map (that you are already on). -jump: 40,40 - -// Warps you to your last save point (2 same commands). -load: 40,60 [return] - -// Warps you to a specific npc -tonpc: 40,40 - -// Saves a warp point. -memo: 40,40 - -// Set your character display options. (Visual effects of your character) -option: 40,60 - -// Sets the level of intemecy of your pet. -petfriendly: 40,50 - -// Sets hunger level of your pet. -pethungry: 40,50 - -// Turns PvP (Person vs. Person) off on a map. -pvpoff: 40,100 - -// Enables PvP on a map. -pvpon: 40,100 - -// Permanently adds a quest skill -questskill: 40,60 - -// Permanently removes a quest skill -lostskill: 40,60 - -// Sets the speed you can walk/attack at. Default is 150. -speed: 40,60 - -// Summons spirit spheres around you. -spiritball: 40,60 - -// Warp yourself to a certain map, at (x,y) coordinates (2 same commands) + also /mm or /mapmove. -warp: 40,60 [rura,mapmove] - -// Changes GM clothes color (2 same commands) -dye: 40,50 [ccolor] - -// Changes GM hair style (2 same commands) -hairstyle: 40,40 [hstyle] - -// Changes GM hair color (2 same commands) -haircolor: 40,50 [hcolor] - -// Deletes all your items. -itemreset: 40,60 - -// Does a skill/stat reset. -reset: 40,60 - -// Displays distribution of players on the server per map (% on each map which has players) -users: 40,40 - -// Deletes floor items in your range of sight -cleanmap: 40,40 - -// Kill all monsters in map (without drops) -killmonster2: 40,40 - -// Sets your spawn point (aka save point). -save: 40,60 - -// Do some visual effect on your character -effect: 40,40 - -// Do some visual effect on your character (misceffect) -misceffect: 40,40 - -// GM's magnifier -identify: 40,40 - -// Drop all your items -dropall: 40,60 - -// Store all your items -storeall: 40,60 - -// Allow other players to hit you out of PvP -killable: 40,60 - -// Look up a skill by name -skillid: 40,40 - -// Use a skill by id -useskill: 40,40 - -// What skills are required to get this skill -skilltree: 40,40 - -// Marriage commands -marry: 40,40 -divorce: 40,40 - -// Adopt a novice into a family -adopt: 40,40 - -// Play a Sound! -sound: 40,40 - -// Displays a player's storage -storagelist: 40,40 - -// Displays a player's cart contents -cartlist: 40,40 - -// Displays a player's items -itemlist: 40,40 - -// Displays a player's stats -stats: 40,40 - -//--------------------- -// 50: Sub-GM+ commands - -// Creates a new guild, with you as the guildmaster. -guild: 50,50 - -// Brings up your guild storage wherever you are. -gstorage: 50,60 - -// Spawns a monster, and a certain amount (2 same commands + /monster). -monster: 50,50 [spawn] - -// Spawns a smaller sized version of a monster. -monstersmall: 50,50 - -// Spawns a larger sized version of a monster. -monsterbig: 50,50 - -// Spawns mobs that treat you as their master (they disappear after some time) -summon: 50,50 - -// It will spawn a supportive clone of the given player. -clone: 50,50 - -// It will spawn a supportive clone of the given player that follows the creator around. -slaveclone: 50,50 - -// It will spawn an aggresive clone of the given player. -evilclone: 50,50 - -//---------------- -// 60: GM commands - -// Add or Remove Cash Points to/from yourself -cash: 60,60 - -// Add or Remove Kafra Points to/from yourself -points: 60,60 - -// Starts Guild Wars -agitstart: 60,100 - -// Ends Guild Wars -agitend: 60,100 - -// Resurects yourself. -alive: 60,60 - -// Raises your base level by specified amount (7 same commands). -blvl: 60,60 [lvup,blevel,baselvl,baselvup,baselevel,baselvlup] - -// Raises your job level by specified amount (6 same commands). -jlvl: 60,60 [jlevel,joblvl,joblvup,joblevel,joblvlup] - -// Changes the sex of yourself -changesex: 60,60 - -// Raises your guild level by specified amount (6 same commands). -glvl: 60,60 [glevel,guildlvl,guildlvup,guildlevel,guildlvlup] - -// Find an itemID based on item name -idsearch: 60,60 - -// Creates an item of your choosing, either Item ID or Name (1 command + /item). -item: 60,60 - -// Creates a complet item (card, etc...) of your choosing, either Item ID or Name. -item2: 60,60 - -// Deletes an item of your choosing, either Item ID or Name. -delitem: 60,60 - -// Kill another character without hitting them. -kill: 60,60 - -// Kill all monsters in map (with drops) -killmonster: 60,60 - -// Creates yourself a pet egg. -makeegg: 60,60 - -// Hatches an egg -hatch: 60,60 - -// Instantly kills player whose name is entered and deals insane damage to everything around -nuke: 60,60 - -// Enable hitting a player even when not in PvP -killer: 60,60 - -// Creates weapon of desired element. -produce: 60,60 - -// Warps a character to you (1 command + /recall). -recall: 60,60 - -// Refines all weapons in your items list. -refine: 60,80 - -// Will repair all broken items in inventory. -repairall: 60,60 - -// Change Status of your character -str: 60,60 -agi: 60,60 -vit: 60,60 -int: 60,60 -dex: 60,60 -luk: 60,60 - -// Gives all skills -allskill: 60,60 [allskills,skillall,skillsall] - -// Sets GM stats to maximum -allstats: 60,60 [allstat,statall,statsall] - -// Gives you stat points. -stpoint: 60,60 - -// Gives you skill points of desired amount. -skpoint: 60,60 - -// Warps all online character of a guild to you. (at least one member of that guild must be on.) -guildrecall: 60,60 - -// Warps all online character of a party to you. -// (at least one party member must be online.) -partyrecall: 60,60 - -// Allows you to spy on any Guilds Guild chat. -// (at least one member of that guild must be on.) -// NOTE: map server needs to be configured to enable spying to use this command (enable_spy: yes) -guildspy: 60,60 - -// Allows you to spy on any party's party chat. -// (at least one party member must be online.) -// NOTE: map server needs to be configured to enable spying to use this command (enable_spy: yes) -partyspy: 60,60 - -// Gives you zeny (or subtracts, if amount is negative) -zeny: 60,80 - -// Block a player indefinitely -block: 60,100 [charblock] - -// Unblock a player -unblock: 60,100 [charunblock] - -// Ban a player for a limited time -ban: 60,100 [banish,charban,charbanish] - -// Unban a player -unban: 60,100 [unbanish,charunban,charunbanish] - -// To send specified character in jails -jail: 60,100 - -// To discharge a jailed character (2 same commands) -unjail: 60,100 [discharge] - -// Timed jailing -jailfor: 60,60 - -// Create a static warp portal that lasts until the next reboot -addwarp: 60,60 - -// Open a trade window with any player -trade: 60,60 - -// Changes the player's appearance (headgear) -changelook: 60,60 - -// Homunculus commands for GMs -hlvl: 60,60 [homlevel,hlevel,homlvl,homlvup] -homevolve: 60,60 [homevolution] -makehomun: 60,60 -homfriendly: 60,60 -homhungry: 60,60 -// Re-calculates stats, as if the homun was sent back to level 1 and re-leveled -homshuffle: 60,60 - -// WoE 2 start/stop commands -agitstart2: 60,100 -agitend2: 60,100 - -// Resets player stats -streset: 60,60 - -// Resets player skills -skreset: 60,60 - -//---------------------- -// 80: GM Chief commands - -// Set the server to day. -day: 80,100 - -// Set the server to night. -night: 80,100 - -// Kills everyone on the server. -doom: 80,100 - -// Kills everyone on the map you are on. -doommap: 80,80 - -// Recalls Everyone To Your Coordinates -recallall: 80,80 - -// Revives all players on the map. -raisemap: 80,80 - -// Revives all players on the server. -raise: 80,100 - -// Hides a NPC. -hidenpc: 80,100 - -// Unhides a NPC. -shownpc: 80,100 - -// Loads an NPC script by path -loadnpc: 80,100 - -// Unloads a NPC -unloadnpc: 80,100 - -// Move a NPC -npcmove: 80,100 - -// turn skills on for a map -skillon: 80,100 - -// turn skills off for a map -skilloff: 80,100 - -// Mute a player (prevents talking, usage of skills and commands) -mute: 80,100 - -// Unmute a player -unmute: 80,100 - -//--------------------------- -// 99: Administrator commands - -// Disconnect all users from the server -kickall: 99,100 - -// Closes Map-Server -mapexit: 99,100 - -// Used for testing packet sends from the client (debug function) -send: 99,100 - -// Give information about terrain/area (debug function) -gat: 99,100 - -// Displays a status change without really applying it (debug function) -displaystatus: 99,100 - -// Displays the animation of a skill without really using it (debug function) -displayskill: 99,100 - -// Shows information about the map -mapinfo: 99,100 - -// Set Map Flags -mapflag: 99,100 - -// Re-load item database (admin command) -reloaditemdb: 99,100 - -// Re-load monsters database (admin command) -reloadmobdb: 99,100 - -// Re-load skills database (admin command) -reloadskilldb: 99,100 - -// Re-load scripts (admin command) -reloadscript: 99,100 - -// Change a battle_config flag without rebooting server -setbattleflag: 99,100 - -// Re-load gm command config (admin command) -reloadatcommand: 99,100 - -// Re-load battle config (admin command) -// Note that some player config settings won't take effect until relog -// (display exp, display zeny, display skill delay fail, ...) -reloadbattleconf: 99,100 - -// Re-load status database (admin command) -reloadstatusdb: 99,100 - -// Re-load player info database (admin command) -reloadpcdb: 99,100 - -// Re-load the Message of the Day (admin command) -reloadmotd: 99,100 - -// Changes the GM level of another character -// (lasts until reboot, or gm list reload) -adjgmlvl: 99,100 - -// Changes the required GM level of an @ command -// (effect lasts until restart or command reload) -adjcmdlvl: 99,100 - -// [Un]Disguise All Players (admin command) -disguiseall: 99,100 -undisguiseall: 99,100 - -// Mutes every player on screen (admin command) -mutearea: 99,100 [stfu] - -// Makes you immune to attacks (monsters/players/skills cannot target/hit you, admin command) -battleignore: 99,100 [monsterignore] - -//--------------------------------------------------------------- -// 99: Weather effects -snow: 99,100 -clouds: 99,100 -clouds2: 99,100 -fog: 99,100 -fireworks: 99,100 -sakura: 99,100 -leaves: 99,100 - -// Stop all weather effects -clearweather: 99,100 - -//--------------------------------------------------------------- -// 100: Disabled commands - -//--------------------- -// OTHER: not a command -import:conf/import/atcommand_conf.txt
\ No newline at end of file +/* Atcommands and charcommands configuration file */ + +/* The symbol that will be used to recognize commands. +You can set any one character except: + - control-characters (0x00-0x1f), + - '%' (party chat symbol) + - '$' (guild chat symbol) + - '/' (client commands symbol) +atcommand_symbol represents @commands used locally. +charcommand_symbol represents #commands used on other players. +*/ + +atcommand_symbol : "@" +charcommand_symbol: "#" + +/* Command aliases +You can define aliases for any command. Aliases work just like original +command. +Format is + <commandname>: ["<alias>", ...] +*/ + +aliases: { + mobinfo: ["monsterinfo", "mi"] + iteminfo: ["ii"] + time: ["date", "serverdate", "servertime"] + autotrade: ["at"] + help: ["h"] + jumpto: ["goto", "warpto"] + mount: ["mountpeco"] + who: ["whois"] + npctalk: ["npctalkc"] + gvgon: ["gpvpon"] + gvgoff: ["gpvpoff"] + jobchange: ["job"] + load: ["return"] + warp: ["rura", "mapmove"] + dye: ["ccolor"] + hairstyle: ["hstyle"] + haircolor: ["hcolor"] + monster: ["spawn"] + blvl: ["lvup", "blevel", "baselvl", "baselvup", "baselevel", "baselvlup"] + jlvl: ["jlevel", "joblvl", "joblvup", "joblevel", "joblvlup"] + glvl: ["glevel", "guildlvl", "guildlvup", "guildlevel", "guildlvlup"] + allskill: ["allskills", "skillall", "skillsall"] + allstats: ["allstat", "statall", "statsall"] + ban: ["banish"] + unban: ["unbanish"] + unjail: ["discharge"] + homlevel: ["hlvl", "hlevel", "homlvl", "homlvup"] + homevolution: ["homevolve"] + mutearea: ["stfu"] + monsterignore: ["battleignore"] + raise: ["revive"] +} + +/* Commands help file */ +help: { + @include "conf/help.txt" +}
\ No newline at end of file diff --git a/conf/battle/gm.conf b/conf/battle/gm.conf index b7dc81909..fe07a6fc4 100644 --- a/conf/battle/gm.conf +++ b/conf/battle/gm.conf @@ -18,97 +18,10 @@ atcommand_slave_clone_limit: 25 // current map server. partial_name_scan: yes -// The level at which a player with access is considered a GM. -// An account with an access level lower than this is not effected -// by gm_can_drop_lv (battle_athena.conf). -lowest_gm_level: 1 - -// [GM] Can use all skills? (No or mimimum GM level) -gm_all_skill: no - -// [GM] Can equip anything? (No or minimum GM level, can cause client errors.) -gm_all_equipment: no - -// [GM] Can use skills without meeting the required conditions (items, etc...)? -// 'no' or minimum GM level to bypass requirements. -gm_skill_unconditional: no - -// [GM] Can join a password protected chat? (No or mimimum GM level) -gm_join_chat: no - -// [GM] Can't be kicked from a chat? (No or mimimum GM level) -gm_kick_chat: no - -// (@) GM Commands available only to GM's? (Note 1) -// set to 'No', Normal players (gm level 0) can use GM commands _IF_ you set the command level to 0. -// set to 'Yes', Normal players (gm level 0) can never use a GM command even if you set the command level to 0. -atcommand_gm_only: no - // (@) @allstats/@str/@agi/@vit/@int/@dex/@luk // allow gms to bypass the maximum stat parameter? ( if yes gm stats can go up to 32k ) default: no atcommand_max_stat_bypass: no -// Is the character of a GM account set as the object of a display by @ command etc. or not? -hide_GM_session: no - -// At what GM level can you see GMs and Account/Char IDs in the @who command? -who_display_aid: 40 - // Ban people that try trade dupe. // Duration of the ban, in minutes (default: 5). To disable the ban, set 0. ban_hack_trade: 5 - -// Set here minimum level of a (online) GM that can receive all informations about any player that try to hack, spoof a name, etc. -// Values are from 0 to 100. -// 100: disable information -// 0: send to any people, including normal players -// default: 60, according to GM definition in atcommand_athena.conf -hack_info_GM_level: 60 - -// The minimum GM level to bypass nowarp and nowarpto mapflags. -// This option is mainly used in commands which modify a character's -// map/coordinates (like @memo, @warp, @charwarp, @go, @jump, etc...). -// default: 20 (first level after normal player or super'normal' player) -any_warp_GM_min_level: 20 - -// The minimum level for a GM to be unable to distribute items. -// You should set this to the same level @item is set to in the atcommand.conf -// NEVER SET THIS VALUE TO 0, or you will block drop/trade for normal players -gm_cant_drop_min_lv: 1 - -//The trust level for your GMs. Any GMs ABOVE this level will be able to distribute items -//ie: Use Storage/Guild Storage, Drop Items, Use Vend, Trade items. -gm_cant_drop_max_lv: 0 - -// Minimum GM level to see the hp of every player? (Default: 60) -// no/0 can be used to disable it. -disp_hpmeter: 0 - -// Minimum GM level to view players equip regardless of their setting. -// (Default: 0 = Disabled). -gm_viewequip_min_lv: 0 - -// Can GMs invite non GMs to a party? (Note 1) -// set to 'No', GMs under the party invite trust level may not invite non GMs to a party. -// set to 'Yes', All GMs can invite any player to a party. -// Also, as long as this is off, players cannot invite GMs to a party as well. -gm_can_party: no - -//The trust level for GMs to invite to a party. Any GMs ABOVE OR EQUAL TO this level will be able to invite normal -//players into their party in addittion to other GMs. (regardless of gm_can_party) -gm_cant_party_min_lv: 20 - -// Players Titles (check msg_athena.conf for title strings) -// You may assign different titles for your Players and GMs -title_lvl1: 1 -title_lvl2: 10 -title_lvl3: 20 -title_lvl4: 40 -title_lvl5: 50 -title_lvl6: 60 -title_lvl7: 80 -title_lvl8: 99 - -// Minimum GM level required for client command /check (display character status) to work. -// Default: 60 -gm_check_minlevel: 60 diff --git a/conf/char_athena.conf b/conf/char_athena.conf index bc9e1ab1c..1b5e96a16 100644 --- a/conf/char_athena.conf +++ b/conf/char_athena.conf @@ -93,8 +93,10 @@ char_new_display: 0 // Maximum users able to connect to the server. Set to 0 for unlimited. max_connect_user: 0 -// Minimum GM level that is allowed to bypass the server limit of users. -gm_allow_level: 99 +// Group ID that is allowed to bypass the server limit of users. +// Default: -1 = nobody (there are no groups with ID < 0) +// See: conf/groups.conf +gm_allow_group: -1 // How often should the server save all files? (In seconds) // Note: Applies to all data files on TXT servers. diff --git a/conf/groups.conf b/conf/groups.conf new file mode 100644 index 000000000..d93d2aa09 --- /dev/null +++ b/conf/groups.conf @@ -0,0 +1,274 @@ +/* + +Player groups configuration file +--------------------------------- + +This file defines "player groups" and their privileges. + +Each group has its id and name, lists of available commands and other +permissions, and a list of other groups it inherits from. + + +Group settings +-------------- +<id> +Unique group number. The only required field. + +<name> +Any string. If empty, defaults to "Group <id>". It is used in several @who +commands. + +<level> +Equivalent of GM level, which was used in revisions before r xxxxx. You can +set it to any number, but usually it's between 0 (default) and 99. Members of +groups with lower level can not perform some actions/commands (like @kick) on +members of groups with higher level. It is what script command getgmlevel() +returns. Group level can also be used to override trade restrictions +(db/item_trade.txt). + +<commands> +A group of settings + <command name> : <bool> +or + <commandname> : [ <bool>, <bool> ] +First boolean value is for atcommand, second one for charcommand. If set to +true, group can use command. If only atcommand value is provided, false is +assumed for charcommand. If a command name is not included, false is assumed for +both atcommand and charcommand. +For a full list of available commands, see: doc/atcommands.txt. +Command names must not be aliases. + +<log_commands> +Boolean value. If true then all commands used by the group will be logged to +atcommandlog. If setting is omitted in a group definition, false is assumed. +Requires 'log_commands' to be enabled in 'conf/log_athena.conf'. + +<permissions> +A group of settings + <permission> : <bool> +If a permission is not included, false is assumed. +For a full list of available permissions, see: doc/permissions.txt + +<inherit> +A list of group names that given group will inherit commands and permissions +from. Group names are case-sensitive. + +Inheritance results +------------------- +Both multiple inheritance (Group 2 -> Group 1 and Group 3 -> Group 1) and +recursive inheritance (Group 3 -> Group 2 -> Group 1) are allowed. + +Inheritance rules should not create cycles (eg Group 1 inherits from Group 2, +and Group inherits from Group 1 at the same time). Configuration with cycles is +considered faulty and can't be processed fully by server. + +Command or permission is inherited ONLY if it's not already defined for the +group. +If group inherits from multiple groups, and the same command or permission is +defined for more than one of these groups, it's undefined which one will be +inherited. + +Syntax +------ +This config file uses libconfig syntax: +http://www.hyperrealm.com/libconfig/libconfig_manual.html#Configuration-Files + + +Upgrading from revisions before XXXXX +------------------------------------- +<forum link> +*/ + +groups: ( +{ + id: 0 /* group 0 is the default group for every new account */ + name: "Player" + level: 0 + inherit: ( /*empty list*/ ) + commands: { + /* no commands by default */ + } + permissions: { + /* without this basic permissions regular players could not + trade or party */ + can_trade: true + can_party: true + } +}, +{ + id: 1 + name: "Super Player" + inherit: ( "Player" ) /* can do everything Players can and more */ + level: 0 + commands: { + /* informational commands */ + commands: true + charcommands: true + help: true + rates: true + uptime: true + showdelay: true + exp: true + mobinfo: true + iteminfo: true + whodrops: true + time: true + jailtime: true + hominfo: true + homstats: true + showexp: true + showzeny: true + whereis: true + /* feature commands */ + refresh: true + noask: true + noks: true + main: true + autoloot: true + alootid: true + autotrade: true + request: true + go: true + } + permissions: { + } +}, +{ + id: 2 + name: "Support" + inherit: ( "Super Player" ) + level: 1 + commands: { + version: true + where: true + jumpto: true + who: true + who2: true + who3: true + whomap: true + whomap2: true + whomap3: true + users: true + broadcast: true + localbroadcast: true + } + log_commands: true + permissions: { + receive_requests: true + view_equipment: true + } +}, +{ + id: 3 + name: "Script Manager" + inherit: ( "Support" ) + level: 1 + commands: { + tonpc: true + hidenpc: true + shownpc: true + loadnpc: true + unloadnpc: true + npcmove: true + addwarp: true + } + log_commands: true + permissions: { + any_warp: true + } +}, +{ + id: 4 + name: "Event Manager" + inherit: ( "Support" ) + level: 1 + commands: { + monster: true + monstersmall: true + monsterbig: true + killmonster2: true + cleanmap: true + item: [true, true] + zeny: [true, true] + disguise: [true, true] + undisguise: [true, true] + size: [true, true] + raise: true + raisemap: true + day: true + night: true + skillon: true + skilloff: true + pvpon: true + pvpoff: true + gvgon: true + gvgoff: true + allowks: true + me: true + marry: true + divorce: true + } + log_commands: true + permissions: { + can_trade: false + any_warp: true + } +}, +{ + id: 10 + name: "Law Enforcement" + inherit: ( "Support" ) + level: 2 + commands: { + hide: true + follow: true + kick: true + disguise: true + fakename: true + option: true + speed: true + warp: true + kill: true + recall: true + ban: true + block: true + jail: true + jailfor: true + mute: true + storagelist: true + cartlist: true + itemlist: true + stats: true + } + log_commands: true + permissions: { + join_chat: true + kick_chat: true + hide_session: true + who_display_aid: true + hack_info: true + any_warp: true + view_hpmeter: true + } +}, +{ + id: 99 + name: "Admin" + level: 99 + inherit: ( "Support", "Law Enforcement" ) + commands: { + } + log_commands: true + permissions: { + can_trade: true + can_party: true + all_skill: true + all_equipment: true + skill_unconditional: true + use_check: true + use_changemaptype: true + all_commands: true + } +} +) + diff --git a/conf/help.txt b/conf/help.txt index 13a958798..5a8f5871f 100644 --- a/conf/help.txt +++ b/conf/help.txt @@ -1,172 +1,230 @@ -// put at first, the minimum level to display the line - 1:To use one command, type it inside the message window where you usually type to chat. - 20:@h/@help - display this help guide. - 20:@h2/@help2 - displays the second help guide. - 1: - 1:--- MESSAGE CMD --- - 1:@main [on|off|message] - Turns on or off global chat (@main must be on to see global chat messages) - 1:@noask - Auto rejects Deals/Invites - 20:@gmotd - Broadcasts the Message of The Day file to all players. - 20:@me <message> - Displays normal text as a message in this format: *name message* (like /me in mIRC) - 20:@fakename [Name] - Changes your name to your choice temporarly. - 20:@npctalk [NPC Name],[Message] - Forces a NPC to display a message in normal chat. - 40:/b/@broadcast <message> - Broadcasts a GM message with name of the GM (in yellow) - 40:/nb <message>/@kami <message> - Broadcasts a GM message without name of the GM (in yellow) - 40:@kamib <message> - Broadcasts a GM message without name of the GM (in blue) - 40:/lb/@localbroadcast <message> - Broadcasts a GM message with name of the GM (in yellow) ONLY on your map - 40:/nlb <message> - Broadcasts a GM message without name of the GM (in yellow) ONLY on your map - 1: - 1:--- INFORMATION CMD --- - 1:@commands - Displays a list of commands that you can use. - 1:@rates - Displays the server's current rates. - 1:@uptime - Displays how long the server has been online. - 1:@showdelay - Shows/Hides the "there is a delay after this skill" message. - 1:@exp - Displays current levels and % progress - 1:@mobinfo/@monsterinfo/@mi [Mob ID|Part of monster name] - Shows Monster Info (rates, stats, drops, MVP stuff) - 1:@iteminfo/@ii [Item ID|Part of item name] - Shows Item info (type, price, etc) - 1:@whodrops [Item ID|Part of item name] - Shows who drops an item (mobs with highest drop rates) - 1:@version - Displays SVN version of the server - 1:@email <actual@email> <new@email> - to change your e-mail (characters protection) - 1:@where [char name] - Tells you the location of a character - 1:@time/@date/@server_date/@serverdate/@server_time/@servertime - Display the date/time of the server - 10:@showexp - Displays/Hides Experience gained. - 10:@showzeny - Displays/Hides Zeny gained. - 10:@mobsearch [Mob ID|Monster Name] - Shows the location of a certain mob on the current map. - 20:@who/@whois/@w [match_text] - Display a listing of who is online and their party/guild. - 20:@who2 [match_text] - Display a listing of who is online and their job. - 20:@who3 [match_text] - Display a listing of who is online and where. - 20:@whomap/@whomap2/@whomap3 [map] - like @who/@who2/@who3 but only for specifical map. - 20:@whogm [match_text] - Like @who+@who2+who3, but only for GM. - 40:@charcartlist <char name> - Displays all items of a player's cart. - 60: - 60:@guildspy <guild_name/id> - You will receive all messages of the guild channel (Chat logging must be enabled) - 60:@partyspy <party_name/id> - You will receive all messages of the party channel (Chat logging must be enabled) - 99:@mapinfo [<0-3> [map]] - Give information about a map (general info +: 0: no more, 1: players, 2: NPC, 3: shops/chat). - 1: - 1:--- CHANGE GM STATE CMD --- - 1:@die - Kills yourself - 10:@go <number/city_name> - Warps you to a city. - 10: -3: (Memo point 2) 1: morocc 5: izlude 9: yuno 13: niflheim - 10: -2: (Memo point 1) 2: geffen 6: aldebaran 10: amatsu 14: louyang - 10: -1: (Memo point 0) 3: payon 7: xmas (lutie) 11: gonryun 15: start point - 10: 0: prontera 4: alberta 8: comodo 12: umbala 16: prison/jail - 10: - 20:/shift/@jumpto/@warpto/@goto <char name> - Warps you to selected character - 20:@follow <char_name> - follow a player - 20:@mountpeco - Give/remove you a peco (Class is required, but not skill) - 20:@disguise <monster_name_or_monster_ID> - Change your appearence to other players to a mob. - 20:@undisguise - Restore your normal appearance. - 20:@model <hair ID: 0-17> <hair color: 0-8> <clothes color: 0-4> - Changes your characters appearence. - 20:@size <1-3> Changes your size (1-Smallest 2-Biggest 3-Normal) - 40:/hide/@hide - Makes you character invisible (GM invisibility). Type /hide or@hide again become visible. - 40:@save - Sets respawn point to current spot - 40:@load/@return - Warps you to your save point - 40:/mm//mapmove/@warp/@rura/@mapmove <mapname> <x> <y> - Warps you to the selected position - 40:@jump [x [y]]- Randomly warps you like a flywing. - 40:@job/@jobchange <job ID> - Changes your job - 40: 0: Novice 18: Alchemist 4015: Paladin - 40: 1: Swordman 19: Bard 4016: Champion - 40: 2: Mage 20: Dancer 4017: Professor - 40: 3: Archer 23: Super Novice 4018: Stalker - 40: 4: Acolyte 4001: High Novice 4019: Creator - 40: 5: Merchant 4002: High Swordman 4020: Clown - 40: 6: Thief 4003: High Mage 4021: Gypsy - 40: 7: Knight 4004: High Archer 4046: Taekwon - 40: 8: Priest 4005: High Acolyte 4047: Star Gladiator - 40: 9: Wizard 4006: High Merchant 4049: Soul Linker - 40: 10: Blacksmith 4007: High Thief 24: Gunslinger - 40: 11: Hunter 4008: Lord Knight 25: Ninja - 40: 12: Assassin 4009: High Priest - 40: 14: Crusader 4010: High Wizard - 40: 15: Monk 4011: Whitesmith - 40: 16: Sage 4012: Sniper - 40: 17: Rogue 4013: Assassin Cross - 40: ---- Baby Classes ---- - 40: 4023: Baby 4024: Baby Swordman 4025: Baby Mage - 40: 4026: Baby Archer 4027: Baby Acolyte 4028: Baby Merchant - 40: 4029: Baby Thief 4030: Baby Knight 4031: Baby Priest - 40: 4032: Baby Wizard 4033: Baby Blacksmith 4034: Baby Hunter - 40: 4035: Baby Assassin 4037: Baby Crusader 4038: Baby Monk - 40: 4039: Baby Sage 4040: Baby Rogue 4041: Baby Alchemist - 40: 4042: Baby Bard 4043: Baby Dancer 4045: Super Baby - 40: - 40: <param1> <param2> <p3>(stackable) <param3> <param3> - 40: 1 Petrified (stackable) 01 Sight 32 Peco Peco riding 2048 Orc Head - 40: 2 Frozen 01 Poison 02 Hide 64 GM Perfect Hide 4096 Wedding Sprites - 40: 3 Stunned 02 Cursed 04 Cloak 128 Level 2 Cart 8192 Ruwach - 40: 4 Sleeping 04 Silenced 08 Level 1 Cart 256 Level 3 Cart - 40: 6 darkness 08 ??? 16 Falcon 512 Level 4 Cart - 40: 16 darkness 1024 Level 5 Cart - 40: - 40:@heal [<HP> <SP>] - Heals the desired amount of HP and SP. No value specified will do a full heal. - 40:@option <param1> <param2> <param3> - Adds different visual effects on or around your character - 40:@dye/@ccolor <clothes color: 0-4> - Changes your characters appearence (only clothes color). - 40:@hairstyle/@hstyle <hair ID: 0-17> - Changes your characters appearence (only hair style). - 40:@haircolor/@hcolor <hair color: 0-8> - Changes your characters appearence (only hair color). - 40:@speed <1-1000> - Changes you walking speed. 1 being the fastest and 1000 the slowest. Default 150. - 40:@effect <effect_id> [flag] - Give an efect to your character. - 40:@dropall - throws all your possession on the ground - 40:@storeall - puts all your possessions in storage - 40:@killable - make your character killable - 40:@memo [memo_position] - set/change a memo location (no position: display memo points). - 40:@spiritball <number: 1-1000> - Gives you "spirit spheres" like from the skill "Call Spirits" - 40: (If the number you use is > 1000, your server may become instable or crash) - 40:@questskill <#> - Gives you the specified quest skill - 40:@lostskill <#> - Takes away the specified quest skill from you - 40:@skillid <name> - look up a skill by name - 40:@useskill <skillid> <skillv> <target> - use a skill on target - 40: Novice Swordsman Thief Merchant - 40: 142 = Emergency Care 144 = Moving HP Recovery 149 = Throw Sand 153 = Cart Revolution - 40: 143 = Act dead 145 = Attack Weak Point 150 = Back Sliding 154 = Change Cart - 40: Archer 146 = Auto Berserk 151 = Take Stone 155 = Crazy Uproar/Loud Voice - 40: 147 = Arrow Creation Acolyte 152 = Stone Throw Magician - 40: 148 = Charge Arrows 156 = Holy Light 157 = Energy Coat - 40: @skilltree < - 40: @marry <player1>,<player2> - marry two players - 40: @divorce <player> - divorces the two players (you need just one name of them) - 60:@alive - Revives yourself from death - 60:@lvup/@blevel/@baselvlup <number of levels> - Raises your base level the desired number of levels. The max is 255 (User Defined). - 60:@joblvup/@jlevel/@joblvlup <number of levels> -Raises your job level the desired number of levels. The max is 50 For Basic Classes. For Super Novice and Advanced Classes it is 70. - 60:@allskill/@allskills/@skillall/@skillsall - Give you all skills. - 60:@stpoint <number of points> - Gives you the desired number of stat points. - 60:@skpoint <number of points> - Gives you the desired number of skill points. - 60:@zeny <amount> - Gives you desired amount of Zeny. - 60:@cash <amount> - Gives you the specified amount of cash points. - 60:@points <amount> - Gives you the specified amount of Kafra Points. - 60:@str,@agi,@vit,@int,@dex,@luk <amount> - Adds desired amount to any stat. For example "@str 10" raises your str by 10 - 60:@statall/@statsall/@allstats/@allstat [value] - Adds value in all stats (maximum if no value). - 60: @addwarp <map name> <x coord> <y coord> - 40: - 40:--- MONSTERS CMD --- - 40:@killmonster2 - kill all monsters of your map (without drops) - 50:/monster <monster_name> - Spawns 1 of the desired monster. - 50:@spawn/@monster/@summon <monster_name_or_monster_ID> [<number to spawn> [<desired_monster_name> [<x coord> [<y coord>]]]] - 50:@monster2 <desired_monster_name> <monster_name_or_monster_ID> [<number to spawn> [<x coord> [<y coord>]]] - 50:@spawn/@monster/@summon/@monster2 "desired monster name" <monster_name_or_monster_ID> [<number to spawn> [<x coord> [<y coord>]]] - 50:@spawn/@monster/@summon/@monster2 <monster_name_or_monster_ID> "desired monster name" [<number to spawn> [<x coord> [<y coord>]]] - 50: Spawns the desired monster with any desired name. - 50:@monstersmall [Mob ID|Mob Name] - Spawns a smaller version of a monster. - 50:@monsterbig [Mob ID|Mob Name] - Spawns a larger version of a monster. - 60:@killmonster [map] - kill all monsters of the map (they drop) - 40: - 10:--- MISC CMD --- - 10:@autoloot [on|off|#] - Makes items go straight into your inventory. - 10:@autotrade/@at - Allows you to vend while you are offline. - 10:@changegm [Player Name] - Changes the leader of your guild (You must be guild leader) - 10:@changeleader [Player Name] - Changes the leader of your party (You must be party leader) - 20:@request [Message] - Sends a message to all connected GMs (via the gm whisper system) - 40:@sound [Path way to file in Data or GRF file] - Plays a sound from the data or grf file located on the client. - 50:@clone [Player Name] - Spawns a supportive clone of the given player. - 50:@slaveclone [Player Name] - Spawns a supportive clone of the given player that follows the creator around. - 50:@evilclone [Player Name] - Spawns an agressive clone of the given player. - 60:@changesex - Changes your gender. - 10: - 1:--- DUEL CMD --- - 1:@duel - Starts a duel. - 1:@invite - Invites a player to a duel. - 1:@accept - Accepts an invitation to a duel. - 1:@reject - Rejects an invitation to a duel. - 1:@leave - Leaves a duel. - 1: - 1:--- MAIL SYSTEM --- (SQL Only) - 1:@mail - Open mail box. +// This is help file that contains help messages for atcommands/charcommands. + +// Format: +// <command>: "<help message>" + +// This file uses libconfig syntax. + +help: "Params: <command>\n" "Shows help for specified command." +main: "Params: [on|off|<message>]\n" "Turns on or off main (server-wide) chat. Sends message to main chat." +noask: "Auto rejects deals/invites." +gmotd: "Broadcasts the Message of The Day to all players." +me: "Params: <message>\n" "Displays normal text as a message in this format: *name message* (like /me in mIRC)." +fakename: "Params: <name>\n" "Changes your name to your choice temporarily." +npctalk: "Params: <NPC name> <message>\n" "Forces a NPC to display a message in normal chat." +broadcast: "Params: <message>\n" "Broadcasts a message with your name (in yellow)." +kami: "Params: <message>\n" "Broadcasts a message without your name (in yellow)." +kamib: "Params: <message>\n" "Broadcasts a message without your name (in blue)." +localbroadcast: "Params: <message>\n" "Broadcasts a message with your name (in yellow) only on your map." +commands: "Displays a list of commands that you can use." +rates: "Displays the server's current rates." +uptime: "Displays how long the server has been online." +showdelay: "Shows/hides the \"There is a delay after this skill\" message." +exp: "Displays current levels and % progress." +mobinfo: "Params: <monster ID>|<monster name>\n" "Shows monster info (stats, exp, drops etc)." +iteminfo: "Params: <item ID>|<item name>\n" "Shows item info (type, price etc)." +whodrops: "Params: <item ID>|<item name>\n" "Shows who drops an item (monster with highest drop rates)." +version: "Displays SVN version of the server." +email: "Params: <current email> <new email>\n" "Changes your account e-mail address." +where: "Params: <char name>\n" "Tells you the location of a character." +time: "Shows the date and time of the server." +showexp: "Displays/hides experience gained." +showzeny: "Displays/hides Zeny gained." +mobsearch: "Params: <monster ID>|<monster name>\n" "Shows the location of a certain mob on the current map." +who: "Params: [<name>]\n" "Shows a list of online players and their party and guild." +who2: "Params: [<name>]\n" "Shows a list of online players and their job." +who3: "Params: [<name>]\n" "Shows a list of online players and their location." +whomap: "@whomap/@whomap2/@whomap3 [map] - like @who/@who2/@who3 but only for specifical map." +whogm: "Params: [match_text] - Like @who+@who2+who3, but only for GM." +guildspy: "Params: <guild_name/id> - You will receive all messages of the guild channel (Chat logging must be enabled)" +partyspy: "@partyspy <party_name/id> - You will receive all messages of the party channel (Chat logging must be enabled)" +mapinfo: "Params: [<0-3> [map]] - Give information about a map (general info +: 0: no more, 1: players, 2: NPC, 3: shops/chat)." +die: "Kills yourself." +go: "Params: <number/city_name>\n" "Warps you to a city.\n" + " -3: (Memo point 2) 1: morocc 5: izlude 9: yuno 13: niflheim \n" + " -2: (Memo point 1) 2: geffen 6: aldebaran 10: amatsu 14: louyang\n" + " -1: (Memo point 0) 3: payon 7: xmas (lutie) 11: gonryun 15: start point\n" + " 0: prontera 4: alberta 8: comodo 12: umbala 16: prison/jail\n" +jumpto: "Params: <char name>\n" "Warps you to selected character." +follow: "Params: <char_name>\n" "Follow a player." +mount: "Give/remove you a peco (Class is required, but not skill)" +disguise: "Params: <monster_name_or_monster_ID>\n" "Change your appearence to other players to a mob." +undisguise: "Restore your normal appearance." +model: "Params: <hair ID: 0-17> <hair color: 0-8> <clothes color: 0-4> - Changes your characters appearence." +size: "Params: <1-3> Changes your size (1-Smallest 2-Biggest 3-Normal)" +hide: "Makes you character invisible (GM invisibility). Type again to become visible." +save: "Sets respawn point to current spot." +load: "Warps you to your save point." +warp: "Params: <mapname> [<x> <y>]\n" "Warps you to the selected map and position." +jump: "Params: [<x> [<y>]]\n" "Randomly warps you like a flywing." +jobchange: "Params: <job ID>\n" "Changes your job.\n" +" 0: Novice 18: Alchemist 4015: Paladin\n" +" 1: Swordman 19: Bard 4016: Champion\n" +" 2: Mage 20: Dancer 4017: Professor\n" +" 3: Archer 23: Super Novice 4018: Stalker\n" +" 4: Acolyte 4001: High Novice 4019: Creator\n" +" 5: Merchant 4002: High Swordman 4020: Clown\n" +" 6: Thief 4003: High Mage 4021: Gypsy\n" +" 7: Knight 4004: High Archer 4046: Taekwon\n" +" 8: Priest 4005: High Acolyte 4047: Star Gladiator\n" +" 9: Wizard 4006: High Merchant 4049: Soul Linker\n" +" 10: Blacksmith 4007: High Thief 24: Gunslinger\n" +" 11: Hunter 4008: Lord Knight 25: Ninja\n" +" 12: Assassin 4009: High Priest\n" +" 14: Crusader 4010: High Wizard\n" +" 15: Monk 4011: Whitesmith\n" +" 16: Sage 4012: Sniper\n" +" 17: Rogue 4013: Assassin Cross\n" +" ---- Baby Classes ----\n" +" 4023: Baby 4024: Baby Swordman 4025: Baby Mage\n" +" 4026: Baby Archer 4027: Baby Acolyte 4028: Baby Merchant\n" +" 4029: Baby Thief 4030: Baby Knight 4031: Baby Priest\n" +" 4032: Baby Wizard 4033: Baby Blacksmith 4034: Baby Hunter\n" +" 4035: Baby Assassin 4037: Baby Crusader 4038: Baby Monk\n" +" 4039: Baby Sage 4040: Baby Rogue 4041: Baby Alchemist\n" +" 4042: Baby Bard 4043: Baby Dancer 4045: Super Baby\n" +option: "Params: <param1> <param2> <param3>\n" "Adds different visual effects on or around your character.\n" +"<param1> <param2> <p3>(stackable) <param3> <param3>\n" +"1 Petrified (stackable) 01 Sight 32 Peco Peco riding 2048 Orc Head\n" +"2 Frozen 01 Poison 02 Hide 64 GM Perfect Hide 4096 Wedding Sprites\n" +"3 Stunned 02 Cursed 04 Cloak 128 Level 2 Cart 8192 Ruwach\n" +"4 Sleeping 04 Silenced 08 Level 1 Cart 256 Level 3 Cart\n" +"6 darkness 08 ??? 16 Falcon 512 Level 4 Cart\n" +" 16 darkness 1024 Level 5 Cart\n" +heal: "Params: [<HP> <SP>]\n" "Heals the desired amount of HP and SP. No value specified will do a full heal." +dye: "Params: <clothes palette no.>\n" "Changes your characters clothes color." +hairstyle: "Params: <hairstyle no.>\n" "Changes your hair style." +haircolor: "Params <hair palette no.>\n" "Changes your hair color." +speed: "Params: <1-1000>\n" "Changes you walking speed. 1 being the fastest and 1000 the slowest. Default is 150." +effect: "Params: <effect id> [<flag>]\n" "Give an effect to your character." +dropall: "Throws all your possession on the ground." +storeall: "Puts all your possessions in storage." +killable: "Make your character killable." +memo: "Params: [memo position]\n" "Set/change a memo location (no position: display memo points)." +spiritball: "Params: <1-100>\n" "Gives you \"spirit spheres\" like from the skill \"Call Spirits\".\n" +questskill: "Params: <#>\n" "Gives you the specified quest skill" +lostskill: "Params: <#>\n" "Takes away the specified quest skill from you\n" +" Novice Swordsman Thief Merchant\n" +" 142 = Emergency Care 144 = Moving HP Recovery 149 = Throw Sand 153 = Cart Revolution\n" +" 143 = Act dead 145 = Attack Weak Point 150 = Back Sliding 154 = Change Cart\n" +" Archer 146 = Auto Berserk 151 = Take Stone 155 = Crazy Uproar/Loud Voice\n" +" 147 = Arrow Creation Acolyte 152 = Stone Throw Magician\n" +" 148 = Charge Arrows 156 = Holy Light 157 = Energy Coat\n" +skillid: "Params: <name>\n" "Look up a skill by name" +useskill: "Params: <skillid> <skillv> <target>\n" "Use a skill on target" +skilltree: "Params: <" +marry: "Params: <player1>,<player2>\n" "Marry two players." +divorce: "Params: <player>\n" "Divorces the two players (you need just one name of them)" +alive: "Revives yourself from death." +blvl: "Params: <number of levels>\n" "Raises your base level the desired number of levels." +jlvl: "Params: <number of levels>\n" "Raises your job level the desired number of levels." +allskill: "Give you all skills." +stpoint: "Params: <number of points> - Gives you the desired number of stat points." +skpoint: "Params: <number of points> - Gives you the desired number of skill points." +zeny: "Params: <amount> - Gives you desired amount of Zeny." +cash: "Params: <amount> - Gives you the specified amount of cash points." +points: "Params: <amount> - Gives you the specified amount of Kafra Points." +str: "Params: <amount>\n" "Raises STR by given amount." +agi: "Params: <amount>\n" "Raises AGI by given amount." +dex: "Params: <amount>\n" "Raises DEX by given amount." +vit: "Params: <amount>\n" "Raises VIT by given amount." +int: "Params: <amount>\n" "Raises INT by given amount." +luk: "Params: <amount>\n" "Raises LUK by given amount." +allstats: "Params: <value>\n" "Adds value in all stats (maximum if no value)." +addwarp: "Params: <map name> <x coord> <y coord>\n" +killmonster2: "Kills all monsters of your map (without drops)." +monster: "Params: <monster_name_or_monster_ID> [<number to spawn> [<desired_monster_name> [<x coord> [<y coord>]]]]\n" + "@monster2 <desired_monster_name> <monster_name_or_monster_ID> [<number to spawn> [<x coord> [<y coord>]]]\n" +"@spawn/@monster/@summon/@monster2 \"desired monster name\" <monster_name_or_monster_ID> [<number to spawn> [<x coord> [<y coord>]]]\n" +"@spawn/@monster/@summon/@monster2 <monster_name_or_monster_ID> \"desired monster name\" [<number to spawn> [<x coord> [<y coord>]]]\n" +" Spawns the desired monster with any desired name." +monstersmall: "Params: [Mob ID|Mob Name]\n" "Spawns a smaller version of a monster." +monsterbig: "Params: [Mob ID|Mob Name]\n" "Spawns a larger version of a monster." +killmonster: "Params: [map]\n" "Kill all monsters of the map (they drop)" +autoloot: "Params: [on|off|#]\n" "Makes items go straight into your inventory." +autotrade: "Allows you to vend while you are offline." +changegm: "Params: [Player Name]\n" "Changes the leader of your guild (You must be guild leader)" +changeleader: "Params: [Player Name]\n" "Changes the leader of your party (You must be party leader)" +request: "Params: [Message]\n" "Sends a message to all connected GMs (via the gm whisper system)" +sound: "Params: [Path way to file in Data or GRF file]\n" "Plays a sound from the data or grf file located on the client." +clone: "Params: [Player Name]\n" "Spawns a supportive clone of the given player." +slaveclone: "Params: [Player Name]\n" "Spawns a supportive clone of the given player that follows the creator around." +evilclone: "Params: [Player Name]\n" "Spawns an agressive clone of the given player." +changesex: "Changes your gender." +duel: "Starts a duel." +invite: "Invites a player to a duel." +accept: "Accepts an invitation to a duel." +reject: "Rejects an invitation to a duel." +leave: "Leaves a duel." +mail: "Open mail box." +storage: "Opens storage." +itemreset: "Remove all your items." +guildstorage: "Opens guild storage." +idsearch: "Params: <part_of_item_name>\n" "Search all items that name have part_of_item_name" +refine: "Params: <equip position> <+/- amount>" +produce: "Params: <equip name or equip ID> <element> <# of very's>\n" +" Element: 0=None 1=Ice 2=Earth 3=Fire 4=Wind\n" +" You can add up to 3 Star Crumbs and 1 element\n" +repairall: "Repair all items of your inventory" +item: "Params: <item name or ID> <quantity>\n" "Gives you the desired item." +item2: "Params: <item name or ID> <quantity> <identified_flag> <refine> <broken_flag> <Card1> <Card2> <Card3> <Card4>\n" "Gives you the desired item." +pvpon: "Turns pvp on on the current map" +pvpoff: "Turns pvp off on the current map" +gvgon: "Turns gvg on on the current map" +gvgoff: "Turns gvg off on the current map" +agitstart: "Starts War of Emperium" +agitend: "End War of Emperium" +party: "Params: <party_name>\n" "Create a party." +guild: "Params: <guild_name>\n" "Create a guild." +glvl: "Params: <# of levels>\n" "Raise Guild by desired number of levels" +guildrecall: "Params: <guild_name/id>\n" "Warps all online characters of a guild to you." +partyrecall: "Params: <party_name/id>\n" "Warps all online characters of a party to you." +petrename: "Re-enable pet rename" +pettalk: "Params: [Message]\n" "Makes your pet say a message." +petfriendly: "Params: <#>\n" "Set pet friendly amount (0-1000) 1000 = Max" +pethungry: "Params: <#>\n" "Set pet hungry amount (0-100) 100 = Max" +hatch: "Create a pet from your inventory eggs list." +makeegg: "Params: <pet_id>\n" "Gives pet egg for monster number in pet DB" +kick: "Params: <char name>\n" "Kicks specified character off the server" +unjail: "Params: <char name>\n" "Discharges specified character/prisoner" +kill: "Params: <char name>\n" "Kills specified character." +recall: "Params: <char name>\n" "Warps target character to you." +raise: "Params: <char name>\n" "Revives target character." +block: "Params: <char name>\n" "Blocks definitively a account" +unblock: "Params: <char name>\n" "Unblocks a account" +ban: "Params: <time> <name>\n" "Ban temporarily a account\n" + " time usage: adjustment (+/- value) and element (y/a, m, d/j, h, mn, s)\n" + " Example: @ban +1m-2mn1s-6y testplayer\n" +unban: "Params: <name> - Unban a account" +jail: "Params: <char name> - Sends specified character in jails" +trade: "Params: <char name> - Open a trade window with a another player" +recallall: "Warps every character online to you." +doom: "Kills all NON GM chars on the server." +doommap: "Kills all non GM characters on the map." +raisemap: "Resurrects all characters on the map." +night: "Uses @option 00 16 00 on all characters. All characters are in darkness." +day: "Uses @option 00 00 00 on all characters." +skillon: "turn skills on for a map" +skilloff: "turn skills on for a map" +snow: "Makes all maps to have the snow weather effect." +clouds: "Makes all maps to have the cloudy weather effect." +clouds2: "Makes all maps to have another cloudy weather effect." +fog: "Makes all maps to have the fog weather effect." +fireworks: "Makes all maps to have the fireworks weather effect." +sakura: "Makes all maps to have the sakura weather effect." +leaves: "Makes all maps to have the leaves weather effect." +shownpc: "Params: <NPC name>\n" "Enable a NPC" +hidenpc: "Params: <NPC name>\n" "Disable a NPC" +loadnpc: "Params: <path to script>\n" "Load script" +unloadnpc: "Params: <NPC name>\n" "Unload script" +adjgroup: "Params: <level> <char name> - Do a temporary adjustment of the GM level of a player" +kickall: "Kick all characters off the server" +mapexit: "Kick all players and shut down map-server." +reloaditemdb: "Reload item database." +reloadmobdb: "Reload monster database." +reloadskilldb: "Reload skills definition database." +reloadscript: "Reload all scripts." +gat: "For debugging (you inspect around gat)" +send: "For debugging (packet variety)" +nuke: "Params: <char name>\n" + diff --git a/conf/help2.txt b/conf/help2.txt deleted file mode 100644 index 8f8330dbd..000000000 --- a/conf/help2.txt +++ /dev/null @@ -1,94 +0,0 @@ - 0:To use one command, type it inside the message window where you usually type to chat. - 1:--- ITEMS CMD --- - 1:@storage - Opens storage - 40:@itemreset - Remove all your items. - 50:@gstorage - Opens guild storage - 60:@itemcheck - Check your items with authorised items. - 60:@idsearch <part_of_item_name> - Search all items that name have part_of_item_name - 60:@refine <equip position> <+/- amount> - 60:@produce <equip name or equip ID> <element> <# of very's> - 60: Element: 0=None 1=Ice 2=Earth 3=Fire 4=Wind - 60: You can add up to 3 Star Crumbs and 1 element - 60:@repairall - Repair all items of your inventory - 60:/item <item_name> - Gives you 1 of the desired item. - 60:@item <item name or ID> <quantity> - Gives you the desired item. - 60:@item2 <item name or ID> <quantity> <identified_flag> <refine> <broken_flag> <Card1> <Card2> <Card3> <Card4> - Gives you the desired item. - 40: - 40:--- PVP CMD --- - 40:@pvpon - Turns pvp on on the current map - 40:@pvpoff - Turns pvp off on the current map - 40:@gvgon/@gpvpon - Turns gvg on on the current map - 40:@gvgoff/@gpvpoff - Turns gvg off on the current map - 60:@agitstart - Starts War of Emperium - 60:@agitend - End War of Emperium - 1: - 1:--- GROUPS CMD --- - 1:@party <party_name> - Create a party. - 50:@guild <guild_name> - Create a guild. - 60:@guildlvup/@guildlvlup <# of levels> - Raise Guild by desired number of levels - 60:@guildrecall <guild_name/id> - Warps all online characters of a guild to you. - 60:@partyrecall <party_name/id> - Warps all online characters of a party to you. - 1: - 1:--- PETS CMD --- - 1:@petrename - Re-enable pet rename - 10:@pettalk [Message] - Makes your pet say a message. - 40:@petfriendly <#> - Set pet friendly amount (0-1000) 1000 = Max - 40:@pethungry <#> - Set pet hungry amount (0-100) 100 = Max - 60:@hatch - Create a pet from your inventory eggs list. - 60:@makeegg <pet_id> - Gives pet egg for monster number in pet DB - 20: - 20:--- REMOTE CHAR CMD --- - 20:@kick <char name> - Kicks specified character off the server - 40:@charkillable <char name> - make another character killable - 60:@unjail/@discharge <char name> - Discharges specified character/prisoner - 60:@kill <char name> - Kills specified character. - 60:@chardropall <char name> - throws all a chars possession on the ground - 60:@charstoreall <char name> - puts all of anothers charactes possessions in storage - 60:/recall/@recall <char name> - Warps target character to you. - 60:@revive <char name> - Revives target character. - 60:@charblock/@block <char name> - Blocks definitively a account - 60:@charunblock/@unblock <char name> - Unblocks a account - 60:@charban/@ban/@banish/@charbanish <time> <name> - Ban temporarily a account - 60: time usage: adjustment (+/- value) and element (y/a, m, d/j, h, mn, s) - 60: Example: @ban +1m-2mn1s-6y testplayer - 60:@charunban/@unban/@unbanish/@charunbanish <name> - Unban a account - 60:@jail <char name> - Sends specified character in jails - 60:@trade <char name> - Open a trade window with a another player - 80:@recallall - Warps every character online to you. - 80:@doom - Kills all NON GM chars on the server. - 80:@doommap - Kills all non GM characters on the map. - 80:@raise - Resurrects all characters on the server. - 80:@raisemap - Resurrects all characters on the map. - 80: - 80:--- ENVIRONMENT CMD --- - 80:@night - Uses @option 00 16 00 on all characters. All characters are in darkness. - 80:@day - Uses @option 00 00 00 on all characters. - 80:@skillon - turn skills on for a map - 80:@skilloff - turn skills on for a map - 99:@rain - Makes all maps to have the rain weather effect. - 99:@snow - Makes all maps to have the snow weather effect. - 99:@clouds - Makes all maps to have the cloudy weather effect. - 99:@clouds2 - Makes all maps to have another cloudy weather effect. - 99:@fog - Makes all maps to have the fog weather effect. - 99:@fireworks - Makes all maps to have the fireworks weather effect. - 99:@sakura - Makes all maps to have the sakura weather effect. - 99:@leaves - Makes all maps to have the leaves weather effect. - 80: - 80:--- ADMIN CMD --- - 80:@shownpc <NPC name> - Enable a NPC - 80:@hidenpc <NPC name> - Disable a NPC - 80:@loadnpc <path to script> - Load script - 80:@unloadnpc <NPC name> - Unload script - 99:@adjgmlvl <level> <char name> - Do a temporary adjustment of the GM level of a player - 99:@adjcmdlvl <level> <command> - Do a temporary adjustment of the GM level of a command - 99:@kickall - Kick all characters off the server - 99:@mapexit - Kick all players and shut down map-server. - 99:@reloaditemdb - Reload item database. - 99:@reloadmobdb - Reload monster database. - 99:@reloadskilldb - Reload skills definition database. - 99:@reloadscript - Reload all scripts. - 99:@reloadgmdb - Reload GM levels. - 99: - 99:@gat - For debugging (you inspect around gat) - 99:@packet - For debugging (packet variety) -100:@nuke <char name> - diff --git a/conf/log_athena.conf b/conf/log_athena.conf index 37ab1b14f..13174a018 100644 --- a/conf/log_athena.conf +++ b/conf/log_athena.conf @@ -84,8 +84,10 @@ log_zeny: 0 // Outdated. Use Pick_Log instead. But this log could be useful to keep track slayed MVPs log_mvpdrop: no -// Log GM Commands (set to minimum level of Logged Commands) -log_gm: 40 +// Log AtCommands & Charcommands (Note 1) +// Only commands issued by player groups ('conf/groups.conf') with +// 'log_commands' setting set to 'true' will be logged. +log_commands: yes // Log NPC 'logmes' commands (Note 1) log_npc: no diff --git a/conf/login_athena.conf b/conf/login_athena.conf index aab2f854c..7dda3cb5c 100644 --- a/conf/login_athena.conf +++ b/conf/login_athena.conf @@ -62,9 +62,10 @@ log_login: yes // Indicate how to display date in logs, to players, etc. date_format: %Y-%m-%d %H:%M:%S -// Indicate the minimum GM level of player that the server accepts to connection. -// 0: all players (normal player are 0. it's default), 1-99: GM level at least with level x -min_level_to_connect: 0 +// Required account group id to connect to server. +// -1: disabled +// 0 or more: group id +group_id_to_connect: -1 // Starting additional sec from now for the limited time at creation of account // -1: new account are created with UNlimited time (default value) diff --git a/conf/msg_athena.conf b/conf/msg_athena.conf index 2f5e50eea..8de5b8ec0 100644 --- a/conf/msg_athena.conf +++ b/conf/msg_athena.conf @@ -44,7 +44,7 @@ 24: Job level raised. 25: Job level lowered. 26: Help commands: -27: File help.txt not found. +27: Commands help is not available. 28: No player found. 29: 1 player found. 30: %d players found. @@ -348,16 +348,6 @@ // 334: Thirty-Four Castles 334: Total Domination -// Players Titles (for @who, etc commands, check battle_athena.conf for titles level setting) -// Useful note: you may remove ':%d' from the line, then you will see only player title, w/o his level -335: Super player:%d -336: Super player+:%d -337: Mediator:%d -338: Sub-GM:%d -339: Sub-GM+:%d -340: GM:%d -341: GM Chief:%d -342: Administrator:%d // Templates for @who output 343: Name: %s 344: (%s) @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Revision: 15238 . +# From configure.in Revision: 15503 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.59. # @@ -1334,7 +1334,7 @@ ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_config_files="$ac_config_files Makefile src/common/Makefile" - ac_config_files="$ac_config_files 3rdparty/mt19937ar/Makefile" + ac_config_files="$ac_config_files 3rdparty/mt19937ar/Makefile 3rdparty/libconfig/Makefile" ac_config_files="$ac_config_files src/char/Makefile src/login/Makefile" @@ -3737,6 +3737,289 @@ if test $ac_cv_func_strnlen = yes; then fi +# libconfig +echo "$as_me:$LINENO: checking for uselocale" >&5 +echo $ECHO_N "checking for uselocale... $ECHO_C" >&6 +if test "${ac_cv_func_uselocale+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define uselocale to an innocuous variant, in case <limits.h> declares uselocale. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define uselocale innocuous_uselocale + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char uselocale (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef uselocale + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char uselocale (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_uselocale) || defined (__stub___uselocale) +choke me +#else +char (*f) () = uselocale; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != uselocale; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_uselocale=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_uselocale=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_uselocale" >&5 +echo "${ECHO_T}$ac_cv_func_uselocale" >&6 +if test $ac_cv_func_uselocale = yes; then + CFLAGS="$CFLAGS -DHAVE_USELOCALE" +fi + +echo "$as_me:$LINENO: checking for newlocale" >&5 +echo $ECHO_N "checking for newlocale... $ECHO_C" >&6 +if test "${ac_cv_func_newlocale+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define newlocale to an innocuous variant, in case <limits.h> declares newlocale. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define newlocale innocuous_newlocale + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char newlocale (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef newlocale + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char newlocale (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_newlocale) || defined (__stub___newlocale) +choke me +#else +char (*f) () = newlocale; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != newlocale; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_newlocale=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_newlocale=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_newlocale" >&5 +echo "${ECHO_T}$ac_cv_func_newlocale" >&6 +if test $ac_cv_func_newlocale = yes; then + CFLAGS="$CFLAGS -DHAVE_NEWLOCALE" +fi + +echo "$as_me:$LINENO: checking for freelocale" >&5 +echo $ECHO_N "checking for freelocale... $ECHO_C" >&6 +if test "${ac_cv_func_freelocale+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* Define freelocale to an innocuous variant, in case <limits.h> declares freelocale. + For example, HP-UX 11i <limits.h> declares gettimeofday. */ +#define freelocale innocuous_freelocale + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char freelocale (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + +#undef freelocale + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char freelocale (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_freelocale) || defined (__stub___freelocale) +choke me +#else +char (*f) () = freelocale; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != freelocale; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_freelocale=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_freelocale=no +fi +rm -f conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_freelocale" >&5 +echo "${ECHO_T}$ac_cv_func_freelocale" >&6 +if test $ac_cv_func_freelocale = yes; then + CFLAGS="$CFLAGS -DHAVE_FREELOCALE" +fi + # # Memory manager @@ -6166,6 +6449,7 @@ do "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; "src/common/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/common/Makefile" ;; "3rdparty/mt19937ar/Makefile" ) CONFIG_FILES="$CONFIG_FILES 3rdparty/mt19937ar/Makefile" ;; + "3rdparty/libconfig/Makefile" ) CONFIG_FILES="$CONFIG_FILES 3rdparty/libconfig/Makefile" ;; "src/char/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/char/Makefile" ;; "src/login/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/login/Makefile" ;; "src/map/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/map/Makefile" ;; diff --git a/configure.in b/configure.in index 3269537b2..940e752a6 100644 --- a/configure.in +++ b/configure.in @@ -6,7 +6,7 @@ AC_REVISION($Revision$) AC_PREREQ([2.59]) AC_CONFIG_SRCDIR([src/common/cbasetypes.h]) AC_CONFIG_FILES([Makefile src/common/Makefile]) -AC_CONFIG_FILES([3rdparty/mt19937ar/Makefile]) +AC_CONFIG_FILES([3rdparty/mt19937ar/Makefile 3rdparty/libconfig/Makefile]) AC_CONFIG_FILES([src/char/Makefile src/login/Makefile]) AC_CONFIG_FILES([src/map/Makefile src/plugins/Makefile src/tool/Makefile]) @@ -468,6 +468,10 @@ AC_CHECK_FUNC([setrlimit],[CFLAGS="$CFLAGS -DHAVE_SETRLIMIT"]) # AC_CHECK_FUNC([strnlen],[CFLAGS="$CFLAGS -DHAVE_STRNLEN"]) +# libconfig +AC_CHECK_FUNC([uselocale],[CFLAGS="$CFLAGS -DHAVE_USELOCALE"]) +AC_CHECK_FUNC([newlocale],[CFLAGS="$CFLAGS -DHAVE_NEWLOCALE"]) +AC_CHECK_FUNC([freelocale],[CFLAGS="$CFLAGS -DHAVE_FREELOCALE"]) # # Memory manager diff --git a/doc/atcommands.txt b/doc/atcommands.txt new file mode 100644 index 000000000..b60735cac --- /dev/null +++ b/doc/atcommands.txt @@ -0,0 +1,213 @@ +TODO: With such short descriptions, it's duplicated 'conf/help.txt' +Consider explaining commands in detail, similar to 'doc/script_commands.txt' + +commands: Displays a list of @ commands available to the player. +charcommands: Displays a list of # commands available to the player. +rates: Displays the server rates. +uptime: Show server uptime since last map server restart. +showdelay: Shows/Hides the "there is a delay after a skill" message. +exp: Displays current levels and % progress. +email: To change your (own) email. Note: this command doesn't check email itself, but check structure of the email (xxx@xxx). +monsterinfo: Show Monster info (rates, stats, drops, MVP stuff). +iteminfo: Show Item info (type, price, etc). +whodrops: Show who drops an item (mobs with highest drop rate). +refresh: Syncs the player's position on the client with the one stored on the server. +time: Give server time. +version: Displays SVN version of the server. +die: Suicide your character. +petrename: Enables you to rename your pet. +party: Organize a new party, with you as the party leader. +storage: Opens your Kafra storage wherever you are. +mail: Opens your mailbox. +auction: Opens auctions window. +where: Locate someone on a map, returns your coordinates if the person isn't on. +duel, invite, accept, reject, leave: Duel organizing commands. +main: Main chat. +noask: Autorejecting Deals/Invites. +jailtime: Displays remaining jail time. +hominfo, homstats: Homunculus commands for players +noks: Kill Steal Protection. +font: Set Font. +showexp: Displays/Hides Experience gained messages. +showzeny: Displays/Hides Zeny gained messages. +go: Warps you to predefined locations in major cities. +autoloot: Enables/disables autolooting from killed mobs. +alootid: Enables/disables autolooting an item. +autotrade: Allows you continue vending offline. +changegm: Change Guild Master of your Guild. +changeleader: Change the leader of your party. +partyoption: Change the party exp- and item share rules. +pettalk: Command what the player's pet will say. +homtalk: Command what the player's homunculus will say. +mobsearch: Locates and displays the position of a certain mob on the current map. +showmobs: Locates and displays the position of a certain mob on your mini-map. +whereis: Prints out in which maps a monster normally spawns at (does not count script-invoked mobs). +feelreset: Resets a Star Gladiator's marked maps +help: Displays help about commands. +goto: Warp yourself to a person. +gmotd: Displays the motd file to all players. +follow: Follow a player (including warping to them). +request: Sends a request to all connected GMs (via the gm whisper system). +kick: Disconnects a user from the server. +model: Changes your appearance. +mount: To get a peco to (un)ride. +who: Returns list of logged in characters with their position. +who2: Returns list of logged in characters with their job. +who3: Returns list of logged in characters with their party/guild. +whomap: Returns list of logged in characters with their position in a specifical map. +whomap2: Returns list of logged in characters with their job in a specifical map. +whomap3: Returns list of logged in characters with their party/guild in a specifical map. +whogm: Displays GMs online. For those who are higher GM level than yourself, only the name is shown, for the rest, it displays the same info of @who+@who2+who3. +disguise: Change your appearence to other players to a mob. +undisguise: Restore your normal appearance. +me: Displays the text as a normal message with the format "*name message*" instead of "name : message" (Like the /me command in IRC). +fakename: Changes your name to your choice temporarily. +size: Changes your size. +npctalk: Can command what other npcs (by name) can say. +broadcast: Broadcast to the whole server. +localbroadcast: Broadcast to the map you are on. +kami: Broadcast (with or without name). +kamib: Same as kami but with blue color. +kamic: Same as kami but you can choose the color (uses different packet). +gvgon: Enables GvG on a map. +gvgoff: Turns GvG (Guild vs. Guild) off on a map +allowks: Activate/Deactivate kill steal protection on a map. +heal: Modifies your HP/SP. +hide: GM Hide (total invisibility to characters and monsters) +job: Changes your job to one you specify. +jump: Enables you to to jump randomly on a map (that you are already on). +load: Warps you to your last save point +tonpc: Warps you to a specific npc. +memo: Saves a warp point. +option: Set your character display options. (Visual effects of your character) +petfriendly: Sets the level of intemecy of your pet. +pethungry: Sets hunger level of your pet. +pvpoff: Turns PvP (Person vs. Person) off on a map. +pvpon: Enables PvP on a map. +questskill: Permanently adds a quest skill. +lostskill: Permanently removes a quest skill +speed: Sets the speed you can walk/attack at. Default is 150. +spiritball: Summons spirit spheres around you. +warp: Warp yourself to a certain map, at (x,y) coordinates (2 same commands) + also /mm or /mapmove. +dye: Changes clothes color. +hairstyle: Changes hair style. +haircolor: Changes hair color. +itemreset: Deletes all your items. +reset: Does a skill/stat reset. +users: Displays distribution of players on the server per map (% on each map which has players). +cleanmap: Deletes floor items in sight range. +killmonster2: Kill all monsters in map (without drops). +save: Sets spawn point (aka save point). +effect: Do some visual effect on a character. +misceffect: Do some visual effect on a character (misceffect) +identify: Magnifier. +dropall: Drop all items. +storeall: Store all items. +killable: Allow other players to hit you out of PvP. +skillid: Look up a skill by name. +useskill: Use a skill by id. +skilltree: What skills are required to get this skill. +marry, divorce: Marriage commands. +adopt: Adopt a novice into a family. +sound: Play a Sound! +storagelist: Displays a player's storage. +cartlist: Displays a player's cart contents. +itemlist: Displays a player's inventory. +stats: Displays player's stats. +guild: Creates a new guild, with you as the guildmaster. +gstorage: Brings up your guild storage wherever you are. +monster: Spawns a monster, and a certain amount. +monstersmall: Spawns a smaller sized version of a monster. +monsterbig: Spawns a larger sized version of a monster. +summon: Spawns mobs that treat you as their master (they disappear after some time). +clone: It will spawn a supportive clone of the given player. +slaveclone: It will spawn a supportive clone of the given player that follows the creator around. +evilclone: It will spawn an aggresive clone of the given player. +cash: Add or Remove Cash Points +points: Add or Remove Kafra Points +agitstart: Starts Guild Wars +agitend: Ends Guild Wars +alive: Resurects yourself. +blvl: Raises your base level by specified amount +jlvl: Raises your job level by specified amount +changesex: Changes the sex of yourself +glvl: Raises your guild level by specified amount +idsearch: Find an itemID based on item name +item: Creates an item of your choosing, either Item ID or Name +item2: Creates a complete item (card, etc...) of your choosing, either Item ID or Name. +delitem: Deletes an item of your choosing, either Item ID or Name. +kill: Kill another character without hitting them. +killmonster: Kill all monsters in map (with drops) +makeegg: Creates yourself a pet egg. +hatch: Hatches an egg. +nuke: Instantly kills player whose name is entered and deals insane damage to everything around. +killer: Enable hitting a player even when not in PvP +produce: Creates weapon of desired element. +recall: Warps a character to you. +refine: Refines all weapons in your items list. +repairall: Will repair all broken items in inventory. +str, agi, vit, int, dex, luk: Change Status of your character. +allskill: Gives all skills +allstats: Sets stats to maximum +stpoint: Gives you stat points. +skpoint: Gives you skill points of desired amount. +guildrecall: Warps all online character of a guild to you. (at least one member of that guild must be on.) +partyrecall: Warps all online character of a party to you. (at least one party member must be online.) +guildspy: Allows you to spy on any Guilds Guild chat. (at least one member of that guild must be on.) NOTE: map server needs to be configured to enable spying to use this command (enable_spy: yes) +partyspy: Allows you to spy on any party's party chat. (at least one party member must be online.) NOTE: map server needs to be configured to enable spying to use this command (enable_spy: yes) +zeny: Gives you zeny (or subtracts, if amount is negative). +block: Block a player indefinitely. +unblock: Unblock a player. +ban: Ban a player for a limited time. +unban: Unban a player. +jail: To send specified character in jails. +unjail: To discharge a jailed character. +jailfor: Timed jailing. +addwarp: Create a static warp portal that lasts until the next reboot. +trade: Open a trade window with any player. +changelook: Changes the player's appearance (headgear). +hlvl, homevolve, makehomun, homfriendly, homhungry: Homunculus commands for GMs. +homshuffle: Re-calculates stats, as if the homun was sent back to level 1 and re-leveled. +agitstart2, agitend2: WoE 2 start/stop commands. +streset: Resets player stats +skreset: Resets player skills +day: Set the server to day. +night: Set the server to night. +doom: Kills everyone on the server. +doommap: Kills everyone on the map you are on. +recallall: Recalls Everyone To Your Coordinates +raisemap: Revives all players on the map. +raise: Revives all players on the server. +hidenpc: Hides a NPC. +shownpc: Unhides a NPC. +loadnpc: Loads an NPC script by path. +unloadnpc: Unloads a NPC. +npcmove: Move a NPC. +skillon: Turn skills on for a map +skilloff: Turn skills off for a map +mute: Mute a player (prevents talking, usage of skills and commands) +unmute: Unmute a player +kickall: Disconnect all users from the server. +mapexit: Closes Map-Server. +send: Used for testing packet sends from the client (debug function). +gat: Give information about terrain/area (debug function). +displaystatus: Displays a status change without really applying it (debug function). +displayskill: Displays the animation of a skill without really using it (debug function). +mapinfo: Shows information about the map. +mapflag: Set Map Flags +reloaditemdb: Re-load item database (admin command) +reloadmobdb: Re-load monsters database (admin command) +reloadskilldb: Re-load skills database (admin command) +reloadscript: Re-load scripts (admin command) +setbattleflag: Change a battle_config flag without rebooting server +reloadatcommand: Re-load atcommand config (admin command) +reloadbattleconf: Re-load battle config (admin command) Note that some player config settings won't take effect until relog (display exp, display zeny, display skill delay fail, ...) +reloadstatusdb: Re-load status database (admin command) +reloadpcdb: Re-load player info database (admin command) +reloadmotd: Re-load the Message of the Day (admin command) +adjgroup: Changes the group of another character (lasts until relog) +disguiseall, undisguiseall: [Un]Disguise All Players (admin command) +mutearea: Mutes every player on screen (admin command) +battleignore: Makes you immune to attacks (monsters/players/skills cannot target/hit you, admin command) +snow, clouds, clouds2, fog, fireworks, sakura, leaves: Weather effects +clearweather: Stop all weather effects diff --git a/doc/permissions.txt b/doc/permissions.txt new file mode 100644 index 000000000..afadb680c --- /dev/null +++ b/doc/permissions.txt @@ -0,0 +1,21 @@ +These are possible permissions of player groups, configured in conf/groups.conf. + +can_trade : Ability to trade or otherwise distribute items (drop, storage, vending etc) +can_party : Ability to join parties. +all_skill : Ability to use all skills. +all_equipment : Ability to equip anything (can cause client errors). +skill_unconditional : Ability to use skills without meeting the required conditions (SP, items, etc...). +join_chat : Ability to join a password protected chatrooms. +kick_chat : Protection from being kicked from a chat. +hide_session : Hides player session from being displayed by @commands. +who_display_aid : Ability to see GMs and Account/Char IDs in the @who command. +hack_info : Ability to receive all informations about any player that try to hack, spoof a name, etc. +any_warp : Ability to bypass nowarp, nowarpto, noteleport and nomemo mapflags. + This option is mainly used in commands which modify a character's + map/coordinates (like @memo, @mapmove, @go, @jump, etc...). +view_hpmeter : Ability to see HP bar of every player. +view_equipment : Ability to view players equipment regardless of their setting. +use_check : Ability to use client command /check (display character status). +use_changemaptype : Ability to use client command /changemaptype. +all_commands: Ability to use ALL atcommands/charcommands. +receive_requests: Ability to receive @requests. diff --git a/sql-files/upgrade_svn15572.sql b/sql-files/upgrade_svn15572.sql new file mode 100644 index 000000000..821bb79d6 --- /dev/null +++ b/sql-files/upgrade_svn15572.sql @@ -0,0 +1,3 @@ +-- Rename `level` column to `group_id` in `login` table + +ALTER TABLE `login` CHANGE COLUMN `level` `group_id` TINYINT(3) NOT NULL DEFAULT '0';
\ No newline at end of file diff --git a/src/char/Makefile.in b/src/char/Makefile.in index e96113f0e..f48f116b8 100644 --- a/src/char/Makefile.in +++ b/src/char/Makefile.in @@ -3,17 +3,24 @@ COMMON_OBJ = ../common/obj_all/core.o ../common/obj_all/socket.o ../common/obj_a ../common/obj_all/db.o ../common/obj_all/plugins.o ../common/obj_all/lock.o \ ../common/obj_all/malloc.o ../common/obj_all/showmsg.o ../common/obj_all/utils.o \ ../common/obj_all/strlib.o \ - ../common/obj_all/mapindex.o ../common/obj_all/ers.o ../common/obj_all/random.o + ../common/obj_all/mapindex.o ../common/obj_all/ers.o ../common/obj_all/random.o ../common/obj_all/conf.o COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h \ ../common/version.h ../common/db.h ../common/plugins.h ../common/lock.h \ ../common/malloc.h ../common/showmsg.h ../common/utils.h \ ../common/strlib.h \ - ../common/mapindex.h ../common/ers.h ../common/random.h + ../common/mapindex.h ../common/ers.h ../common/random.h ../common/obj_all/conf.h MT19937AR_OBJ = ../../3rdparty/mt19937ar/mt19937ar.o MT19937AR_H = ../../3rdparty/mt19937ar/mt19937ar.h MT19937AR_INCLUDE = -I../../3rdparty/mt19937ar +LIBCONFIG_OBJ = ../../3rdparty/libconfig/libconfig.o ../../3rdparty/libconfig/grammar.o \ + ../../3rdparty/libconfig/scanctx.o ../../3rdparty/libconfig/scanner.o ../../3rdparty/libconfig/strbuf.o +LIBCONFIG_H = ../../3rdparty/libconfig/libconfig.h ../../3rdparty/libconfig/grammar.h \ + ../../3rdparty/libconfig/parsectx.h ../../3rdparty/libconfig/scanctx.h ../../3rdparty/libconfig/scanner.h \ + ../../3rdparty/libconfig/strbuf.h ../../3rdparty/libconfig/wincompat.h +LIBCONFIG_INCLUDE = -I../../3rdparty/libconfig + COMMON_SQL_OBJ = ../common/obj_sql/sql.o COMMON_H = ../common/sql.h @@ -36,7 +43,7 @@ endif all: char-server_sql char-server_sql: $(CHAR_SERVER_SQL_DEPENDS) - @CC@ @LDFLAGS@ -o ../../char-server_sql@EXEEXT@ $(CHAR_OBJ) $(COMMON_OBJ) $(COMMON_SQL_OBJ) $(MT19937AR_OBJ) @LIBS@ @MYSQL_LIBS@ + @CC@ @LDFLAGS@ -o ../../char-server_sql@EXEEXT@ $(CHAR_OBJ) $(COMMON_OBJ) $(COMMON_SQL_OBJ) $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @MYSQL_LIBS@ clean: rm -rf *.o obj_sql ../../char-server_sql@EXEEXT@ @@ -57,8 +64,8 @@ needs_mysql: obj_sql: -mkdir obj_sql -obj_sql/%.o: %.c $(CHAR_H) $(COMMON_H) $(COMMON_SQL_H) $(MT19937AR_H) - @CC@ @CFLAGS@ $(MT19937AR_INCLUDE) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< +obj_sql/%.o: %.c $(CHAR_H) $(COMMON_H) $(COMMON_SQL_H) $(MT19937AR_H) $(LIBCONFIG_H) + @CC@ @CFLAGS@ $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< # missing object files ../common/obj_all/%.o: @@ -69,3 +76,6 @@ obj_sql/%.o: %.c $(CHAR_H) $(COMMON_H) $(COMMON_SQL_H) $(MT19937AR_H) MT19937AR_OBJ: @$(MAKE) -C ../../3rdparty/mt19937ar + +LIBCONFIG_OBJ: + @$(MAKE) -C ../../3rdparty/libconfig diff --git a/src/char/char.c b/src/char/char.c index 9f5be7d59..c2490efed 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -126,7 +126,7 @@ struct char_session_data { int found_char[MAX_CHARS]; // ids of chars on this account char email[40]; // e-mail (default: a@a.com) by [Yor] time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited) - int gmlevel; + int group_id; uint32 version; uint8 clienttype; char new_name[NAME_LENGTH]; @@ -134,7 +134,7 @@ struct char_session_data { }; int max_connect_user = 0; -int gm_allow_level = 99; +int gm_allow_group = -1; int autosave_interval = DEFAULT_AUTOSAVE_INTERVAL; int start_zeny = 0; int start_weapon = 1201; @@ -174,7 +174,7 @@ struct auth_node { uint32 ip; int sex; time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited) - int gmlevel; + int group_id; unsigned changing_mapservers : 1; }; @@ -1972,12 +1972,12 @@ int parse_fromlogin(int fd) int server_id; memcpy(sd->email, RFIFOP(fd,6), 40); sd->expiration_time = (time_t)RFIFOL(fd,46); - sd->gmlevel = RFIFOB(fd,50); + sd->group_id = RFIFOB(fd,50); safestrncpy(sd->birthdate, (const char*)RFIFOP(fd,51), sizeof(sd->birthdate)); ARR_FIND( 0, ARRAYLENGTH(server), server_id, server[server_id].fd > 0 && server[server_id].map[0] ); // continued from char_auth_ok... if( server_id == ARRAYLENGTH(server) || //server not online, bugreport:2359 - ( max_connect_user && count_users() >= max_connect_user && sd->gmlevel < gm_allow_level ) ) { + ( max_connect_user && count_users() >= max_connect_user && sd->group_id != gm_allow_group ) ) { // refuse connection (over populated) WFIFOHEAD(i,3); WFIFOW(i,0) = 0x6c; @@ -2741,7 +2741,7 @@ int parse_frommap(int fd) node->sex = RFIFOB(fd,30); node->expiration_time = 0; // FIXME (this thing isn't really supported we could as well purge it instead of fixing) node->ip = ntohl(RFIFOL(fd,31)); - node->gmlevel = RFIFOL(fd,35); + node->group_id = RFIFOL(fd,35); node->changing_mapservers = 1; idb_put(auth_db, RFIFOL(fd,2), node); @@ -3102,7 +3102,7 @@ int parse_frommap(int fd) WFIFOL(fd,8) = node->login_id1; WFIFOL(fd,12) = node->login_id2; WFIFOL(fd,16) = (uint32)node->expiration_time; // FIXME: will wrap to negative after "19-Jan-2038, 03:14:07 AM GMT" - WFIFOL(fd,20) = node->gmlevel; + WFIFOL(fd,20) = node->group_id; WFIFOB(fd,24) = node->changing_mapservers; memcpy(WFIFOP(fd,25), cd, sizeof(struct mmo_charstatus)); WFIFOSET(fd, WFIFOW(fd,2)); @@ -3664,7 +3664,7 @@ int parse_char(int fd) node->login_id2 = sd->login_id2; node->sex = sd->sex; node->expiration_time = sd->expiration_time; - node->gmlevel = sd->gmlevel; + node->group_id = sd->group_id; node->ip = ipl; idb_put(auth_db, sd->account_id, node); @@ -4366,10 +4366,8 @@ int char_config_read(const char* cfgName) max_connect_user = atoi(w2); if (max_connect_user < 0) max_connect_user = 0; // unlimited online players - } else if(strcmpi(w1, "gm_allow_level") == 0) { - gm_allow_level = atoi(w2); - if(gm_allow_level < 0) - gm_allow_level = 99; + } else if(strcmpi(w1, "gm_allow_group") == 0) { + gm_allow_group = atoi(w2); } else if (strcmpi(w1, "autosave_time") == 0) { autosave_interval = atoi(w2)*1000; if (autosave_interval <= 0) diff --git a/src/common/Makefile.in b/src/common/Makefile.in index 8dab1d816..7897b6cfb 100644 --- a/src/common/Makefile.in +++ b/src/common/Makefile.in @@ -2,11 +2,13 @@ COMMON_OBJ = obj_all/core.o obj_all/socket.o obj_all/timer.o obj_all/db.o obj_all/plugins.o obj_all/lock.o \ obj_all/nullpo.o obj_all/malloc.o obj_all/showmsg.o obj_all/strlib.o obj_all/utils.o \ obj_all/grfio.o obj_all/mapindex.o obj_all/ers.o obj_all/md5calc.o \ - obj_all/minicore.o obj_all/minisocket.o obj_all/minimalloc.o obj_all/random.o obj_all/des.o + obj_all/minicore.o obj_all/minisocket.o obj_all/minimalloc.o obj_all/random.o obj_all/des.o \ + obj_all/conf.o COMMON_H = mmo.h plugin.h version.h \ core.h socket.h timer.h db.h plugins.h lock.h \ nullpo.h malloc.h showmsg.h strlib.h utils.h \ - grfio.h mapindex.h ers.h md5calc.h random.h des.h + grfio.h mapindex.h ers.h md5calc.h random.h des.h \ + conf.h COMMON_SQL_OBJ = obj_sql/sql.o COMMON_SQL_H = sql.h @@ -15,6 +17,13 @@ MT19937AR_OBJ = ../../3rdparty/mt19937ar/mt19937ar.o MT19937AR_H = ../../3rdparty/mt19937ar/mt19937ar.h MT19937AR_INCLUDE = -I../../3rdparty/mt19937ar +LIBCONFIG_OBJ = ../../3rdparty/libconfig/libconfig.o ../../3rdparty/libconfig/grammar.o \ + ../../3rdparty/libconfig/scanctx.o ../../3rdparty/libconfig/scanner.o ../../3rdparty/libconfig/strbuf.o +LIBCONFIG_H = ../../3rdparty/libconfig/libconfig.h ../../3rdparty/libconfig/grammar.h \ + ../../3rdparty/libconfig/parsectx.h ../../3rdparty/libconfig/scanctx.h ../../3rdparty/libconfig/scanner.h \ + ../../3rdparty/libconfig/strbuf.h ../../3rdparty/libconfig/wincompat.h +LIBCONFIG_INCLUDE = -I../../3rdparty/libconfig + HAVE_MYSQL=@HAVE_MYSQL@ ifeq ($(HAVE_MYSQL),yes) ALL_DEPENDS=txt sql @@ -59,21 +68,24 @@ obj_all: obj_sql: -mkdir obj_sql -common: obj_all $(COMMON_OBJ) $(MT19937AR_OBJ) +common: obj_all $(COMMON_OBJ) $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) common_sql: obj_sql $(COMMON_SQL_OBJ) -obj_all/%.o: %.c $(COMMON_H) $(MT19937AR_H) - @CC@ @CFLAGS@ $(MT19937AR_INCLUDE) @LDFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< +obj_all/%.o: %.c $(COMMON_H) $(MT19937AR_H) $(LIBCONFIG_H) + @CC@ @CFLAGS@ $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) @LDFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< -obj_all/mini%.o: %.c $(COMMON_H) $(MT19937AR_H) - @CC@ @CFLAGS@ $(MT19937AR_INCLUDE) -DMINICORE @LDFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< +obj_all/mini%.o: %.c $(COMMON_H) $(MT19937AR_H) $(LIBCONFIG_H) + @CC@ @CFLAGS@ $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) -DMINICORE @LDFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< -obj_sql/%.o: %.c $(COMMON_H) $(COMMON_SQL_H) - @CC@ @CFLAGS@ @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< +obj_sql/%.o: %.c $(COMMON_H) $(COMMON_SQL_H) $(LIBCONFIG_H) + @CC@ @CFLAGS@ $(LIBCONFIG_INCLUDE) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< # missing object files MT19937AR_OBJ: @$(MAKE) -C ../../3rdparty/mt19937ar + +LIBCONFIG_OBJ: + @$(MAKE) -C ../../3rdparty/libconfig diff --git a/src/common/conf.c b/src/common/conf.c new file mode 100644 index 000000000..eed39d409 --- /dev/null +++ b/src/common/conf.c @@ -0,0 +1,109 @@ +// Copyright (c) Athena Dev Teams - Licensed under GNU GPL +// For more information, see LICENCE in the main folder + +#include "conf.h" +#include <libconfig.h> + +#include "../common/showmsg.h" // ShowError + +int conf_read_file(config_t *config, const char *config_filename) +{ + config_init(config); + if (!config_read_file(config, config_filename)) { + ShowError("%s:%d - %s\n", config_error_file(config), + config_error_line(config), config_error_text(config)); + config_destroy(config); + return 1; + } + return 0; +} + +// +// Functions to copy settings from libconfig/contrib +// +static void config_setting_copy_simple(config_setting_t *parent, const config_setting_t *src); +static void config_setting_copy_elem(config_setting_t *parent, const config_setting_t *src); +static void config_setting_copy_aggregate(config_setting_t *parent, const config_setting_t *src); +int config_setting_copy(config_setting_t *parent, const config_setting_t *src); + +void config_setting_copy_simple(config_setting_t *parent, const config_setting_t *src) +{ + if (config_setting_is_aggregate(src)) { + config_setting_copy_aggregate(parent, src); + } + else { + config_setting_t *set = config_setting_add(parent, config_setting_name(src), config_setting_type(src)); + + if (set == NULL) + return; + + if (CONFIG_TYPE_INT == config_setting_type(src)) { + config_setting_set_int(set, config_setting_get_int(src)); + config_setting_set_format(set, src->format); + } else if (CONFIG_TYPE_INT64 == config_setting_type(src)) { + config_setting_set_int64(set, config_setting_get_int64(src)); + config_setting_set_format(set, src->format); + } else if (CONFIG_TYPE_FLOAT == config_setting_type(src)) { + config_setting_set_float(set, config_setting_get_float(src)); + } else if (CONFIG_TYPE_STRING == config_setting_type(src)) { + config_setting_set_string(set, config_setting_get_string(src)); + } else if (CONFIG_TYPE_BOOL == config_setting_type(src)) { + config_setting_set_bool(set, config_setting_get_bool(src)); + } + } +} + +void config_setting_copy_elem(config_setting_t *parent, const config_setting_t *src) +{ + config_setting_t *set = NULL; + + if (config_setting_is_aggregate(src)) + config_setting_copy_aggregate(parent, src); + else if (CONFIG_TYPE_INT == config_setting_type(src)) { + set = config_setting_set_int_elem(parent, -1, config_setting_get_int(src)); + config_setting_set_format(set, src->format); + } else if (CONFIG_TYPE_INT64 == config_setting_type(src)) { + set = config_setting_set_int64_elem(parent, -1, config_setting_get_int64(src)); + config_setting_set_format(set, src->format); + } else if (CONFIG_TYPE_FLOAT == config_setting_type(src)) { + set = config_setting_set_float_elem(parent, -1, config_setting_get_float(src)); + } else if (CONFIG_TYPE_STRING == config_setting_type(src)) { + set = config_setting_set_string_elem(parent, -1, config_setting_get_string(src)); + } else if (CONFIG_TYPE_BOOL == config_setting_type(src)) { + set = config_setting_set_bool_elem(parent, -1, config_setting_get_bool(src)); + } +} + +void config_setting_copy_aggregate(config_setting_t *parent, const config_setting_t *src) +{ + config_setting_t *newAgg; + int i, n; + + newAgg = config_setting_add(parent, config_setting_name(src), config_setting_type(src)); + + if (newAgg == NULL) + return; + + n = config_setting_length(src); + + for (i = 0; i < n; i++) { + if (config_setting_is_group(src)) { + config_setting_copy_simple(newAgg, config_setting_get_elem(src, i)); + } else { + config_setting_copy_elem(newAgg, config_setting_get_elem(src, i)); + } + } +} + +int config_setting_copy(config_setting_t *parent, const config_setting_t *src) +{ + if (!config_setting_is_group(parent) && !config_setting_is_list(parent)) + return CONFIG_FALSE; + + if (config_setting_is_aggregate(src)) { + config_setting_copy_aggregate(parent, src); + } else { + config_setting_copy_simple(parent, src); + } + return CONFIG_TRUE; +} diff --git a/src/common/conf.h b/src/common/conf.h new file mode 100644 index 000000000..0b70a0c79 --- /dev/null +++ b/src/common/conf.h @@ -0,0 +1,13 @@ +// Copyright (c) Athena Dev Teams - Licensed under GNU GPL +// For more information, see LICENCE in the main folder + +#ifndef _CONF_H_ +#define _CONF_H_ + +#include "../common/cbasetypes.h" +#include <libconfig.h> + +int conf_read_file(config_t *config, const char *config_filename); +int config_setting_copy(config_setting_t *parent, const config_setting_t *src); + +#endif // _CONF_H_
\ No newline at end of file diff --git a/src/common/showmsg.c b/src/common/showmsg.c index 7a6f632e7..b77bf3949 100644 --- a/src/common/showmsg.c +++ b/src/common/showmsg.c @@ -13,6 +13,8 @@ #include <time.h> #include <stdlib.h> // atexit +#include <libconfig.h> + #ifdef WIN32 #define WIN32_LEAN_AND_MEAN #include <windows.h> @@ -872,6 +874,20 @@ int ShowWarning(const char *string, ...) { va_end(ap); return ret; } +int ShowConfigWarning(config_setting_t *config, const char *string, ...) +{ + StringBuf buf; + int ret; + va_list ap; + StringBuf_Init(&buf); + StringBuf_AppendStr(&buf, string); + StringBuf_Printf(&buf, " (%s:%d)\n", config_setting_source_file(config), config_setting_source_line(config)); + va_start(ap, string); + ret = _vShowMessage(MSG_WARNING, StringBuf_Value(&buf), ap); + va_end(ap); + StringBuf_Destroy(&buf); + return ret; +} int ShowDebug(const char *string, ...) { int ret; va_list ap; diff --git a/src/common/showmsg.h b/src/common/showmsg.h index 5f80a4312..839f1dc7e 100644 --- a/src/common/showmsg.h +++ b/src/common/showmsg.h @@ -4,6 +4,8 @@ #ifndef _SHOWMSG_H_ #define _SHOWMSG_H_ +#include <libconfig.h> + // for help with the console colors look here: // http://www.edoceo.com/liberum/?doc=printf-with-color // some code explanation (used here): @@ -92,5 +94,6 @@ extern int ShowWarning(const char *, ...); extern int ShowDebug(const char *, ...); extern int ShowError(const char *, ...); extern int ShowFatalError(const char *, ...); +extern int ShowConfigWarning(config_setting_t *config, const char *string, ...); #endif /* _SHOWMSG_H_ */ diff --git a/src/login/Makefile.in b/src/login/Makefile.in index 7dfe085c0..7938640aa 100644 --- a/src/login/Makefile.in +++ b/src/login/Makefile.in @@ -3,12 +3,13 @@ COMMON_OBJ = ../common/obj_all/core.o ../common/obj_all/socket.o ../common/obj_a ../common/obj_all/db.o ../common/obj_all/plugins.o ../common/obj_all/lock.o \ ../common/obj_all/malloc.o ../common/obj_all/showmsg.o ../common/obj_all/utils.o \ ../common/obj_all/strlib.o ../common/obj_all/mapindex.o \ - ../common/obj_all/ers.o ../common/obj_all/md5calc.o ../common/obj_all/random.o + ../common/obj_all/ers.o ../common/obj_all/md5calc.o ../common/obj_all/random.o \ + ../common/obj_all/conf.o COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h ../common/mmo.h \ ../common/version.h ../common/db.h ../common/plugins.h ../common/lock.h \ ../common/malloc.h ../common/showmsg.h ../common/utils.h ../common/strlib.h \ ../common/mapindex.h \ - ../common/ers.h ../common/md5calc.h ../common/random.h + ../common/ers.h ../common/md5calc.h ../common/random.h ../common/conf.h COMMON_SQL_OBJ = ../common/obj_sql/sql.o COMMON_SQL_H = ../common/sql.h @@ -17,6 +18,13 @@ MT19937AR_OBJ = ../../3rdparty/mt19937ar/mt19937ar.o MT19937AR_H = ../../3rdparty/mt19937ar/mt19937ar.h MT19937AR_INCLUDE = -I../../3rdparty/mt19937ar +LIBCONFIG_OBJ = ../../3rdparty/libconfig/libconfig.o ../../3rdparty/libconfig/grammar.o \ + ../../3rdparty/libconfig/scanctx.o ../../3rdparty/libconfig/scanner.o ../../3rdparty/libconfig/strbuf.o +LIBCONFIG_H = ../../3rdparty/libconfig/libconfig.h ../../3rdparty/libconfig/grammar.h \ + ../../3rdparty/libconfig/parsectx.h ../../3rdparty/libconfig/scanctx.h ../../3rdparty/libconfig/scanner.h \ + ../../3rdparty/libconfig/strbuf.h ../../3rdparty/libconfig/wincompat.h +LIBCONFIG_INCLUDE = -I../../3rdparty/libconfig + LOGIN_OBJ = login.o LOGIN_SQL_OBJ = $(LOGIN_OBJ:%=obj_sql/%) \ obj_sql/account_sql.o obj_sql/ipban_sql.o obj_sql/loginlog_sql.o @@ -62,12 +70,12 @@ obj_sql: #executables login-server_sql: $(LOGIN_SERVER_SQL_DEPENDS) - @CC@ @LDFLAGS@ -o ../../login-server_sql@EXEEXT@ $(LOGIN_SQL_OBJ) $(COMMON_OBJ) $(COMMON_SQL_OBJ) $(MT19937AR_OBJ) @LIBS@ @MYSQL_LIBS@ + @CC@ @LDFLAGS@ -o ../../login-server_sql@EXEEXT@ $(LOGIN_SQL_OBJ) $(COMMON_OBJ) $(COMMON_SQL_OBJ) $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @MYSQL_LIBS@ # login object files -obj_sql/%.o: %.c $(LOGIN_H) $(COMMON_H) $(MT19937AR_H) - @CC@ @CFLAGS@ $(MT19937AR_INCLUDE) -DWITH_SQL @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< +obj_sql/%.o: %.c $(LOGIN_H) $(COMMON_H) $(MT19937AR_H) $(LIBCONFIG_H) + @CC@ @CFLAGS@ $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) -DWITH_SQL @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< # missing object files ../common/obj_all/%.o: @@ -78,3 +86,6 @@ obj_sql/%.o: %.c $(LOGIN_H) $(COMMON_H) $(MT19937AR_H) MT19937AR_OBJ: @$(MAKE) -C ../../3rdparty/mt19937ar + +LIBCONFIG_OBJ: + @$(MAKE) -C ../../3rdparty/libconfig diff --git a/src/login/account.h b/src/login/account.h index 170d60aca..1b567be70 100644 --- a/src/login/account.h +++ b/src/login/account.h @@ -41,7 +41,7 @@ struct mmo_account char pass[32+1]; // 23+1 for plaintext, 32+1 for md5-ed passwords char sex; // gender (M/F/S) char email[40]; // e-mail (by default: a@a.com) - int level; // GM level + int group_id; // player group id unsigned int state; // packet 0x006a value + 1 (0: compte OK) time_t unban_time; // (timestamp): ban time limit of the account (0 = no ban) time_t expiration_time; // (timestamp): validity limit of the account (0 = unlimited) diff --git a/src/login/account_sql.c b/src/login/account_sql.c index bc607c59e..5073941e2 100644 --- a/src/login/account_sql.c +++ b/src/login/account_sql.c @@ -522,7 +522,7 @@ static bool mmo_auth_fromsql(AccountDB_SQL* db, struct mmo_account* acc, int acc // retrieve login entry for the specified account if( SQL_ERROR == Sql_Query(sql_handle, - "SELECT `account_id`,`userid`,`user_pass`,`sex`,`email`,`level`,`state`,`unban_time`,`expiration_time`,`logincount`,`lastlogin`,`last_ip`,`birthdate` FROM `%s` WHERE `account_id` = %d", + "SELECT `account_id`,`userid`,`user_pass`,`sex`,`email`,`group_id`,`state`,`unban_time`,`expiration_time`,`logincount`,`lastlogin`,`last_ip`,`birthdate` FROM `%s` WHERE `account_id` = %d", db->account_db, account_id ) ) { Sql_ShowDebug(sql_handle); @@ -540,7 +540,7 @@ static bool mmo_auth_fromsql(AccountDB_SQL* db, struct mmo_account* acc, int acc Sql_GetData(sql_handle, 2, &data, NULL); safestrncpy(acc->pass, data, sizeof(acc->pass)); Sql_GetData(sql_handle, 3, &data, NULL); acc->sex = data[0]; Sql_GetData(sql_handle, 4, &data, NULL); safestrncpy(acc->email, data, sizeof(acc->email)); - Sql_GetData(sql_handle, 5, &data, NULL); acc->level = atoi(data); + Sql_GetData(sql_handle, 5, &data, NULL); acc->group_id = atoi(data); Sql_GetData(sql_handle, 6, &data, NULL); acc->state = strtoul(data, NULL, 10); Sql_GetData(sql_handle, 7, &data, NULL); acc->unban_time = atol(data); Sql_GetData(sql_handle, 8, &data, NULL); acc->expiration_time = atol(data); @@ -596,14 +596,14 @@ static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, boo if( is_new ) {// insert into account table if( SQL_SUCCESS != SqlStmt_Prepare(stmt, - "INSERT INTO `%s` (`account_id`, `userid`, `user_pass`, `sex`, `email`, `level`, `state`, `unban_time`, `expiration_time`, `logincount`, `lastlogin`, `last_ip`, `birthdate`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + "INSERT INTO `%s` (`account_id`, `userid`, `user_pass`, `sex`, `email`, `group_id`, `state`, `unban_time`, `expiration_time`, `logincount`, `lastlogin`, `last_ip`, `birthdate`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", db->account_db) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_INT, (void*)&acc->account_id, sizeof(acc->account_id)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (void*)acc->userid, strlen(acc->userid)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 2, SQLDT_STRING, (void*)acc->pass, strlen(acc->pass)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 3, SQLDT_ENUM, (void*)&acc->sex, sizeof(acc->sex)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 4, SQLDT_STRING, (void*)&acc->email, strlen(acc->email)) - || SQL_SUCCESS != SqlStmt_BindParam(stmt, 5, SQLDT_INT, (void*)&acc->level, sizeof(acc->level)) + || SQL_SUCCESS != SqlStmt_BindParam(stmt, 5, SQLDT_INT, (void*)&acc->group_id, sizeof(acc->group_id)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 6, SQLDT_UINT, (void*)&acc->state, sizeof(acc->state)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 7, SQLDT_LONG, (void*)&acc->unban_time, sizeof(acc->unban_time)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 8, SQLDT_INT, (void*)&acc->expiration_time, sizeof(acc->expiration_time)) @@ -619,12 +619,12 @@ static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, boo } else {// update account table - if( SQL_SUCCESS != SqlStmt_Prepare(stmt, "UPDATE `%s` SET `userid`=?,`user_pass`=?,`sex`=?,`email`=?,`level`=?,`state`=?,`unban_time`=?,`expiration_time`=?,`logincount`=?,`lastlogin`=?,`last_ip`=?,`birthdate`=? WHERE `account_id` = '%d'", db->account_db, acc->account_id) + if( SQL_SUCCESS != SqlStmt_Prepare(stmt, "UPDATE `%s` SET `userid`=?,`user_pass`=?,`sex`=?,`email`=?,`group_id`=?,`state`=?,`unban_time`=?,`expiration_time`=?,`logincount`=?,`lastlogin`=?,`last_ip`=?,`birthdate`=? WHERE `account_id` = '%d'", db->account_db, acc->account_id) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, (void*)acc->userid, strlen(acc->userid)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (void*)acc->pass, strlen(acc->pass)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 2, SQLDT_ENUM, (void*)&acc->sex, sizeof(acc->sex)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 3, SQLDT_STRING, (void*)acc->email, strlen(acc->email)) - || SQL_SUCCESS != SqlStmt_BindParam(stmt, 4, SQLDT_INT, (void*)&acc->level, sizeof(acc->level)) + || SQL_SUCCESS != SqlStmt_BindParam(stmt, 4, SQLDT_INT, (void*)&acc->group_id, sizeof(acc->group_id)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 5, SQLDT_UINT, (void*)&acc->state, sizeof(acc->state)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 6, SQLDT_LONG, (void*)&acc->unban_time, sizeof(acc->unban_time)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 7, SQLDT_LONG, (void*)&acc->expiration_time, sizeof(acc->expiration_time)) diff --git a/src/login/login.c b/src/login/login.c index 78a9b9420..5a504ce2f 100644 --- a/src/login/login.c +++ b/src/login/login.c @@ -548,7 +548,7 @@ int parse_fromchar(int fd) struct mmo_account acc; time_t expiration_time = 0; char email[40] = ""; - int gmlevel = 0; + int group_id = 0; char birthdate[10+1] = ""; int account_id = RFIFOL(fd,2); @@ -560,7 +560,7 @@ int parse_fromchar(int fd) { safestrncpy(email, acc.email, sizeof(email)); expiration_time = acc.expiration_time; - gmlevel = acc.level; + group_id = acc.group_id; safestrncpy(birthdate, acc.birthdate, sizeof(birthdate)); } @@ -569,7 +569,7 @@ int parse_fromchar(int fd) WFIFOL(fd,2) = account_id; safestrncpy((char*)WFIFOP(fd,6), email, 40); WFIFOL(fd,46) = (uint32)expiration_time; - WFIFOB(fd,50) = gmlevel; + WFIFOB(fd,50) = group_id; safestrncpy((char*)WFIFOP(fd,51), birthdate, 10+1); WFIFOSET(fd,62); } @@ -1068,7 +1068,7 @@ int mmo_auth(struct login_session_data* sd) sd->login_id2 = rnd(); safestrncpy(sd->lastlogin, acc.lastlogin, sizeof(sd->lastlogin)); sd->sex = acc.sex; - sd->level = acc.level; + sd->group_id = acc.group_id; // update account data timestamp2string(acc.lastlogin, sizeof(acc.lastlogin), time(NULL), "%Y-%m-%d %H:%M:%S"); @@ -1104,9 +1104,9 @@ void login_auth_ok(struct login_session_data* sd) return; } - if( sd->level < login_config.min_level_to_connect ) + if( login_config.group_id_to_connect >= 0 && sd->group_id != login_config.group_id_to_connect ) { - ShowStatus("Connection refused: the minimum GM level for connection is %d (account: %s, GM level: %d).\n", login_config.min_level_to_connect, sd->userid, sd->level); + ShowStatus("Connection refused: the required group id for connection is %d (account: %s, group: %d).\n", login_config.group_id_to_connect, sd->userid, sd->group_id); WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x81; WFIFOB(fd,2) = 1; // 01 = Server closed @@ -1161,11 +1161,7 @@ void login_auth_ok(struct login_session_data* sd) } login_log(ip, sd->userid, 100, "login ok"); - - if( sd->level > 0 ) - ShowStatus("Connection of the GM (level:%d) account '%s' accepted.\n", sd->level, sd->userid); - else - ShowStatus("Connection of the account '%s' accepted.\n", sd->userid); + ShowStatus("Connection of the account '%s' accepted.\n", sd->userid); WFIFOHEAD(fd,47+32*server_num); WFIFOW(fd,0) = 0x69; @@ -1508,7 +1504,7 @@ void login_set_defaults() login_config.new_account_flag = true; login_config.new_acc_length_limit = true; login_config.use_md5_passwds = false; - login_config.min_level_to_connect = 0; + login_config.group_id_to_connect = -1; login_config.check_client_version = false; login_config.client_version_to_connect = 20; @@ -1575,8 +1571,8 @@ int login_config_read(const char* cfgName) login_config.client_version_to_connect = strtoul(w2, NULL, 10); else if(!strcmpi(w1, "use_MD5_passwords")) login_config.use_md5_passwds = (bool)config_switch(w2); - else if(!strcmpi(w1, "min_level_to_connect")) - login_config.min_level_to_connect = atoi(w2); + else if(!strcmpi(w1, "group_id_to_connect")) + login_config.group_id_to_connect = atoi(w2); else if(!strcmpi(w1, "date_format")) safestrncpy(login_config.date_format, w2, sizeof(login_config.date_format)); else if(!strcmpi(w1, "console")) diff --git a/src/login/login.h b/src/login/login.h index 3f14ec93c..384372c75 100644 --- a/src/login/login.h +++ b/src/login/login.h @@ -34,7 +34,7 @@ struct login_session_data { uint16 md5keylen; char lastlogin[24]; - uint8 level; + uint8 group_id; uint8 clienttype; uint32 version; @@ -64,7 +64,7 @@ struct Login_Config { bool new_account_flag,new_acc_length_limit; // autoregistration via _M/_F ? / if yes minimum length is 4? int start_limited_time; // new account expiration time (-1: unlimited) bool use_md5_passwds; // work with password hashes instead of plaintext passwords? - int min_level_to_connect; // minimum level of player/GM (0: player, 1-99: GM) to connect + int group_id_to_connect; // required group id to connect bool check_client_version; // check the clientversion set in the clientinfo ? uint32 client_version_to_connect; // the client version needed to connect (if checking is enabled) diff --git a/src/map/Makefile.in b/src/map/Makefile.in index dc0e48bf9..16675086d 100644 --- a/src/map/Makefile.in +++ b/src/map/Makefile.in @@ -4,13 +4,13 @@ COMMON_OBJ = ../common/obj_all/core.o ../common/obj_all/socket.o ../common/obj_a ../common/obj_all/nullpo.o ../common/obj_all/malloc.o ../common/obj_all/showmsg.o \ ../common/obj_all/utils.o ../common/obj_all/strlib.o ../common/obj_all/grfio.o \ ../common/obj_all/mapindex.o ../common/obj_all/ers.o ../common/obj_all/md5calc.o \ - ../common/obj_all/random.o ../common/obj_all/des.o + ../common/obj_all/random.o ../common/obj_all/des.o ../common/obj_all/conf.o COMMON_H = ../common/core.h ../common/socket.h ../common/timer.h \ ../common/db.h ../common/plugins.h ../common/lock.h \ ../common/nullpo.h ../common/malloc.h ../common/showmsg.h \ ../common/utils.h ../common/strlib.h ../common/grfio.h \ ../common/mapindex.h ../common/ers.h ../common/md5calc.h \ - ../common/random.h ../common/des.h + ../common/random.h ../common/des.h ../common/conf.h COMMON_SQL_OBJ = ../common/obj_sql/sql.o COMMON_SQL_H = ../common/sql.h @@ -19,12 +19,19 @@ MT19937AR_OBJ = ../../3rdparty/mt19937ar/mt19937ar.o MT19937AR_H = ../../3rdparty/mt19937ar/mt19937ar.h MT19937AR_INCLUDE = -I../../3rdparty/mt19937ar +LIBCONFIG_OBJ = ../../3rdparty/libconfig/libconfig.o ../../3rdparty/libconfig/grammar.o \ + ../../3rdparty/libconfig/scanctx.o ../../3rdparty/libconfig/scanner.o ../../3rdparty/libconfig/strbuf.o +LIBCONFIG_H = ../../3rdparty/libconfig/libconfig.h ../../3rdparty/libconfig/grammar.h \ + ../../3rdparty/libconfig/parsectx.h ../../3rdparty/libconfig/scanctx.h ../../3rdparty/libconfig/scanner.h \ + ../../3rdparty/libconfig/strbuf.h ../../3rdparty/libconfig/wincompat.h +LIBCONFIG_INCLUDE = -I../../3rdparty/libconfig + MAP_OBJ = map.o chrif.o clif.o pc.o status.o npc.o \ npc_chat.o chat.o path.o itemdb.o mob.o script.o \ storage.o skill.o atcommand.o battle.o battleground.o \ intif.o trade.o party.o vending.o guild.o pet.o \ log.o mail.o date.o unit.o homunculus.o mercenary.o quest.o instance.o \ - buyingstore.o searchstore.o duel.o + buyingstore.o searchstore.o duel.o pc_groups.o MAP_SQL_OBJ = $(MAP_OBJ:%=obj_sql/%) \ obj_sql/mapreg_sql.o MAP_H = map.h chrif.h clif.h pc.h status.h npc.h \ @@ -32,7 +39,7 @@ MAP_H = map.h chrif.h clif.h pc.h status.h npc.h \ storage.h skill.h atcommand.h battle.h battleground.h \ intif.h trade.h party.h vending.h guild.h pet.h \ log.h mail.h date.h unit.h homunculus.h mercenary.h quest.h instance.h mapreg.h \ - buyingstore.h searchstore.h duel.h \ + buyingstore.h searchstore.h duel.h pc_groups.h \ config/Core.h config/Renewal.h config/Secure.h config/Data/Const.h \ config/Skills/General.h config/Skills/Mage_Classes.h config/Skills/Swordsman_Classes.h @@ -95,12 +102,12 @@ obj_sql: # executables map-server_sql: obj_sql $(MAP_SQL_OBJ) $(COMMON_OBJ) $(COMMON_SQL_OBJ) - @CC@ @LDFLAGS@ -o ../../map-server_sql@EXEEXT@ $(MAP_SQL_OBJ) $(COMMON_OBJ) $(COMMON_SQL_OBJ) $(MT19937AR_OBJ) @LIBS@ @PCRE_LIBS@ @MYSQL_LIBS@ + @CC@ @LDFLAGS@ -o ../../map-server_sql@EXEEXT@ $(MAP_SQL_OBJ) $(COMMON_OBJ) $(COMMON_SQL_OBJ) $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @PCRE_LIBS@ @MYSQL_LIBS@ # map object files -obj_sql/%.o: %.c $(MAP_H) $(COMMON_H) $(COMMON_SQL_H) $(MT19937AR_H) - @CC@ @CFLAGS@ $(MT19937AR_INCLUDE) $(PCRE_CFLAGS) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< +obj_sql/%.o: %.c $(MAP_H) $(COMMON_H) $(COMMON_SQL_H) $(MT19937AR_H) $(LIBCONFIG_H) + @CC@ @CFLAGS@ $(MT19937AR_INCLUDE) $(LIBCONFIG_INCLUDE) $(PCRE_CFLAGS) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< # missing object files ../common/obj_all/%.o: @@ -111,3 +118,6 @@ obj_sql/%.o: %.c $(MAP_H) $(COMMON_H) $(COMMON_SQL_H) $(MT19937AR_H) MT19937AR_OBJ: @$(MAKE) -C ../../3rdparty/mt19937ar + +LIBCONFIG_OBJ: + @$(MAKE) -C ../../3rdparty/libconfig diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 701ef0ee8..44249e8af 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -12,6 +12,7 @@ #include "../common/socket.h" #include "../common/strlib.h" #include "../common/utils.h" +#include "../common/conf.h" #include "atcommand.h" #include "battle.h" @@ -24,6 +25,7 @@ #include "log.h" #include "map.h" #include "pc.h" +#include "pc_groups.h" // groupid2name #include "status.h" #include "skill.h" #include "mob.h" @@ -39,54 +41,43 @@ #include "trade.h" #include "unit.h" - #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> -// extern variables -char atcommand_symbol = '@'; // first char of the commands -char charcommand_symbol = '#'; -char* msg_table[MAX_MSG]; // Server messages (0-499 reserved for GM commands, 500-999 reserved for others) - -// local declarations -#define ACMD_FUNC(x) int atcommand_ ## x (const int fd, struct map_session_data* sd, const char* command, const char* message) - -DBMap* atcommand_db = NULL;//name -> AtCommandInfo #define ATCOMMAND_LENGTH 50 +#define ACMD_FUNC(x) static int atcommand_ ## x (const int fd, struct map_session_data* sd, const char* command, const char* message) +#define MAX_MSG 1000 -typedef struct AtCommandInfo { - char command[ATCOMMAND_LENGTH]; - int level; - int level2; +typedef struct AtCommandInfo AtCommandInfo; +typedef struct AliasInfo AliasInfo; + +struct AtCommandInfo { + char command[ATCOMMAND_LENGTH]; AtCommandFunc func; -} AtCommandInfo; +}; -static AtCommandInfo* get_atcommandinfo_byname(const char* name); +struct AliasInfo { + AtCommandInfo *command; + char alias[ATCOMMAND_LENGTH]; +}; -ACMD_FUNC(commands); -ACMD_FUNC(charcommands); -/*========================================= - * Generic variables - *-----------------------------------------*/ -char atcmd_output[CHAT_SIZE_MAX]; -char atcmd_player_name[NAME_LENGTH]; -char atcmd_temp[100]; +char atcommand_symbol = '@'; // first char of the commands +char charcommand_symbol = '#'; -// compare function for sorting high to lowest -int hightolow_compare (const void * a, const void * b) -{ - return ( *(int*)b - *(int*)a ); -} +static char* msg_table[MAX_MSG]; // Server messages (0-499 reserved for GM commands, 500-999 reserved for others) +static DBMap* atcommand_db = NULL; //name -> AtCommandInfo +static DBMap* atcommand_alias_db = NULL; //alias -> AtCommandInfo +static config_t atcommand_config; -// compare function for sorting lowest to highest -int lowtohigh_compare (const void * a, const void * b) -{ - return ( *(int*)a - *(int*)b ); -} +static char atcmd_output[CHAT_SIZE_MAX]; +static char atcmd_player_name[NAME_LENGTH]; + +static AtCommandInfo* get_atcommandinfo_byname(const char *name); // @help +static const char* atcommand_checkalias(const char *aliasname); // @help //----------------------------------------------------------- // Return the message string of the specified number by [Yor] @@ -100,26 +91,6 @@ const char* msg_txt(int msg_number) return "??"; } -//----------------------------------------------------------- -// Returns Players title (from msg_athena.conf) [Lupus] -//----------------------------------------------------------- -static char* player_title_txt(int level) -{ - const char* format; - format = (level >= battle_config.title_lvl8) ? msg_txt(342) - : (level >= battle_config.title_lvl7) ? msg_txt(341) - : (level >= battle_config.title_lvl6) ? msg_txt(340) - : (level >= battle_config.title_lvl5) ? msg_txt(339) - : (level >= battle_config.title_lvl4) ? msg_txt(338) - : (level >= battle_config.title_lvl3) ? msg_txt(337) - : (level >= battle_config.title_lvl2) ? msg_txt(336) - : (level >= battle_config.title_lvl1) ? msg_txt(335) - : ""; - sprintf(atcmd_temp, format, level); - return atcmd_temp; -} - - /*========================================== * Read Message Data *------------------------------------------*/ @@ -447,11 +418,11 @@ ACMD_FUNC(mapmove) if (!map_search_freecell(NULL, m, &x, &y, 10, 10, 1)) x = y = 0; //Invalid cell, use random spot. } - if (map[m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { + if (map[m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { clif_displaymessage(fd, msg_txt(247)); return -1; } - if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { + if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { clif_displaymessage(fd, msg_txt(248)); return -1; } @@ -480,9 +451,9 @@ ACMD_FUNC(where) } pl_sd = map_nick2sd(atcmd_player_name); - if( pl_sd == NULL - || strncmp(pl_sd->status.name,atcmd_player_name,NAME_LENGTH) != 0 - || (battle_config.hide_GM_session && pc_isGM(sd) < pc_isGM(pl_sd) && !(battle_config.who_display_aid && pc_isGM(sd) >= battle_config.who_display_aid)) + if (pl_sd == NULL || + strncmp(pl_sd->status.name, atcmd_player_name, NAME_LENGTH) != 0 || + (pc_has_permission(pl_sd, PC_PERM_HIDE_SESSION) && pc_get_group_level(pl_sd) > pc_get_group_level(sd) && !pc_has_permission(sd, PC_PERM_WHO_DISPLAY_AID)) ) { clif_displaymessage(fd, msg_txt(3)); // Character not found. return -1; @@ -520,13 +491,13 @@ ACMD_FUNC(jumpto) return -1; } - if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) + if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { clif_displaymessage(fd, msg_txt(247)); // You are not authorized to warp to this map. return -1; } - if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) + if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { clif_displaymessage(fd, msg_txt(248)); // You are not authorized to warp from your current map. return -1; @@ -558,7 +529,7 @@ ACMD_FUNC(jump) sscanf(message, "%hd %hd", &x, &y); - if (map[sd->bl.m].flag.noteleport && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { + if (map[sd->bl.m].flag.noteleport && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { clif_displaymessage(fd, msg_txt(248)); // You are not authorized to warp from your current map. return -1; } @@ -591,7 +562,7 @@ ACMD_FUNC(who3) struct map_session_data *pl_sd; struct s_mapiterator* iter; int j, count; - int pl_GM_level, GM_level; + int level; char match_text[100]; char player_name[NAME_LENGTH]; @@ -607,20 +578,19 @@ ACMD_FUNC(who3) match_text[j] = TOLOWER(match_text[j]); count = 0; - GM_level = pc_isGM(sd); + level = pc_get_group_level(sd); iter = mapit_getallusers(); for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) { - pl_GM_level = pc_isGM(pl_sd); - if(!( (battle_config.hide_GM_session || (pl_sd->sc.option & OPTION_INVISIBLE)) && pl_GM_level > GM_level )) + if (!((pc_has_permission(pl_sd, PC_PERM_HIDE_SESSION) || (pl_sd->sc.option & OPTION_INVISIBLE)) && pc_get_group_level(pl_sd) > level)) {// you can look only lower or same level memcpy(player_name, pl_sd->status.name, NAME_LENGTH); for (j = 0; player_name[j]; j++) player_name[j] = TOLOWER(player_name[j]); if (strstr(player_name, match_text) != NULL) { // search with no case sensitive - if (battle_config.who_display_aid > 0 && pc_isGM(sd) >= battle_config.who_display_aid) { + if (pc_has_permission(sd, PC_PERM_WHO_DISPLAY_AID)) { sprintf(atcmd_output, "(CID:%d/AID:%d) ", pl_sd->status.char_id, pl_sd->status.account_id); } else { atcmd_output[0]=0; @@ -629,9 +599,8 @@ ACMD_FUNC(who3) sprintf(temp0, msg_txt(343), pl_sd->status.name); strcat(atcmd_output,temp0); //Player title, if exists - if (pl_GM_level > 0) { - //sprintf(temp0, "(%s) ", player_title_txt(pl_GM_level) ); - sprintf(temp0, msg_txt(344), player_title_txt(pl_GM_level) ); + if (pl_sd->group_id > 0) { + sprintf(temp0, msg_txt(344), pc_group_id2name(pl_sd->group_id) ); strcat(atcmd_output,temp0); } //Players Location: map x y @@ -666,7 +635,7 @@ ACMD_FUNC(who2) struct map_session_data *pl_sd; struct s_mapiterator* iter; int j, count; - int pl_GM_level, GM_level; + int pl_level, level; char match_text[100]; char player_name[NAME_LENGTH]; @@ -682,13 +651,13 @@ ACMD_FUNC(who2) match_text[j] = TOLOWER(match_text[j]); count = 0; - GM_level = pc_isGM(sd); + level = pc_get_group_level(sd); iter = mapit_getallusers(); for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) { - pl_GM_level = pc_isGM(pl_sd); - if(!( (battle_config.hide_GM_session || (pl_sd->sc.option & OPTION_INVISIBLE)) && (pl_GM_level > GM_level) )) + pl_level = pc_get_group_level(pl_sd); + if (!((pc_has_permission(pl_sd, PC_PERM_HIDE_SESSION) || (pl_sd->sc.option & OPTION_INVISIBLE)) && pc_get_group_level(pl_sd) > level)) {// you can look only lower or same level memcpy(player_name, pl_sd->status.name, NAME_LENGTH); for (j = 0; player_name[j]; j++) @@ -698,9 +667,8 @@ ACMD_FUNC(who2) //sprintf(atcmd_output, "Name: %s ", pl_sd->status.name); sprintf(atcmd_output, msg_txt(343), pl_sd->status.name); //Player title, if exists - if (pl_GM_level > 0) { - //sprintf(temp0, "(%s) ", player_title_txt(pl_GM_level) ); - sprintf(temp0, msg_txt(344), player_title_txt(pl_GM_level) ); + if (pl_sd->group_id > 0) { + sprintf(temp0, msg_txt(344), pc_group_id2name(pl_sd->group_id) ); strcat(atcmd_output,temp0); } //Players Base Level / Job name @@ -736,7 +704,7 @@ ACMD_FUNC(who) struct map_session_data *pl_sd; struct s_mapiterator* iter; int j, count; - int pl_GM_level, GM_level; + int pl_level, level; char match_text[100]; char player_name[NAME_LENGTH]; struct guild *g; @@ -755,13 +723,13 @@ ACMD_FUNC(who) match_text[j] = TOLOWER(match_text[j]); count = 0; - GM_level = pc_isGM(sd); + level = pc_get_group_level(sd); iter = mapit_getallusers(); for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) { - pl_GM_level = pc_isGM(pl_sd); - if(!( (battle_config.hide_GM_session || (pl_sd->sc.option & OPTION_INVISIBLE)) && pl_GM_level > GM_level )) + pl_level = pc_get_group_level(pl_sd); + if (!((pc_has_permission(pl_sd, PC_PERM_HIDE_SESSION) || (pl_sd->sc.option & OPTION_INVISIBLE)) && pc_get_group_level(pl_sd) > level)) {// you can look only lower or same level memcpy(player_name, pl_sd->status.name, NAME_LENGTH); for (j = 0; player_name[j]; j++) @@ -772,8 +740,8 @@ ACMD_FUNC(who) //Players Name sprintf(atcmd_output, msg_txt(343), pl_sd->status.name); //Player title, if exists - if (pl_GM_level > 0) { - sprintf(temp0, msg_txt(344), player_title_txt(pl_GM_level) ); + if (pl_sd->group_id > 0) { + sprintf(temp0, msg_txt(344), pc_group_id2name(pl_sd->group_id) ); strcat(atcmd_output,temp0); } //Players Party if exists @@ -815,7 +783,7 @@ ACMD_FUNC(whomap3) struct map_session_data *pl_sd; struct s_mapiterator* iter; int count; - int pl_GM_level, GM_level; + int pl_level, level; int map_id; char map_name[MAP_NAME_LENGTH_EXT]; @@ -831,19 +799,19 @@ ACMD_FUNC(whomap3) } count = 0; - GM_level = pc_isGM(sd); + level = pc_get_group_level(sd); iter = mapit_getallusers(); for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) { - pl_GM_level = pc_isGM(pl_sd); + pl_level = pc_get_group_level(pl_sd); if( pl_sd->bl.m != map_id ) continue; - if( (battle_config.hide_GM_session || (pl_sd->sc.option & OPTION_INVISIBLE)) && (pl_GM_level > GM_level) ) + if ((pc_has_permission(pl_sd, PC_PERM_HIDE_SESSION) || (pl_sd->sc.option & OPTION_INVISIBLE)) && pl_level > level) continue; - if (pl_GM_level > 0) - sprintf(atcmd_output, "Name: %s (GM:%d) | Location: %s %d %d", pl_sd->status.name, pl_GM_level, mapindex_id2name(pl_sd->mapindex), pl_sd->bl.x, pl_sd->bl.y); + if (pl_level > 0) + sprintf(atcmd_output, "Name: %s (GM:%d) | Location: %s %d %d", pl_sd->status.name, pl_level, mapindex_id2name(pl_sd->mapindex), pl_sd->bl.x, pl_sd->bl.y); else sprintf(atcmd_output, "Name: %s | Location: %s %d %d", pl_sd->status.name, mapindex_id2name(pl_sd->mapindex), pl_sd->bl.x, pl_sd->bl.y); clif_displaymessage(fd, atcmd_output); @@ -871,7 +839,7 @@ ACMD_FUNC(whomap2) struct map_session_data *pl_sd; struct s_mapiterator* iter; int count; - int pl_GM_level, GM_level; + int pl_level, level; int map_id = 0; char map_name[MAP_NAME_LENGTH_EXT]; @@ -889,19 +857,19 @@ ACMD_FUNC(whomap2) } count = 0; - GM_level = pc_isGM(sd); + level = pc_get_group_level(sd); iter = mapit_getallusers(); for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) { - pl_GM_level = pc_isGM(pl_sd); + pl_level = pc_get_group_level(pl_sd); if( pl_sd->bl.m != map_id ) continue; - if( (battle_config.hide_GM_session || (pl_sd->sc.option & OPTION_INVISIBLE)) && (pl_GM_level > GM_level) ) + if ((pc_has_permission(pl_sd, PC_PERM_HIDE_SESSION) || (pl_sd->sc.option & OPTION_INVISIBLE)) && pl_level > level) continue; - if (pl_GM_level > 0) - sprintf(atcmd_output, "Name: %s (GM:%d) | BLvl: %d | Job: %s (Lvl: %d)", pl_sd->status.name, pl_GM_level, pl_sd->status.base_level, job_name(pl_sd->status.class_), pl_sd->status.job_level); + if (pl_level > 0) + sprintf(atcmd_output, "Name: %s (GM:%d) | BLvl: %d | Job: %s (Lvl: %d)", pl_sd->status.name, pl_level, pl_sd->status.base_level, job_name(pl_sd->status.class_), pl_sd->status.job_level); else sprintf(atcmd_output, "Name: %s | BLvl: %d | Job: %s (Lvl: %d)", pl_sd->status.name, pl_sd->status.base_level, job_name(pl_sd->status.class_), pl_sd->status.job_level); clif_displaymessage(fd, atcmd_output); @@ -931,7 +899,7 @@ ACMD_FUNC(whomap) struct map_session_data *pl_sd; struct s_mapiterator* iter; int count; - int pl_GM_level, GM_level; + int pl_level, level; int map_id = 0; char map_name[MAP_NAME_LENGTH_EXT]; struct guild *g; @@ -953,15 +921,15 @@ ACMD_FUNC(whomap) } count = 0; - GM_level = pc_isGM(sd); + level = pc_get_group_level(sd); iter = mapit_getallusers(); for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) { - pl_GM_level = pc_isGM(pl_sd); + pl_level = pc_get_group_level(pl_sd); if( pl_sd->bl.m != map_id ) continue; - if( (battle_config.hide_GM_session || (pl_sd->sc.option & OPTION_INVISIBLE)) && (pl_GM_level > GM_level) ) + if ((pc_has_permission(pl_sd, PC_PERM_HIDE_SESSION) || (pl_sd->sc.option & OPTION_INVISIBLE)) && pl_level > level) continue; g = guild_search(pl_sd->status.guild_id); @@ -974,8 +942,8 @@ ACMD_FUNC(whomap) sprintf(temp0, "None"); else sprintf(temp0, "%s", p->party.name); - if (pl_GM_level > 0) - sprintf(atcmd_output, "Name: %s (GM:%d) | Party: '%s' | Guild: '%s'", pl_sd->status.name, pl_GM_level, temp0, temp1); + if (pl_level > 0) + sprintf(atcmd_output, "Name: %s (GM:%d) | Party: '%s' | Guild: '%s'", pl_sd->status.name, pl_level, temp0, temp1); else sprintf(atcmd_output, "Name: %s | Party: '%s' | Guild: '%s'", pl_sd->status.name, temp0, temp1); clif_displaymessage(fd, atcmd_output); @@ -1003,7 +971,7 @@ ACMD_FUNC(whogm) struct map_session_data* pl_sd; struct s_mapiterator* iter; int j, count; - int pl_GM_level, GM_level; + int pl_level, level; char match_text[CHAT_SIZE_MAX]; char player_name[NAME_LENGTH]; struct guild *g; @@ -1021,13 +989,13 @@ ACMD_FUNC(whogm) match_text[j] = TOLOWER(match_text[j]); count = 0; - GM_level = pc_isGM(sd); + level = pc_get_group_level(sd); iter = mapit_getallusers(); for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) { - pl_GM_level = pc_isGM(pl_sd); - if (!pl_GM_level) + pl_level = pc_get_group_level(pl_sd); + if (!pl_level) continue; if (match_text[0]) @@ -1039,7 +1007,7 @@ ACMD_FUNC(whogm) if (strstr(player_name, match_text) == NULL) continue; } - if (pl_GM_level > GM_level) { + if (pl_level > level) { if (pl_sd->sc.option & OPTION_INVISIBLE) continue; sprintf(atcmd_output, "Name: %s (GM)", pl_sd->status.name); @@ -1049,7 +1017,7 @@ ACMD_FUNC(whogm) } sprintf(atcmd_output, "Name: %s (GM:%d) | Location: %s %d %d", - pl_sd->status.name, pl_GM_level, + pl_sd->status.name, pl_level, mapindex_id2name(pl_sd->mapindex), pl_sd->bl.x, pl_sd->bl.y); clif_displaymessage(fd, atcmd_output); @@ -1109,11 +1077,11 @@ ACMD_FUNC(load) nullpo_retr(-1, sd); m = map_mapindex2mapid(sd->status.save_point.map); - if (m >= 0 && map[m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { + if (m >= 0 && map[m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { clif_displaymessage(fd, msg_txt(249)); // You are not authorized to warp to your save map. return -1; } - if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { + if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { clif_displaymessage(fd, msg_txt(248)); // You are not authorized to warp from your current map. return -1; } @@ -1552,7 +1520,7 @@ ACMD_FUNC(kill) return -1; } - if (pc_isGM(sd) < pc_isGM(pl_sd)) + if (pc_get_group_level(sd) < pc_get_group_level(pl_sd)) { // you can kill only lower or same level clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. return -1; @@ -1941,78 +1909,69 @@ ACMD_FUNC(joblevelup) *------------------------------------------*/ ACMD_FUNC(help) { - char buf[2048], w1[2048], w2[2048]; - int i, gm_level; - FILE* fp; - nullpo_retr(-1, sd); + config_setting_t *help; + const char *text = NULL; + const char *command_name = NULL; + char *default_command = "help"; - memset(buf, '\0', sizeof(buf)); + nullpo_retr(-1, sd); - if ((fp = fopen(help_txt, "r")) != NULL) { - clif_displaymessage(fd, msg_txt(26)); // Help commands: - gm_level = pc_isGM(sd); - while(fgets(buf, sizeof(buf), fp) != NULL) { - if (buf[0] == '/' && buf[1] == '/') - continue; - for (i = 0; buf[i] != '\0'; i++) { - if (buf[i] == '\r' || buf[i] == '\n') { - buf[i] = '\0'; - break; - } - } - if (sscanf(buf, "%2047[^:]:%2047[^\n]", w1, w2) < 2) - clif_displaymessage(fd, buf); - else if (gm_level >= atoi(w1)) - clif_displaymessage(fd, w2); - } - fclose(fp); - } else { - clif_displaymessage(fd, msg_txt(27)); // File help.txt not found. + help = config_lookup(&atcommand_config, "help"); + if (help == NULL) { + clif_displaymessage(fd, msg_txt(27)); // "Commands help is not available." return -1; } - return 0; -} + if (!message || !*message) { + command_name = default_command; // If no command_name specified, display help for @help. + } else { + if (*message == atcommand_symbol || *message == charcommand_symbol) + ++message; + command_name = atcommand_checkalias(message); + } -/*========================================== - * @help2 - Char commands [Kayla] - *------------------------------------------*/ -ACMD_FUNC(help2) -{ - char buf[2048], w1[2048], w2[2048]; - int i, gm_level; - FILE* fp; - nullpo_retr(-1, sd); + if (!pc_can_use_command(sd, command_name, COMMAND_ATCOMMAND)) { + sprintf(atcmd_output, msg_txt(153), message); // "%s is Unknown Command" + clif_displaymessage(fd, atcmd_output); + return -1; + } + + if (!config_setting_lookup_string(help, command_name, &text)) { + clif_displaymessage(fd, "There is no help for this command_name."); + return -1; + } - memset(buf, '\0', sizeof(buf)); + sprintf(atcmd_output, "Help for command %c%s:", atcommand_symbol, command_name); + clif_displaymessage(fd, atcmd_output); - if ((fp = fopen(help2_txt, "r")) != NULL) { - clif_displaymessage(fd, msg_txt(26)); // Help commands: - gm_level = pc_isGM(sd); - while(fgets(buf, sizeof(buf), fp) != NULL) { - if (buf[0] == '/' && buf[1] == '/') - continue; - for (i = 0; buf[i] != '\0'; i++) { - if (buf[i] == '\r' || buf[i] == '\n') { - buf[i] = '\0'; - break; - } + { // Display aliases + DBIterator* iter; + AtCommandInfo *command_info; + AliasInfo *alias_info = NULL; + StringBuf buf; + bool has_aliases = false; + + StringBuf_Init(&buf); + StringBuf_AppendStr(&buf, "Available aliases:"); + command_info = get_atcommandinfo_byname(command_name); + iter = db_iterator(atcommand_alias_db); + for (alias_info = (AliasInfo*)dbi_first(iter); dbi_exists(iter); alias_info = (AliasInfo*)dbi_next(iter)) { + if (alias_info->command == command_info) { + StringBuf_Printf(&buf, " %s", alias_info->alias); + has_aliases = true; } - if (sscanf(buf, "%2047[^:]:%2047[^\n]", w1, w2) < 2) - clif_displaymessage(fd, buf); - else if (gm_level >= atoi(w1)) - clif_displaymessage(fd, w2); } - fclose(fp); - } else { - clif_displaymessage(fd, msg_txt(27)); // File help.txt not found. - return -1; + iter->destroy(iter); + if (has_aliases) + clif_displaymessage(fd, StringBuf_Value(&buf)); + StringBuf_Destroy(&buf); } + // Display help contents + clif_displaymessage(fd, text); return 0; } - // helper function, used in foreach calls to stop auto-attack timers // parameter: '0' - everyone, 'id' - only those attacking someone with that id static int atcommand_stopattack(struct block_list *bl,va_list ap) @@ -2304,7 +2263,7 @@ ACMD_FUNC(go) nullpo_retr(-1, sd); - if( map[sd->bl.m].flag.nogo && battle_config.any_warp_GM_min_level > pc_isGM(sd) ) { + if( map[sd->bl.m].flag.nogo && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE) ) { clif_displaymessage(sd->fd,"You can not use @go on this map."); return 0; } @@ -2429,11 +2388,11 @@ ACMD_FUNC(go) if (town >= 0 && town < ARRAYLENGTH(data)) { m = map_mapname2mapid(data[town].map); - if (m >= 0 && map[m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { + if (m >= 0 && map[m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { clif_displaymessage(fd, msg_txt(247)); return -1; } - if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { + if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { clif_displaymessage(fd, msg_txt(248)); return -1; } @@ -2458,6 +2417,7 @@ ACMD_FUNC(monster) { char name[NAME_LENGTH]; char monster[NAME_LENGTH]; + char eventname[EVENT_NAME_LENGTH] = ""; int mob_id; int number = 0; int count; @@ -2513,6 +2473,11 @@ ACMD_FUNC(monster) if (battle_config.atc_spawn_quantity_limit && number > battle_config.atc_spawn_quantity_limit) number = battle_config.atc_spawn_quantity_limit; + if (strcmp(command+1, "monstersmall") == 0) + strcpy(eventname, "2"); + else if (strcmp(command+1, "monsterbig") == 0) + strcpy(eventname, "4"); + if (battle_config.etc_log) ShowInfo("%s monster='%s' name='%s' id=%d count=%d (%d,%d)\n", command, monster, name, mob_id, number, sd->bl.x, sd->bl.y); @@ -2520,7 +2485,7 @@ ACMD_FUNC(monster) range = (int)sqrt((float)number) +2; // calculation of an odd number (+ 4 area around) for (i = 0; i < number; i++) { map_search_freecell(&sd->bl, 0, &mx, &my, range, range, 0); - k = mob_once_spawn(sd, sd->bl.m, mx, my, name, mob_id, 1, ""); + k = mob_once_spawn(sd, sd->bl.m, mx, my, name, mob_id, 1, eventname); count += (k != 0) ? 1 : 0; } @@ -2539,159 +2504,6 @@ ACMD_FUNC(monster) return 0; } -// small monster spawning [Valaris] -ACMD_FUNC(monstersmall) -{ - char name[NAME_LENGTH] = ""; - char monster[NAME_LENGTH] = ""; - int mob_id = 0; - int number = 0; - int x = 0; - int y = 0; - int count; - int i; - - nullpo_retr(-1, sd); - - if (!message || !*message) { - clif_displaymessage(fd, "Give a monster name/id please."); - return -1; - } - - if (sscanf(message, "\"%23[^\"]\" %23s %d %d %d", name, monster, &number, &x, &y) < 2 && - sscanf(message, "%23s \"%23[^\"]\" %d %d %d", monster, name, &number, &x, &y) < 2 && - sscanf(message, "%23s %d %23s %d %d", monster, &number, name, &x, &y) < 1) { - clif_displaymessage(fd, "Give a monster name/id please."); - return -1; - } - - // If monster identifier/name argument is a name - if ((mob_id = mobdb_searchname(monster)) == 0) // check name first (to avoid possible name begining by a number) - mob_id = atoi(monster); - - if (mob_id == 0) { - clif_displaymessage(fd, msg_txt(40)); - return -1; - } - - if (mob_id == MOBID_EMPERIUM) { - clif_displaymessage(fd, msg_txt(83)); // Cannot spawn emperium - return -1; - } - - if (mobdb_checkid(mob_id) == 0) { - clif_displaymessage(fd, "Invalid monster ID"); // Invalid Monster ID. - return -1; - } - - if (number <= 0) - number = 1; - - if( !name[0] ) - strcpy(name, "--ja--"); - - // If value of atcommand_spawn_quantity_limit directive is greater than or equal to 1 and quantity of monsters is greater than value of the directive - if (battle_config.atc_spawn_quantity_limit >= 1 && number > battle_config.atc_spawn_quantity_limit) - number = battle_config.atc_spawn_quantity_limit; - - count = 0; - for (i = 0; i < number; i++) { - int mx, my; - if (x <= 0) - mx = sd->bl.x + (rnd() % 11 - 5); - else - mx = x; - if (y <= 0) - my = sd->bl.y + (rnd() % 11 - 5); - else - my = y; - count += (mob_once_spawn(sd, sd->bl.m, mx, my, name, mob_id, 1, "2") != 0) ? 1 : 0; - } - - if (count != 0) - clif_displaymessage(fd, msg_txt(39)); // Monster Summoned!! - else - clif_displaymessage(fd, msg_txt(40)); // Invalid Monster ID. - - return 0; -} -// big monster spawning [Valaris] -ACMD_FUNC(monsterbig) -{ - char name[NAME_LENGTH] = ""; - char monster[NAME_LENGTH] = ""; - int mob_id = 0; - int number = 0; - int x = 0; - int y = 0; - int count; - int i; - - nullpo_retr(-1, sd); - - if (!message || !*message) { - clif_displaymessage(fd, "Give a monster name/id please."); - return -1; - } - - if (sscanf(message, "\"%23[^\"]\" %23s %d %d %d", name, monster, &number, &x, &y) < 2 && - sscanf(message, "%23s \"%23[^\"]\" %d %d %d", monster, name, &number, &x, &y) < 2 && - sscanf(message, "%23s %d %23s %d %d", monster, &number, name, &x, &y) < 1) { - clif_displaymessage(fd, "Give a monster name/id please."); - return -1; - } - - // If monster identifier/name argument is a name - if ((mob_id = mobdb_searchname(monster)) == 0) // check name first (to avoid possible name begining by a number) - mob_id = atoi(monster); - - if (mob_id == 0) { - clif_displaymessage(fd, msg_txt(40)); - return -1; - } - - if (mob_id == MOBID_EMPERIUM) { - clif_displaymessage(fd, msg_txt(83)); // Cannot spawn emperium - return -1; - } - - if (mobdb_checkid(mob_id) == 0) { - clif_displaymessage(fd, "Invalid monster ID"); // Invalid Monster ID. - return -1; - } - - if (number <= 0) - number = 1; - - if( !name[0] ) - strcpy(name, "--ja--"); - - // If value of atcommand_spawn_quantity_limit directive is greater than or equal to 1 and quantity of monsters is greater than value of the directive - if (battle_config.atc_spawn_quantity_limit >= 1 && number > battle_config.atc_spawn_quantity_limit) - number = battle_config.atc_spawn_quantity_limit; - - count = 0; - for (i = 0; i < number; i++) { - int mx, my; - if (x <= 0) - mx = sd->bl.x + (rnd() % 11 - 5); - else - mx = x; - if (y <= 0) - my = sd->bl.y + (rnd() % 11 - 5); - else - my = y; - count += (mob_once_spawn(sd, sd->bl.m, mx, my, name, mob_id, 1, "4") != 0) ? 1 : 0; - } - - if (count != 0) - clif_displaymessage(fd, msg_txt(39)); // Monster Summoned!! - else - clif_displaymessage(fd, msg_txt(40)); // Invalid Monster ID. - - return 0; -} - /*========================================== * *------------------------------------------*/ @@ -3443,17 +3255,17 @@ ACMD_FUNC(recall) return -1; } - if ( pc_isGM(sd) < pc_isGM(pl_sd) ) + if ( pc_get_group_level(sd) < pc_get_group_level(pl_sd) ) { clif_displaymessage(fd, msg_txt(81)); // Your GM level doesn't authorize you to preform this action on the specified player. return -1; } - if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { - clif_displaymessage(fd, "You are not authorised to warp somenone to your actual map."); + if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { + clif_displaymessage(fd, "You are not authorised to warp someone to your actual map."); return -1; } - if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { + if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { clif_displaymessage(fd, "You are not authorized to warp this player from its actual map."); return -1; } @@ -3571,7 +3383,7 @@ ACMD_FUNC(char_ban) tmtime->tm_min = tmtime->tm_min + minute; tmtime->tm_sec = tmtime->tm_sec + second; timestamp = mktime(tmtime); - if( timestamp <= time(NULL) && get_atcommand_level("unban") > pc_isGM(sd) ) { + if( timestamp <= time(NULL) && !pc_can_use_command(sd, "unban", COMMAND_ATCOMMAND) ) { clif_displaymessage(fd,"You are not allowed to reduce the length of a ban"); return -1; } @@ -3671,7 +3483,7 @@ ACMD_FUNC(doom) iter = mapit_getallusers(); for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) { - if (pl_sd->fd != fd && pc_isGM(sd) >= pc_isGM(pl_sd)) + if (pl_sd->fd != fd && pc_get_group_level(sd) >= pc_get_group_level(pl_sd)) { status_kill(&pl_sd->bl); clif_specialeffect(&pl_sd->bl,450,AREA); @@ -3698,7 +3510,7 @@ ACMD_FUNC(doommap) iter = mapit_getallusers(); for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) { - if (pl_sd->fd != fd && sd->bl.m == pl_sd->bl.m && pc_isGM(sd) >= pc_isGM(pl_sd)) + if (pl_sd->fd != fd && sd->bl.m == pl_sd->bl.m && pc_get_group_level(sd) >= pc_get_group_level(pl_sd)) { status_kill(&pl_sd->bl); clif_specialeffect(&pl_sd->bl,450,AREA); @@ -3788,7 +3600,7 @@ ACMD_FUNC(kick) return -1; } - if ( pc_isGM(sd) < pc_isGM(pl_sd) ) + if ( pc_get_group_level(sd) < pc_get_group_level(pl_sd) ) { clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. return -1; @@ -3811,7 +3623,7 @@ ACMD_FUNC(kickall) iter = mapit_getallusers(); for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) { - if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can kick only lower or same gm level + if (pc_get_group_level(sd) >= pc_get_group_level(pl_sd)) { // you can kick only lower or same gm level if (sd->status.account_id != pl_sd->status.account_id) clif_GM_kick(NULL, pl_sd); } @@ -4104,7 +3916,7 @@ ACMD_FUNC(recallall) memset(atcmd_output, '\0', sizeof(atcmd_output)); - if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { + if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { clif_displaymessage(fd, "You are not authorised to warp somenone to your actual map."); return -1; } @@ -4113,9 +3925,9 @@ ACMD_FUNC(recallall) iter = mapit_getallusers(); for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) { - if (sd->status.account_id != pl_sd->status.account_id && pc_isGM(sd) >= pc_isGM(pl_sd)) + if (sd->status.account_id != pl_sd->status.account_id && pc_get_group_level(sd) >= pc_get_group_level(pl_sd)) { - if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) + if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) count++; else { if (pc_isdead(pl_sd)) { //Wake them up @@ -4157,7 +3969,7 @@ ACMD_FUNC(guildrecall) return -1; } - if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { + if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { clif_displaymessage(fd, "You are not authorised to warp somenone to your actual map."); return -1; } @@ -4176,9 +3988,9 @@ ACMD_FUNC(guildrecall) { if (sd->status.account_id != pl_sd->status.account_id && pl_sd->status.guild_id == g->guild_id) { - if (pc_isGM(pl_sd) > pc_isGM(sd)) + if (pc_get_group_level(pl_sd) > pc_get_group_level(sd)) continue; //Skip GMs greater than you. - if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) + if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) count++; else pc_setpos(pl_sd, sd->mapindex, sd->bl.x, sd->bl.y, CLR_RESPAWN); @@ -4216,7 +4028,7 @@ ACMD_FUNC(partyrecall) return -1; } - if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd)) { + if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { clif_displaymessage(fd, "You are not authorised to warp somenone to your actual map."); return -1; } @@ -4235,9 +4047,9 @@ ACMD_FUNC(partyrecall) { if (sd->status.account_id != pl_sd->status.account_id && pl_sd->status.party_id == p->party.party_id) { - if (pc_isGM(pl_sd) > pc_isGM(sd)) + if (pc_get_group_level(pl_sd) > pc_get_group_level(sd)) continue; //Skip GMs greater than you. - if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd)) + if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) count++; else pc_setpos(pl_sd, sd->mapindex, sd->bl.x, sd->bl.y, CLR_RESPAWN); @@ -4297,11 +4109,12 @@ ACMD_FUNC(reloadskilldb) } /*========================================== - * @reloadatcommand - reloads atcommand_athena.conf + * @reloadatcommand - reloads atcommand_athena.conf groups.conf *------------------------------------------*/ void atcommand_doload(); ACMD_FUNC(reloadatcommand) { atcommand_doload(); + pc_groups_reload(); clif_displaymessage(fd, msg_txt(254)); return 0; } @@ -4833,7 +4646,7 @@ ACMD_FUNC(nuke) } if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) { - if (pc_isGM(sd) >= pc_isGM(pl_sd)) { // you can kill only lower or same GM level + if (pc_get_group_level(sd) >= pc_get_group_level(pl_sd)) { // you can kill only lower or same GM level skill_castend_nodamage_id(&pl_sd->bl, &pl_sd->bl, NPC_SELFDESTRUCTION, 99, gettick(), 0); clif_displaymessage(fd, msg_txt(109)); // Player has been nuked! } else { @@ -5143,7 +4956,7 @@ ACMD_FUNC(jail) return -1; } - if (pc_isGM(sd) < pc_isGM(pl_sd)) + if (pc_get_group_level(sd) < pc_get_group_level(pl_sd)) { // you can jail only lower or same GM clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. return -1; @@ -5195,7 +5008,7 @@ ACMD_FUNC(unjail) return -1; } - if (pc_isGM(sd) < pc_isGM(pl_sd)) { // you can jail only lower or same GM + if (pc_get_group_level(sd) < pc_get_group_level(pl_sd)) { // you can jail only lower or same GM clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. return -1; @@ -5275,7 +5088,7 @@ ACMD_FUNC(jailfor) return -1; } - if (pc_isGM(pl_sd) > pc_isGM(sd)) { + if (pc_get_group_level(pl_sd) > pc_get_group_level(sd)) { clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. return -1; } @@ -5859,7 +5672,7 @@ ACMD_FUNC(useskill) return -1; } - if ( pc_isGM(sd) < pc_isGM(pl_sd) ) + if ( pc_get_group_level(sd) < pc_get_group_level(pl_sd) ) { clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. return -1; @@ -6817,76 +6630,29 @@ ACMD_FUNC(summon) } /*========================================== - * @adjcmdlvl by [MouseJstr] - * - * Temp adjust the GM level required to use a GM command - * Useful during beta testing to allow players to use GM commands for short periods of time - *------------------------------------------*/ -ACMD_FUNC(adjcmdlvl) -{ - int newlev, newremotelev; - char name[100]; - AtCommandInfo* cmd; - - nullpo_retr(-1, sd); - - if (!message || !*message || sscanf(message, "%d %d %99s", &newlev, &newremotelev, name) != 3) - { - clif_displaymessage(fd, "Usage: @adjcmdlvl <lvl> <remote lvl> <command>."); - return -1; - } - - cmd = get_atcommandinfo_byname(name); - if (cmd == NULL) - { - clif_displaymessage(fd, "@command not found."); - return -1; - } - else if (newlev > pc_isGM(sd) || newremotelev > pc_isGM(sd) ) - { - clif_displaymessage(fd, "You can't make a command require higher GM level than your own."); - return -1; - } - else if (cmd->level > pc_isGM(sd) || cmd->level2 > pc_isGM(sd) ) - { - clif_displaymessage(fd, "You can't adjust the level of a command which's level is above your own."); - return -1; - } - else - { - cmd->level = newlev; - cmd->level2 = newremotelev; - clif_displaymessage(fd, "@command level changed."); - return 0; - } -} - -/*========================================== - * @adjgmlvl by [MouseJstr] - * Create a temp GM + * @adjgroup + * Temporarily move player to another group * Useful during beta testing to allow players to use GM commands for short periods of time *------------------------------------------*/ -ACMD_FUNC(adjgmlvl) +ACMD_FUNC(adjgroup) { - int newlev; - char user[NAME_LENGTH]; - struct map_session_data *pl_sd; + int new_group = 0; nullpo_retr(-1, sd); - if (!message || !*message || sscanf(message, "%d %23[^\r\n]", &newlev, user) != 2) { - clif_displaymessage(fd, "Usage: @adjgmlvl <lvl> <user>."); + if (!message || !*message || sscanf(message, "%d", &new_group) != 1) { + clif_displaymessage(fd, "Usage: @adjgroup <group_id>"); return -1; } - if ( (pl_sd = map_nick2sd(user)) == NULL ) - { - clif_displaymessage(fd, msg_txt(3)); // Character not found. + if (!pc_group_exists(new_group)) { + clif_displaymessage(fd, "Specified group does not exists."); return -1; } - - pl_sd->gmlevel = newlev; - - return 0; + + sd->group_id = new_group; + clif_displaymessage(fd, "Group changed successfully."); + clif_displaymessage(sd->fd, "Your group has changed."); + return 0; } /*========================================== @@ -7023,7 +6789,7 @@ ACMD_FUNC(mute) return -1; } - if ( pc_isGM(sd) < pc_isGM(pl_sd) ) + if ( pc_get_group_level(sd) < pc_get_group_level(pl_sd) ) { clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. return -1; @@ -7819,7 +7585,7 @@ static int atcommand_mutearea_sub(struct block_list *bl,va_list ap) id = va_arg(ap, int); time = va_arg(ap, int); - if (id != bl->id && !pc_isGM(pl_sd)) { + if (id != bl->id && !pc_get_group_level(pl_sd)) { pl_sd->status.manner -= time; if (pl_sd->status.manner < 0) sc_start(&pl_sd->bl,SC_NOCHAT,100,0,0); @@ -8316,7 +8082,7 @@ ACMD_FUNC(clone) return 0; } - if(pc_isGM(pl_sd) > pc_isGM(sd)) { + if(pc_get_group_level(pl_sd) > pc_get_group_level(sd)) { clif_displaymessage(fd, msg_txt(126)); // Cannot clone a player of higher GM level than yourself. return 0; } @@ -8431,7 +8197,7 @@ ACMD_FUNC(request) } sprintf(atcmd_output, msg_txt(278), message); // (@request): %s - intif_wis_message_to_gm(sd->status.name, battle_config.lowest_gm_level, atcmd_output); + intif_wis_message_to_gm(sd->status.name, PC_PERM_RECEIVE_REQUESTS, atcmd_output); clif_disp_onlyself(sd, atcmd_output, strlen(atcmd_output)); clif_displaymessage(sd->fd,msg_txt(279)); // @request sent. return 0; @@ -8860,6 +8626,72 @@ ACMD_FUNC(font) return 0; } + +/*========================================== + * type: 1 = commands (@), 2 = charcommands (#) + *------------------------------------------*/ +static void atcommand_commands_sub(struct map_session_data* sd, const int fd, AtCommandType type) +{ + char line_buff[CHATBOX_SIZE]; + char* cur = line_buff; + AtCommandInfo* cmd; + DBIterator* iter = atcommand_db->iterator(atcommand_db); + int count = 0; + + memset(line_buff,' ',CHATBOX_SIZE); + line_buff[CHATBOX_SIZE-1] = 0; + + clif_displaymessage(fd, msg_txt(273)); // "Commands available:" + + for (cmd = (AtCommandInfo*)iter->first(iter, NULL); iter->exists(iter); cmd = (AtCommandInfo*)iter->next(iter, NULL)) { + unsigned int slen = 0; + + if (!pc_can_use_command(sd, cmd->command, type)) + continue; + + slen = strlen(cmd->command); + + // flush the text buffer if this command won't fit into it + if ( slen + cur - line_buff >= CHATBOX_SIZE ) + { + clif_displaymessage(fd,line_buff); + cur = line_buff; + memset(line_buff,' ',CHATBOX_SIZE); + line_buff[CHATBOX_SIZE-1] = 0; + } + + memcpy(cur,cmd->command,slen); + cur += slen+(10-slen%10); + + count++; + } + iter->destroy(iter); + clif_displaymessage(fd,line_buff); + + sprintf(atcmd_output, msg_txt(274), count); // "%d commands found." + clif_displaymessage(fd, atcmd_output); + + return; +} + +/*========================================== + * @commands Lists available @ commands to you + *------------------------------------------*/ +ACMD_FUNC(commands) +{ + atcommand_commands_sub(sd, fd, COMMAND_ATCOMMAND); + return 0; +} + +/*========================================== + * @charcommands Lists available # commands to you + *------------------------------------------*/ +ACMD_FUNC(charcommands) +{ + atcommand_commands_sub(sd, fd, COMMAND_CHARCOMMAND); + return 0; +} + ACMD_FUNC(new_mount) { clif_displaymessage(sd->fd,"NOTICE: If you crash with mount your LUA is outdated"); if( !(sd->sc.option&OPTION_MOUNTING) ) { @@ -8875,264 +8707,262 @@ ACMD_FUNC(new_mount) { /** * Fills the reference of available commands in atcommand DBMap **/ +#define ACMD_DEF(x) { #x, atcommand_ ## x } +#define ACMD_DEF2(x2, x) { x2, atcommand_ ## x } void atcommand_basecommands(void) { /** * Command reference list, place the base of your commands here - * Dev note: I'd love to get rid of this, if you have a better idea on this please share with the poor mortals **/ AtCommandInfo atcommand_base[] = { - { "warp", 40,40, atcommand_mapmove }, // + /mm - { "where", 1,1, atcommand_where }, - { "goto", 20,20, atcommand_jumpto }, // + /shift - { "jump", 40,40, atcommand_jump }, - { "who", 20,20, atcommand_who }, - { "who2", 20,20, atcommand_who2 }, - { "who3", 20,20, atcommand_who3 }, - { "whomap", 20,20, atcommand_whomap }, - { "whomap2", 20,20, atcommand_whomap2 }, - { "whomap3", 20,20, atcommand_whomap3 }, - { "whogm", 20,20, atcommand_whogm }, - { "save", 40,40, atcommand_save }, - { "load", 40,40, atcommand_load }, - { "speed", 40,40, atcommand_speed }, - { "storage", 1,1, atcommand_storage }, - { "gstorage", 50,50, atcommand_guildstorage }, - { "option", 40,40, atcommand_option }, - { "hide", 40,40, atcommand_hide }, // + /hide - { "job", 40,40, atcommand_jobchange }, - { "die", 1,1, atcommand_die }, - { "kill", 60,60, atcommand_kill }, - { "alive", 60,60, atcommand_alive }, - { "kami", 40,40, atcommand_kami }, - { "kamib", 40,40, atcommand_kami }, - { "kamic", 40,40, atcommand_kami }, - { "heal", 40,60, atcommand_heal }, - { "item", 60,60, atcommand_item }, - { "item2", 60,60, atcommand_item2 }, - { "itemreset", 40,40, atcommand_itemreset }, - { "blvl", 60,60, atcommand_baselevelup }, - { "jlvl", 60,60, atcommand_joblevelup }, - { "help", 20,20, atcommand_help }, - { "help2", 20,20, atcommand_help2 }, - { "pvpoff", 40,40, atcommand_pvpoff }, - { "pvpon", 40,40, atcommand_pvpon }, - { "gvgoff", 40,40, atcommand_gvgoff }, - { "gvgon", 40,40, atcommand_gvgon }, - { "model", 20,20, atcommand_model }, - { "go", 10,10, atcommand_go }, - { "monster", 50,50, atcommand_monster }, - { "monstersmall", 50,50, atcommand_monstersmall }, - { "monsterbig", 50,50, atcommand_monsterbig }, - { "killmonster", 60,60, atcommand_killmonster }, - { "killmonster2", 40,40, atcommand_killmonster2 }, - { "refine", 60,60, atcommand_refine }, - { "produce", 60,60, atcommand_produce }, - { "memo", 40,40, atcommand_memo }, - { "gat", 99,99, atcommand_gat }, - { "displaystatus", 99,99, atcommand_displaystatus }, - { "stpoint", 60,60, atcommand_statuspoint }, - { "skpoint", 60,60, atcommand_skillpoint }, - { "zeny", 60,60, atcommand_zeny }, - { "str", 60,60, atcommand_param }, - { "agi", 60,60, atcommand_param }, - { "vit", 60,60, atcommand_param }, - { "int", 60,60, atcommand_param }, - { "dex", 60,60, atcommand_param }, - { "luk", 60,60, atcommand_param }, - { "glvl", 60,60, atcommand_guildlevelup }, - { "makeegg", 60,60, atcommand_makeegg }, - { "hatch", 60,60, atcommand_hatch }, - { "petfriendly", 40,40, atcommand_petfriendly }, - { "pethungry", 40,40, atcommand_pethungry }, - { "petrename", 1,1, atcommand_petrename }, - { "recall", 60,60, atcommand_recall }, // + /recall - { "night", 80,80, atcommand_night }, - { "day", 80,80, atcommand_day }, - { "doom", 80,80, atcommand_doom }, - { "doommap", 80,80, atcommand_doommap }, - { "raise", 80,80, atcommand_raise }, - { "raisemap", 80,80, atcommand_raisemap }, - { "kick", 20,20, atcommand_kick }, // + right click menu for GM "(name) force to quit" - { "kickall", 99,99, atcommand_kickall }, - { "allskill", 60,60, atcommand_allskill }, - { "questskill", 40,40, atcommand_questskill }, - { "lostskill", 40,40, atcommand_lostskill }, - { "spiritball", 40,40, atcommand_spiritball }, - { "party", 1,1, atcommand_party }, - { "guild", 50,50, atcommand_guild }, - { "agitstart", 60,60, atcommand_agitstart }, - { "agitend", 60,60, atcommand_agitend }, - { "mapexit", 99,99, atcommand_mapexit }, - { "idsearch", 60,60, atcommand_idsearch }, - { "broadcast", 40,40, atcommand_broadcast }, // + /b and /nb - { "localbroadcast", 40,40, atcommand_localbroadcast }, // + /lb and /nlb - { "recallall", 80,80, atcommand_recallall }, - { "reloaditemdb", 99,99, atcommand_reloaditemdb }, - { "reloadmobdb", 99,99, atcommand_reloadmobdb }, - { "reloadskilldb", 99,99, atcommand_reloadskilldb }, - { "reloadscript", 99,99, atcommand_reloadscript }, - { "reloadatcommand", 99,99, atcommand_reloadatcommand }, - { "reloadbattleconf", 99,99, atcommand_reloadbattleconf }, - { "reloadstatusdb", 99,99, atcommand_reloadstatusdb }, - { "reloadpcdb", 99,99, atcommand_reloadpcdb }, - { "reloadmotd", 99,99, atcommand_reloadmotd }, - { "mapinfo", 99,99, atcommand_mapinfo }, - { "dye", 40,40, atcommand_dye }, - { "hairstyle", 40,40, atcommand_hair_style }, - { "haircolor", 40,40, atcommand_hair_color }, - { "allstats", 60,60, atcommand_stat_all }, - { "block", 60,60, atcommand_char_block }, - { "ban", 60,60, atcommand_char_ban }, - { "unblock", 60,60, atcommand_char_unblock }, - { "unban", 60,60, atcommand_char_unban }, - { "mount", 20,20, atcommand_mount_peco }, - { "guildspy", 60,60, atcommand_guildspy }, - { "partyspy", 60,60, atcommand_partyspy }, - { "repairall", 60,60, atcommand_repairall }, - { "guildrecall", 60,60, atcommand_guildrecall }, - { "partyrecall", 60,60, atcommand_partyrecall }, - { "nuke", 60,60, atcommand_nuke }, - { "shownpc", 80,80, atcommand_shownpc }, - { "hidenpc", 80,80, atcommand_hidenpc }, - { "loadnpc", 80,80, atcommand_loadnpc }, - { "unloadnpc", 80,80, atcommand_unloadnpc }, - { "time", 1,1, atcommand_servertime }, - { "jail", 60,60, atcommand_jail }, - { "unjail", 60,60, atcommand_unjail }, - { "jailfor", 60,60, atcommand_jailfor }, - { "jailtime", 1,1, atcommand_jailtime }, - { "disguise", 20,20, atcommand_disguise }, - { "undisguise", 20,20, atcommand_undisguise }, - { "email", 1,1, atcommand_email }, - { "effect", 40,40, atcommand_effect }, - { "follow", 20,20, atcommand_follow }, - { "addwarp", 60,60, atcommand_addwarp }, - { "skillon", 80,80, atcommand_skillon }, - { "skilloff", 80,80, atcommand_skilloff }, - { "killer", 60,60, atcommand_killer }, - { "npcmove", 80,80, atcommand_npcmove }, - { "killable", 40,40, atcommand_killable }, - { "dropall", 40,40, atcommand_dropall }, - { "storeall", 40,40, atcommand_storeall }, - { "skillid", 40,40, atcommand_skillid }, - { "useskill", 40,40, atcommand_useskill }, - { "displayskill", 99,99, atcommand_displayskill }, - { "snow", 99,99, atcommand_snow }, - { "sakura", 99,99, atcommand_sakura }, - { "clouds", 99,99, atcommand_clouds }, - { "clouds2", 99,99, atcommand_clouds2 }, - { "fog", 99,99, atcommand_fog }, - { "fireworks", 99,99, atcommand_fireworks }, - { "leaves", 99,99, atcommand_leaves }, - { "summon", 60,60, atcommand_summon }, - { "adjgmlvl", 99,99, atcommand_adjgmlvl }, - { "adjcmdlvl", 99,99, atcommand_adjcmdlvl }, - { "trade", 60,60, atcommand_trade }, - { "send", 99,99, atcommand_send }, - { "setbattleflag", 99,99, atcommand_setbattleflag }, - { "unmute", 80,80, atcommand_unmute }, - { "clearweather", 99,99, atcommand_clearweather }, - { "uptime", 1,1, atcommand_uptime }, - { "changesex", 60,60, atcommand_changesex }, - { "mute", 80,80, atcommand_mute }, - { "refresh", 1,1, atcommand_refresh }, - { "identify", 40,40, atcommand_identify }, - { "gmotd", 20,20, atcommand_gmotd }, - { "misceffect", 50,50, atcommand_misceffect }, - { "mobsearch", 10,10, atcommand_mobsearch }, - { "cleanmap", 40,40, atcommand_cleanmap }, - { "npctalk", 20,20, atcommand_npctalk }, - { "pettalk", 10,10, atcommand_pettalk }, - { "users", 40,40, atcommand_users }, - { "reset", 40,40, atcommand_reset }, - { "skilltree", 40,40, atcommand_skilltree }, - { "marry", 40,40, atcommand_marry }, - { "divorce", 40,40, atcommand_divorce }, - { "sound", 40,40, atcommand_sound }, - { "undisguiseall", 99,99, atcommand_undisguiseall }, - { "disguiseall", 99,99, atcommand_disguiseall }, - { "changelook", 60,60, atcommand_changelook }, - { "autoloot", 10,10, atcommand_autoloot }, - { "alootid", 10,10, atcommand_autolootitem }, - { "monsterinfo", 1,1, atcommand_mobinfo }, - { "exp", 1,1, atcommand_exp }, - { "adopt", 40,40, atcommand_adopt }, - { "version", 1,1, atcommand_version }, - { "mutearea", 99,99, atcommand_mutearea }, - { "rates", 1,1, atcommand_rates }, - { "iteminfo", 1,1, atcommand_iteminfo }, - { "whodrops", 1,1, atcommand_whodrops }, - { "whereis", 10,10, atcommand_whereis }, - { "mapflag", 99,99, atcommand_mapflag }, - { "me", 20,20, atcommand_me }, - { "battleignore", 99,99, atcommand_monsterignore }, - { "fakename", 20,20, atcommand_fakename }, - { "size", 20,20, atcommand_size }, - { "showexp", 10,10, atcommand_showexp}, - { "showzeny", 10,10, atcommand_showzeny}, - { "showdelay", 1,1, atcommand_showdelay}, - { "autotrade", 10,10, atcommand_autotrade }, - { "changegm", 10,10, atcommand_changegm }, - { "changeleader", 10,10, atcommand_changeleader }, - { "partyoption", 10,10, atcommand_partyoption}, - { "invite", 1,1, atcommand_invite }, - { "duel", 1,1, atcommand_duel }, - { "leave", 1,1, atcommand_leave }, - { "accept", 1,1, atcommand_accept }, - { "reject", 1,1, atcommand_reject }, - { "main", 1,1, atcommand_main }, - { "clone", 50,50, atcommand_clone }, - { "slaveclone", 50,50, atcommand_clone }, - { "evilclone", 50,50, atcommand_clone }, - { "tonpc", 40,40, atcommand_tonpc }, - { "commands", 1,1, atcommand_commands }, - { "noask", 1,1, atcommand_noask }, - { "request", 20,20, atcommand_request }, - { "hlvl", 60,60, atcommand_homlevel }, - { "homevolve", 60,60, atcommand_homevolution }, - { "makehomun", 60,60, atcommand_makehomun }, - { "homfriendly", 60,60, atcommand_homfriendly }, - { "homhungry", 60,60, atcommand_homhungry }, - { "homtalk", 10,10, atcommand_homtalk }, - { "hominfo", 1,1, atcommand_hominfo }, - { "homstats", 1,1, atcommand_homstats }, - { "homshuffle", 60,60, atcommand_homshuffle }, - { "showmobs", 10,10, atcommand_showmobs }, - { "feelreset", 10,10, atcommand_feelreset }, - { "auction", 1,1, atcommand_auction }, - { "mail", 1,1, atcommand_mail }, - { "noks", 1,1, atcommand_ksprotection }, - { "allowks", 40,40, atcommand_allowks }, - { "cash", 60,60, atcommand_cash }, - { "points", 60,60, atcommand_cash }, - { "agitstart2", 60,60, atcommand_agitstart2 }, - { "agitend2", 60,60, atcommand_agitend2 }, - { "skreset", 60,60, atcommand_resetskill }, - { "streset", 60,60, atcommand_resetstat }, - { "storagelist", 40,40, atcommand_itemlist }, - { "cartlist", 40,40, atcommand_itemlist }, - { "itemlist", 40,40, atcommand_itemlist }, - { "stats", 40,40, atcommand_stats }, - { "delitem", 60,60, atcommand_delitem }, - { "charcommands", 1,1, atcommand_charcommands }, - { "font", 1,1, atcommand_font }, + ACMD_DEF2("warp", mapmove), + ACMD_DEF(where), + ACMD_DEF(jumpto), + ACMD_DEF(jump), + ACMD_DEF(who), + ACMD_DEF(who2), + ACMD_DEF(who3), + ACMD_DEF(whomap), + ACMD_DEF(whomap2), + ACMD_DEF(whomap3), + ACMD_DEF(whogm), + ACMD_DEF(save), + ACMD_DEF(load), + ACMD_DEF(speed), + ACMD_DEF(storage), + ACMD_DEF(guildstorage), + ACMD_DEF(option), + ACMD_DEF(hide), // + /hide + ACMD_DEF(jobchange), + ACMD_DEF(die), + ACMD_DEF(kill), + ACMD_DEF(alive), + ACMD_DEF(kami), + ACMD_DEF2("kamib", kami), + ACMD_DEF2("kamic", kami), + ACMD_DEF(heal), + ACMD_DEF(item), + ACMD_DEF(item2), + ACMD_DEF(itemreset), + ACMD_DEF2("blvl", baselevelup), + ACMD_DEF2("jlvl", joblevelup), + ACMD_DEF(help), + ACMD_DEF(pvpoff), + ACMD_DEF(pvpon), + ACMD_DEF(gvgoff), + ACMD_DEF(gvgon), + ACMD_DEF(model), + ACMD_DEF(go), + ACMD_DEF(monster), + ACMD_DEF2("monstersmall", monster), + ACMD_DEF2("monsterbig", monster), + ACMD_DEF(killmonster), + ACMD_DEF(killmonster2), + ACMD_DEF(refine), + ACMD_DEF(produce), + ACMD_DEF(memo), + ACMD_DEF(gat), + ACMD_DEF(displaystatus), + ACMD_DEF2("stpoint", statuspoint), + ACMD_DEF2("skpoint", skillpoint), + ACMD_DEF(zeny), + ACMD_DEF2("str", param), + ACMD_DEF2("agi", param), + ACMD_DEF2("vit", param), + ACMD_DEF2("int", param), + ACMD_DEF2("dex", param), + ACMD_DEF2("luk", param), + ACMD_DEF2("glvl", guildlevelup), + ACMD_DEF(makeegg), + ACMD_DEF(hatch), + ACMD_DEF(petfriendly), + ACMD_DEF(pethungry), + ACMD_DEF(petrename), + ACMD_DEF(recall), // + /recall + ACMD_DEF(night), + ACMD_DEF(day), + ACMD_DEF(doom), + ACMD_DEF(doommap), + ACMD_DEF(raise), + ACMD_DEF(raisemap), + ACMD_DEF(kick), // + right click menu for GM "(name) force to quit" + ACMD_DEF(kickall), + ACMD_DEF(allskill), + ACMD_DEF(questskill), + ACMD_DEF(lostskill), + ACMD_DEF(spiritball), + ACMD_DEF(party), + ACMD_DEF(guild), + ACMD_DEF(agitstart), + ACMD_DEF(agitend), + ACMD_DEF(mapexit), + ACMD_DEF(idsearch), + ACMD_DEF(broadcast), // + /b and /nb + ACMD_DEF(localbroadcast), // + /lb and /nlb + ACMD_DEF(recallall), + ACMD_DEF(reloaditemdb), + ACMD_DEF(reloadmobdb), + ACMD_DEF(reloadskilldb), + ACMD_DEF(reloadscript), + ACMD_DEF(reloadatcommand), + ACMD_DEF(reloadbattleconf), + ACMD_DEF(reloadstatusdb), + ACMD_DEF(reloadpcdb), + ACMD_DEF(reloadmotd), + ACMD_DEF(mapinfo), + ACMD_DEF(dye), + ACMD_DEF2("hairstyle", hair_style), + ACMD_DEF2("haircolor", hair_color), + ACMD_DEF2("allstats", stat_all), + ACMD_DEF2("block", char_block), + ACMD_DEF2("ban", char_ban), + ACMD_DEF2("unblock", char_unblock), + ACMD_DEF2("unban", char_unban), + ACMD_DEF2("mount", mount_peco), + ACMD_DEF(guildspy), + ACMD_DEF(partyspy), + ACMD_DEF(repairall), + ACMD_DEF(guildrecall), + ACMD_DEF(partyrecall), + ACMD_DEF(nuke), + ACMD_DEF(shownpc), + ACMD_DEF(hidenpc), + ACMD_DEF(loadnpc), + ACMD_DEF(unloadnpc), + ACMD_DEF2("time", servertime), + ACMD_DEF(jail), + ACMD_DEF(unjail), + ACMD_DEF(jailfor), + ACMD_DEF(jailtime), + ACMD_DEF(disguise), + ACMD_DEF(undisguise), + ACMD_DEF(email), + ACMD_DEF(effect), + ACMD_DEF(follow), + ACMD_DEF(addwarp), + ACMD_DEF(skillon), + ACMD_DEF(skilloff), + ACMD_DEF(killer), + ACMD_DEF(npcmove), + ACMD_DEF(killable), + ACMD_DEF(dropall), + ACMD_DEF(storeall), + ACMD_DEF(skillid), + ACMD_DEF(useskill), + ACMD_DEF(displayskill), + ACMD_DEF(snow), + ACMD_DEF(sakura), + ACMD_DEF(clouds), + ACMD_DEF(clouds2), + ACMD_DEF(fog), + ACMD_DEF(fireworks), + ACMD_DEF(leaves), + ACMD_DEF(summon), + ACMD_DEF(adjgroup), + ACMD_DEF(trade), + ACMD_DEF(send), + ACMD_DEF(setbattleflag), + ACMD_DEF(unmute), + ACMD_DEF(clearweather), + ACMD_DEF(uptime), + ACMD_DEF(changesex), + ACMD_DEF(mute), + ACMD_DEF(refresh), + ACMD_DEF(identify), + ACMD_DEF(gmotd), + ACMD_DEF(misceffect), + ACMD_DEF(mobsearch), + ACMD_DEF(cleanmap), + ACMD_DEF(npctalk), + ACMD_DEF(pettalk), + ACMD_DEF(users), + ACMD_DEF(reset), + ACMD_DEF(skilltree), + ACMD_DEF(marry), + ACMD_DEF(divorce), + ACMD_DEF(sound), + ACMD_DEF(undisguiseall), + ACMD_DEF(disguiseall), + ACMD_DEF(changelook), + ACMD_DEF(autoloot), + ACMD_DEF2("alootid", autolootitem), + ACMD_DEF(mobinfo), + ACMD_DEF(exp), + ACMD_DEF(adopt), + ACMD_DEF(version), + ACMD_DEF(mutearea), + ACMD_DEF(rates), + ACMD_DEF(iteminfo), + ACMD_DEF(whodrops), + ACMD_DEF(whereis), + ACMD_DEF(mapflag), + ACMD_DEF(me), + ACMD_DEF(monsterignore), + ACMD_DEF(fakename), + ACMD_DEF(size), + ACMD_DEF(showexp), + ACMD_DEF(showzeny), + ACMD_DEF(showdelay), + ACMD_DEF(autotrade), + ACMD_DEF(changegm), + ACMD_DEF(changeleader), + ACMD_DEF(partyoption), + ACMD_DEF(invite), + ACMD_DEF(duel), + ACMD_DEF(leave), + ACMD_DEF(accept), + ACMD_DEF(reject), + ACMD_DEF(main), + ACMD_DEF(clone), + ACMD_DEF2("slaveclone", clone), + ACMD_DEF2("evilclone", clone), + ACMD_DEF(tonpc), + ACMD_DEF(commands), + ACMD_DEF(noask), + ACMD_DEF(request), + ACMD_DEF(homlevel), + ACMD_DEF(homevolution), + ACMD_DEF(makehomun), + ACMD_DEF(homfriendly), + ACMD_DEF(homhungry), + ACMD_DEF(homtalk), + ACMD_DEF(hominfo), + ACMD_DEF(homstats), + ACMD_DEF(homshuffle), + ACMD_DEF(showmobs), + ACMD_DEF(feelreset), + ACMD_DEF(auction), + ACMD_DEF(mail), + ACMD_DEF2("noks", ksprotection), + ACMD_DEF(allowks), + ACMD_DEF(cash), + ACMD_DEF2("points", cash), + ACMD_DEF(agitstart2), + ACMD_DEF(agitend2), + ACMD_DEF2("skreset", resetskill), + ACMD_DEF2("streset", resetstat), + ACMD_DEF2("storagelist", itemlist), + ACMD_DEF2("cartlist", itemlist), + ACMD_DEF2("itemlist", itemlist), + ACMD_DEF(stats), + ACMD_DEF(delitem), + ACMD_DEF(charcommands), + ACMD_DEF(font), /** * For Testing Purposes, not going to be here after we're done. **/ - { "newmount", 0,99, atcommand_new_mount }, + ACMD_DEF2("newmount", new_mount), }; AtCommandInfo* atcommand; int i; for( i = 0; i < ARRAYLENGTH(atcommand_base); i++ ) { - + if(atcommand_exists(atcommand_base[i].command)) { // Should not happen if atcommand_base[] array is OK + ShowDebug("atcommand_basecommands: duplicate ACMD_DEF for '%s'.\n", atcommand_base[i].command); + continue; + } CREATE(atcommand, AtCommandInfo, 1); - - safestrncpy(atcommand->command,atcommand_base[i].command,sizeof(atcommand->command)); - atcommand->level = atcommand_base[i].level; - atcommand->level2 = atcommand_base[i].level2; + safestrncpy(atcommand->command, atcommand_base[i].command, sizeof(atcommand->command)); atcommand->func = atcommand_base[i].func; - strdb_put(atcommand_db, atcommand->command, atcommand); } return; @@ -9141,23 +8971,26 @@ void atcommand_basecommands(void) { /*========================================== * Command lookup functions *------------------------------------------*/ -static AtCommandInfo* get_atcommandinfo_byname(const char* name) { - if( *name == atcommand_symbol || *name == charcommand_symbol ) name++; // for backwards compatibility - if( strdb_exists(atcommand_db,name) ) +bool atcommand_exists(const char* name) +{ + return strdb_exists(atcommand_db, name); +} + +static AtCommandInfo* get_atcommandinfo_byname(const char *name) +{ + if (strdb_exists(atcommand_db, name)) return (AtCommandInfo*)strdb_get(atcommand_db, name); return NULL; } - -/*========================================== - * Retrieve the command's required gm level - *------------------------------------------*/ -int get_atcommand_level(const char* name) { - AtCommandInfo* info = (AtCommandInfo*)strdb_get(atcommand_db, name); - return ( info != NULL ) ? info->level : 100; // 100: command can not be used +static const char* atcommand_checkalias(const char *aliasname) +{ + AliasInfo *alias_info = NULL; + if ((alias_info = (AliasInfo*)strdb_get(atcommand_alias_db, aliasname)) != NULL) + return alias_info->command->command; + return aliasname; } - /// Executes an at-command. bool is_atcommand(const int fd, struct map_session_data* sd, const char* message, int type) { @@ -9165,7 +8998,6 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message char charname2[NAME_LENGTH], params2[100]; char command[100]; char output[CHAT_SIZE_MAX]; - int x, y, z; int lv = 0; //Reconstructed message @@ -9177,15 +9009,15 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message nullpo_retr(false, sd); //Shouldn't happen - if( !message || !*message ) + if ( !message || !*message ) return false; //Block NOCHAT but do not display it as a normal message - if( sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCOMMAND ) + if ( sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCOMMAND ) return true; // skip 10/11-langtype's codepage indicator, if detected - if( message[0] == '|' && strlen(message) >= 4 && (message[3] == atcommand_symbol || message[3] == charcommand_symbol) ) + if ( message[0] == '|' && strlen(message) >= 4 && (message[3] == atcommand_symbol || message[3] == charcommand_symbol) ) message += 3; //Should display as a normal message @@ -9194,64 +9026,49 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message // type value 0 = server invoked: bypass restrictions // 1 = player invoked - if( type ) - { + if ( type == 1) { //Commands are disabled on maps flagged as 'nocommand' - if( map[sd->bl.m].nocommand && pc_isGM(sd) < map[sd->bl.m].nocommand ) - { + if ( map[sd->bl.m].nocommand && pc_get_group_level(sd) < map[sd->bl.m].nocommand ) { clif_displaymessage(fd, msg_txt(143)); return false; } - - //Displays as a normal message for Non-GMs - if( battle_config.atc_gmonly != 0 && pc_isGM(sd) == 0 ) - return false; } - while (*message == charcommand_symbol) - { - //Checks to see if #command has a name or a name + parameters. - x = sscanf(message, "%99s \"%23[^\"]\" %99[^\n]", command, charname, params); - y = sscanf(message, "%99s %23s %99[^\n]", command, charname2, params2); - - //z always has the value of the scan that was successful - z = ( x > 1 ) ? x : y; + if (*message == charcommand_symbol) { + do { + int x, y, z; + + //Checks to see if #command has a name or a name + parameters. + x = sscanf(message, "%99s \"%23[^\"]\" %99[^\n]", command, charname, params); + y = sscanf(message, "%99s %23s %99[^\n]", command, charname2, params2); - if ( (ssd = map_nick2sd(charname)) == NULL && ( (ssd = map_nick2sd(charname2)) == NULL ) ) { - if( pc_isGM(sd) ) { - sprintf(output, "%s failed. Player not found.", command); - clif_displaymessage(fd, output); - } else { - sprintf(output, "Charcommand failed. Usage: #<command> <char name> <params>."); - clif_displaymessage(fd, output); + //z always has the value of the scan that was successful + z = ( x > 1 ) ? x : y; + + //#command + name means the sufficient target was used and anything else after + //can be looked at by the actual command function since most scan to see if the + //right parameters are used. + if ( x > 2 ) { + sprintf(atcmd_msg, "%s %s", command, params); + break; + } + else if ( y > 2 ) { + sprintf(atcmd_msg, "%s %s", command, params2); + break; + } + //Regardless of what style the #command is used, if it's correct, it will always have + //this value if there is no parameter. Send it as just the #command + else if ( z == 2 ) { + sprintf(atcmd_msg, "%s", command); + break; } - return true; - } - - //#command + name means the sufficient target was used and anything else after - //can be looked at by the actual command function since most scan to see if the - //right parameters are used. - if ( x > 2 ) { - sprintf(atcmd_msg, "%s %s", command, params); - break; - } - else if ( y > 2 ) { - sprintf(atcmd_msg, "%s %s", command, params2); - break; - } - //Regardless of what style the #command is used, if it's correct, it will always have - //this value if there is no parameter. Send it as just the #command - else if ( z == 2 ) { - sprintf(atcmd_msg, "%s", command); - break; - } - sprintf(output, "Charcommand failed. Usage: #<command> <char name> <params>."); - clif_displaymessage(fd, output); - return true; + sprintf(output, "Charcommand failed. Usage: %c<command> <char name> <params>.", charcommand_symbol); + clif_displaymessage(fd, output); + return true; + } while(0); } - - if (*message == atcommand_symbol) { + else if (*message == atcommand_symbol) { //atcmd_msg is constructed above differently for charcommands //it's copied from message if not a charcommand so it can //pass through the rest of the code compatible with both symbols @@ -9267,9 +9084,10 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message params[0] = '\0'; //Grab the command information and check for the proper GM level required to use it or if the command exists - if( (info = (AtCommandInfo*)strdb_get(atcommand_db, command+1)) == NULL || info->func == NULL || ( type && ((*atcmd_msg == atcommand_symbol && pc_isGM(sd) < info->level) || (*atcmd_msg == charcommand_symbol && pc_isGM(sd) < info->level2)) ) ) + info = get_atcommandinfo_byname(atcommand_checkalias(command + 1)); + if (info == NULL) { - if( pc_isGM(sd) ) { + if( pc_get_group_level(sd) ) { // TODO: remove or replace with proper permission sprintf(output, msg_txt(153), command); // "%s is Unknown Command." clif_displaymessage(fd, output); return true; @@ -9277,238 +9095,167 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message return false; } - //Log atcommands - if( *atcmd_msg == atcommand_symbol ) - log_atcommand(sd, info->level, atcmd_msg); - //Log Charcommands - else if( *atcmd_msg == charcommand_symbol && ssd != NULL ) - log_atcommand(sd, info->level2, message); - + // type == 1 : player invoked + if (type == 1) { + if ((*command == atcommand_symbol && !pc_can_use_command(sd, atcommand_checkalias(command + 1), COMMAND_ATCOMMAND)) || + (*command == charcommand_symbol && !pc_can_use_command(sd, atcommand_checkalias(command + 1), COMMAND_CHARCOMMAND))) { + return false; + } + } + + // Check if target is valid only if confirmed that player can use command. + if (*message == charcommand_symbol && + (ssd = map_nick2sd(charname)) == NULL && (ssd = map_nick2sd(charname2)) == NULL ) { + sprintf(output, "%s failed. Player not found.", command); + clif_displaymessage(fd, output); + return true; + } + //Attempt to use the command - if( strcmpi("adjgmlvl",command+1) && ssd ) { lv = ssd->gmlevel; ssd->gmlevel = sd->gmlevel; } if ( (info->func(fd, (*atcmd_msg == atcommand_symbol) ? sd : ssd, command, params) != 0) ) { sprintf(output,msg_txt(154), command); // %s failed. clif_displaymessage(fd, output); - } - if( strcmpi("adjgmlvl",command+1) && ssd ) ssd->gmlevel = lv; - - return true; -} -/** - * Splits and parses command aliases field - * Note: I'm not good (at all) with string manipulation, if you think you can improve, please do. I beg you. - **/ -void atcommand_parse_aliases(char aliases[1024],AtCommandInfo* base) { - char *str[99], *p; - int i, max = 0; - - p = aliases; - while( ISSPACE(*p) )//trim - ++p; - - //I assume nobody is getting over 98 alises in the same command lol - for( i = 0; i < 99; i++ ) { - str[i] = p; - p = strchr(p,','); - if( p == NULL ) { - max = i+1; - break;// comma not found - } - *p = '\0'; - ++p; + return true; } - if( !str[0] )//no aliases at all - return; - - for(i = 0; i < max;i++) { - AtCommandInfo* atcommand = NULL; - normalize_name(str[i]," ");//trim over - if( (atcommand = strdb_get(atcommand_db, str[i])) ) { - atcommand->level = base->level; - atcommand->level2 = base->level2; - continue; - } - - CREATE(atcommand, AtCommandInfo, 1); - - safestrncpy(atcommand->command,str[i],sizeof(atcommand->command)); - atcommand->level = base->level; - atcommand->level2 = base->level2; - atcommand->func = base->func; - - strdb_put(atcommand_db, atcommand->command, atcommand); - } + //Log only if successful. + if ( *atcmd_msg == atcommand_symbol ) + log_atcommand(sd, atcmd_msg); + else if ( *atcmd_msg == charcommand_symbol ) + log_atcommand(sd, message); - return; + return true; } + /*========================================== * *------------------------------------------*/ -int atcommand_config_read(const char* cfgName) +static void atcommand_config_read(const char* config_filename) { - char line[1024], w1[1024], w2[1024], w3[1024], w4[1024]; - AtCommandInfo* p; - FILE* fp; - int i; + config_setting_t *aliases = NULL, *help = NULL; + const char *symbol = NULL; + int num_aliases = 0; - if( (fp = fopen(cfgName, "r")) == NULL ) { - ShowError("AtCommand configuration file not found: %s\n", cfgName); - return 1; - } - - while( fgets(line, sizeof(line), fp) ) { - if( line[0] == '/' && line[1] == '/' ) - continue; - if( ( i = sscanf(line,"%1023[^:]:%1023[^,],%1023[^[][%1023[^]]",w1,w2,w3,w4) ) >= 3 ) { - if( ( p = (AtCommandInfo*)strdb_get(atcommand_db, w1) ) != NULL ) { - - p->level = atoi(w2);//update @level - p->level2 = atoi(w3);//update #level - - /** - * Parse the alises - **/ - if( i == 4 ) - atcommand_parse_aliases(w4,p); - - continue;//we're done move on + if (conf_read_file(&atcommand_config, config_filename)) + return; + + // Command symbols + if (config_lookup_string(&atcommand_config, "atcommand_symbol", &symbol)) { + if (ISPRINT(*symbol) && // no control characters + *symbol != '/' && // symbol of client commands + *symbol != '%' && // symbol of party chat + *symbol != '$' && // symbol of guild chat + *symbol != charcommand_symbol) + atcommand_symbol = *symbol; + } + + if (config_lookup_string(&atcommand_config, "charcommand_symbol", &symbol)) { + if (ISPRINT(*symbol) && // no control characters + *symbol != '/' && // symbol of client commands + *symbol != '%' && // symbol of party chat + *symbol != '$' && // symbol of guild chat + *symbol != atcommand_symbol) + charcommand_symbol = *symbol; + } + + // Command aliases + aliases = config_lookup(&atcommand_config, "aliases"); + if (aliases != NULL) { + int i = 0; + int count = config_setting_length(aliases); + + for (i = 0; i < count; ++i) { + config_setting_t *command = NULL; + const char *commandname = NULL; + int j = 0, alias_count = 0; + AtCommandInfo *commandinfo = NULL; + + command = config_setting_get_elem(aliases, i); + if (config_setting_type(command) != CONFIG_TYPE_ARRAY) + continue; + commandname = config_setting_name(command); + if (!atcommand_exists(commandname)) { + ShowConfigWarning(command, "atcommand_config_read: can not set alias for non-existent command %s", commandname); + continue; + } + commandinfo = get_atcommandinfo_byname(commandname); + alias_count = config_setting_length(command); + for (j = 0; j < alias_count; ++j) { + const char *alias = config_setting_get_string_elem(command, j); + if (alias != NULL) { + AliasInfo *alias_info; + if (strdb_exists(atcommand_alias_db, alias)) { + ShowConfigWarning(command, "atcommand_config_read: alias %s already exists", alias); + continue; + } + CREATE(alias_info, AliasInfo, 1); + alias_info->command = commandinfo; + safestrncpy(alias_info->alias, alias, sizeof(alias_info->alias)); + strdb_put(atcommand_alias_db, alias, alias_info); + ++num_aliases; + } } - } else if( strcmpi(w1, "import") != 0 && strcmpi(w1, "command_symbol") != 0 && strcmpi(w1, "char_symbol") != 0 ) { - if( i > 1 ) - ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName); - continue; } - normalize_name(w2," ");//trim - if( strcmpi(w1, "import") == 0 ) - atcommand_config_read(w2); - else if( strcmpi(w1, "command_symbol") == 0 && - w2[0] > 31 && // control characters - w2[0] != '/' && // symbol of standard ragnarok GM commands - w2[0] != '%' && // symbol of party chat speaking - w2[0] != '$' && // symbol of guild chat speaking - w2[0] != '#' ) // remote symbol - atcommand_symbol = w2[0]; - else if( strcmpi(w1, "char_symbol") == 0 && - w2[0] > 31 && - w2[0] != '/' && - w2[0] != '%' && - w2[0] != '$' && - w2[0] != '@' ) - charcommand_symbol = w2[0]; } - fclose(fp); - - return 0; -} -static int atcommand_db_free(DBKey key,void *data,va_list va) { - - aFree((AtCommandInfo*)data); - - return 1; -} + // Commands help + // We only check if all commands exist + help = config_lookup(&atcommand_config, "help"); + if (help != NULL) { + int count = config_setting_length(help); + int i; -void atcommand_db_clear() { + for (i = 0; i < count; ++i) { + config_setting_t *command = NULL; + const char *commandname = NULL; - atcommand_db->foreach(atcommand_db,atcommand_db_free); - db_destroy(atcommand_db); + command = config_setting_get_elem(help, i); + commandname = config_setting_name(command); + if (!atcommand_exists(commandname)) + ShowConfigWarning(command, "atcommand_config_read: command %s does not exist", commandname); + } + } + ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' command aliases in '"CL_WHITE"%s"CL_RESET"'.\n", num_aliases, config_filename); return; } -void atcommand_doload() { - - if( atcommand_db != NULL ) - atcommand_db_clear(); - - atcommand_db = stridb_alloc(DB_OPT_DUP_KEY, 0); - atcommand_basecommands();//fills initial atcommand_db with known commands - - atcommand_config_read(ATCOMMAND_CONF_FILENAME); - - return; +static int atcommand_db_free(DBKey key, void *data, va_list va) +{ + aFree((AtCommandInfo*)data); + return 1; } -void do_init_atcommand() { - - atcommand_doload(); - +static int atcommand_alias_db_free(DBKey key, void *data, va_list va) +{ + aFree((AliasInfo*)data); + return 1; } -void do_final_atcommand() { - - atcommand_db_clear(); - - return; +void atcommand_db_clear(void) +{ + if (atcommand_db != NULL) + atcommand_db->destroy(atcommand_db, atcommand_db_free); + if (atcommand_alias_db != NULL) + atcommand_alias_db->destroy(atcommand_alias_db, atcommand_alias_db_free); } - -// commands that need to go _after_ the commands table - -/*========================================== - * type: 1 = commands (@), 2 = charcommands (#) - *------------------------------------------*/ -static void atcommand_commands_sub(struct map_session_data* sd, const int fd, int type) { - char line_buff[CHATBOX_SIZE]; - int gm_lvl = pc_isGM(sd), count = 0; - char* cur = line_buff; - AtCommandInfo* cmd; - DBIterator* iter = atcommand_db->iterator(atcommand_db); - - memset(line_buff,' ',CHATBOX_SIZE); - line_buff[CHATBOX_SIZE-1] = 0; - - clif_displaymessage(fd, msg_txt(273)); // "Commands available:" - - for( cmd = (AtCommandInfo*)iter->first(iter,NULL); iter->exists(iter); cmd = (AtCommandInfo*)iter->next(iter,NULL) ) { - unsigned int slen; - - if( type == 1 && gm_lvl < cmd->level ) - continue; - if( type == 2 && gm_lvl < cmd->level2 ) - continue; - - slen = strlen(cmd->command); - - // flush the text buffer if this command won't fit into it - if( slen + cur - line_buff >= CHATBOX_SIZE ) - { - clif_displaymessage(fd,line_buff); - cur = line_buff; - memset(line_buff,' ',CHATBOX_SIZE); - line_buff[CHATBOX_SIZE-1] = 0; - } - - memcpy(cur,cmd->command,slen); - cur += slen+(10-slen%10); - - count++; - } - iter->destroy(iter); - clif_displaymessage(fd,line_buff); - - sprintf(atcmd_output, msg_txt(274), count); // "%d commands found." - clif_displaymessage(fd, atcmd_output); - - return; +void atcommand_doload(void) +{ + atcommand_db_clear(); + atcommand_db = stridb_alloc(DB_OPT_DUP_KEY, ATCOMMAND_LENGTH); + atcommand_alias_db = stridb_alloc(DB_OPT_DUP_KEY, ATCOMMAND_LENGTH); + atcommand_basecommands(); //fills initial atcommand_db with known commands + atcommand_config_read(ATCOMMAND_CONF_FILENAME); } -/*========================================== - * @commands Lists available @ commands to you - *------------------------------------------*/ -ACMD_FUNC(commands) +void do_init_atcommand(void) { - atcommand_commands_sub(sd, fd, 1); - return 0; - } + atcommand_doload(); +} -/*========================================== - * @charcommands Lists available # commands to you - *------------------------------------------*/ -ACMD_FUNC(charcommands) +void do_final_atcommand(void) { - atcommand_commands_sub(sd, fd, 2); - return 0; -} + atcommand_db_clear(); +}
\ No newline at end of file diff --git a/src/map/atcommand.h b/src/map/atcommand.h index 415aa9305..a0a7c2286 100644 --- a/src/map/atcommand.h +++ b/src/map/atcommand.h @@ -4,7 +4,6 @@ #ifndef _ATCOMMAND_H_ #define _ATCOMMAND_H_ -//#include "map.h" struct map_session_data; //This is the distance at which @autoloot works, @@ -15,32 +14,21 @@ struct map_session_data; extern char atcommand_symbol; extern char charcommand_symbol; + +typedef enum { + COMMAND_ATCOMMAND = 1, + COMMAND_CHARCOMMAND = 2, +} AtCommandType; + typedef int (*AtCommandFunc)(const int fd, struct map_session_data* sd, const char* command, const char* message); bool is_atcommand(const int fd, struct map_session_data* sd, const char* message, int type); -int get_atcommand_level(const char* name); void do_init_atcommand(void); void do_final_atcommand(void); -int atcommand_config_read(const char *cfgName); - -int atcommand_mail(const int fd, struct map_session_data* sd,const char* command, const char* message); -int atcommand_item(const int fd, struct map_session_data* sd,const char* command, const char* message); -int atcommand_mapmove(const int fd, struct map_session_data* sd,const char* command, const char* message); -int atcommand_monster(const int fd, struct map_session_data* sd, const char* command, const char* message); -int atcommand_jumpto(const int fd, struct map_session_data* sd, const char* command, const char* message); -int atcommand_recall(const int fd, struct map_session_data* sd, const char* command, const char* message); -int atcommand_hide(const int fd, struct map_session_data* sd, const char* command, const char* message); -int atcommand_mute(const int fd, struct map_session_data* sd, const char* command, const char* message); -int atcommand_kick(const int fd, struct map_session_data* sd, const char* command, const char* message); -int atcommand_broadcast(const int fd, struct map_session_data* sd,const char* command, const char* message); -int atcommand_localbroadcast(const int fd, struct map_session_data* sd,const char* command, const char* message); -int atcommand_reset(const int fd, struct map_session_data* sd,const char* command, const char* message); -int atcommand_unloadnpc(const int fd, struct map_session_data* sd, const char* command, const char* message); -int atcommand_killmonster(const int fd, struct map_session_data* sd, const char* command, const char* message); - -#define MAX_MSG 1000 -extern char* msg_table[MAX_MSG]; + +bool atcommand_exists(const char* name); + const char* msg_txt(int msg_number); int msg_config_read(const char* cfgName); void do_final_msg(void); diff --git a/src/map/battle.c b/src/map/battle.c index cbf0610ef..a7257406e 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -4441,18 +4441,9 @@ static const struct _battle_data { { "guild_max_castles", &battle_config.guild_max_castles, 0, 0, INT_MAX, }, { "guild_skill_relog_delay", &battle_config.guild_skill_relog_delay, 0, 0, 1, }, { "emergency_call", &battle_config.emergency_call, 11, 0, 31, }, - { "lowest_gm_level", &battle_config.lowest_gm_level, 1, 0, 99, }, - { "atcommand_gm_only", &battle_config.atc_gmonly, 0, 0, 1, }, { "atcommand_spawn_quantity_limit", &battle_config.atc_spawn_quantity_limit, 100, 0, INT_MAX, }, { "atcommand_slave_clone_limit", &battle_config.atc_slave_clone_limit, 25, 0, INT_MAX, }, { "partial_name_scan", &battle_config.partial_name_scan, 0, 0, 1, }, - { "gm_all_skill", &battle_config.gm_allskill, 0, 0, 100, }, - { "gm_all_equipment", &battle_config.gm_allequip, 0, 0, 100, }, - { "gm_skill_unconditional", &battle_config.gm_skilluncond, 0, 0, 100, }, - { "gm_join_chat", &battle_config.gm_join_chat, 0, 0, 100, }, - { "gm_kick_chat", &battle_config.gm_kick_chat, 0, 0, 100, }, - { "gm_can_party", &battle_config.gm_can_party, 0, 0, 1, }, - { "gm_cant_party_min_lv", &battle_config.gm_cant_party_min_lv, 20, 0, 100, }, { "player_skillfree", &battle_config.skillfree, 0, 0, 1, }, { "player_skillup_limit", &battle_config.skillup_limit, 1, 0, 1, }, { "weapon_produce_rate", &battle_config.wp_rate, 100, 0, INT_MAX, }, @@ -4588,15 +4579,11 @@ static const struct _battle_data { { "gx_disptype", &battle_config.gx_disptype, 1, 0, 1, }, { "devotion_level_difference", &battle_config.devotion_level_difference, 10, 0, INT_MAX, }, { "player_skill_partner_check", &battle_config.player_skill_partner_check, 1, 0, 1, }, - { "hide_GM_session", &battle_config.hide_GM_session, 0, 0, 1, }, { "invite_request_check", &battle_config.invite_request_check, 1, 0, 1, }, { "skill_removetrap_type", &battle_config.skill_removetrap_type, 0, 0, 1, }, { "disp_experience", &battle_config.disp_experience, 0, 0, 1, }, { "disp_zeny", &battle_config.disp_zeny, 0, 0, 1, }, { "castle_defense_rate", &battle_config.castle_defense_rate, 100, 0, 100, }, - { "gm_cant_drop_min_lv", &battle_config.gm_cant_drop_min_lv, 1, 0, 100, }, - { "gm_cant_drop_max_lv", &battle_config.gm_cant_drop_max_lv, 0, 0, 100, }, - { "disp_hpmeter", &battle_config.disp_hpmeter, 0, 0, 100, }, { "bone_drop", &battle_config.bone_drop, 0, 0, 2, }, { "buyer_name", &battle_config.buyer_name, 1, 0, 1, }, { "skill_wall_check", &battle_config.skill_wall_check, 1, 0, 1, }, @@ -4649,9 +4636,6 @@ static const struct _battle_data { { "night_at_start", &battle_config.night_at_start, 0, 0, 1, }, { "show_mob_info", &battle_config.show_mob_info, 0, 0, 1|2|4, }, { "ban_hack_trade", &battle_config.ban_hack_trade, 0, 0, INT_MAX, }, - { "hack_info_GM_level", &battle_config.hack_info_GM_level, 60, 0, 100, }, - { "any_warp_GM_min_level", &battle_config.any_warp_GM_min_level, 20, 0, 100, }, - { "who_display_aid", &battle_config.who_display_aid, 40, 0, 100, }, { "packet_ver_flag", &battle_config.packet_ver_flag, 0xFFFFFF,0x0000,INT_MAX, }, { "min_hair_style", &battle_config.min_hair_style, 0, 0, INT_MAX, }, { "max_hair_style", &battle_config.max_hair_style, 23, 0, INT_MAX, }, @@ -4699,14 +4683,6 @@ static const struct _battle_data { { "mob_max_skilllvl", &battle_config.mob_max_skilllvl, MAX_SKILL_LEVEL, 1, MAX_SKILL_LEVEL, }, { "retaliate_to_master", &battle_config.retaliate_to_master, 1, 0, 1, }, { "rare_drop_announce", &battle_config.rare_drop_announce, 0, 0, 10000, }, - { "title_lvl1", &battle_config.title_lvl1, 1, 0, 100, }, - { "title_lvl2", &battle_config.title_lvl2, 10, 0, 100, }, - { "title_lvl3", &battle_config.title_lvl3, 20, 0, 100, }, - { "title_lvl4", &battle_config.title_lvl4, 40, 0, 100, }, - { "title_lvl5", &battle_config.title_lvl5, 50, 0, 100, }, - { "title_lvl6", &battle_config.title_lvl6, 60, 0, 100, }, - { "title_lvl7", &battle_config.title_lvl7, 80, 0, 100, }, - { "title_lvl8", &battle_config.title_lvl8, 99, 0, 100, }, { "duel_allow_pvp", &battle_config.duel_allow_pvp, 0, 0, 1, }, { "duel_allow_gvg", &battle_config.duel_allow_gvg, 0, 0, 1, }, { "duel_allow_teleport", &battle_config.duel_allow_teleport, 0, 0, 1, }, @@ -4750,7 +4726,6 @@ static const struct _battle_data { { "ksprotection", &battle_config.ksprotection, 5000, 0, INT_MAX, }, { "auction_feeperhour", &battle_config.auction_feeperhour, 12000, 0, INT_MAX, }, { "auction_maximumprice", &battle_config.auction_maximumprice, 500000000, 0, MAX_ZENY, }, - { "gm_viewequip_min_lv", &battle_config.gm_viewequip_min_lv, 0, 0, 99, }, { "homunculus_auto_vapor", &battle_config.homunculus_auto_vapor, 1, 0, 1, }, { "display_status_timers", &battle_config.display_status_timers, 1, 0, 1, }, { "skill_add_heal_rate", &battle_config.skill_add_heal_rate, 7, 0, INT_MAX, }, @@ -4760,7 +4735,6 @@ static const struct _battle_data { { "autospell_check_range", &battle_config.autospell_check_range, 0, 0, 1, }, { "client_reshuffle_dice", &battle_config.client_reshuffle_dice, 0, 0, 1, }, { "client_sort_storage", &battle_config.client_sort_storage, 0, 0, 1, }, - { "gm_check_minlevel", &battle_config.gm_check_minlevel, 60, 0, 100, }, { "feature.buying_store", &battle_config.feature_buying_store, 1, 0, 1, }, { "feature.search_stores", &battle_config.feature_search_stores, 1, 0, 1, }, { "searchstore_querydelay", &battle_config.searchstore_querydelay, 10, 0, INT_MAX, }, diff --git a/src/map/battle.h b/src/map/battle.h index 43c1d69ec..54b707f08 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -151,16 +151,9 @@ extern struct Battle_Config int monster_max_aspd; int view_range_rate; int chase_range_rate; - int lowest_gm_level; - int atc_gmonly; int atc_spawn_quantity_limit; int atc_slave_clone_limit; int partial_name_scan; - int gm_allskill; - int gm_allequip; - int gm_skilluncond; - int gm_join_chat; - int gm_kick_chat; int skillfree; int skillup_limit; int wp_rate; @@ -327,7 +320,6 @@ extern struct Battle_Config int gx_disptype; int devotion_level_difference; int player_skill_partner_check; - int hide_GM_session; int invite_request_check; int skill_removetrap_type; int disp_experience; @@ -336,21 +328,14 @@ extern struct Battle_Config int backstab_bow_penalty; int hp_rate; int sp_rate; - int gm_cant_drop_min_lv; - int gm_cant_drop_max_lv; - int disp_hpmeter; int bone_drop; int buyer_name; - int gm_cant_party_min_lv; - int gm_can_party; // [SketchyPhoenix] // eAthena additions int night_at_start; // added by [Yor] int day_duration; // added by [Yor] int night_duration; // added by [Yor] int ban_hack_trade; // added by [Yor] - int hack_info_GM_level; // added by [Yor] - int any_warp_GM_min_level; // added by [Yor] int packet_ver_flag; // added by [Yor] int min_hair_style; // added by [MouseJstr] @@ -387,7 +372,6 @@ extern struct Battle_Config int delay_battle_damage; int hide_woe_damage; int display_version; - int who_display_aid; int display_hallucination; // [Skotlex] int use_statpoint_table; // [Skotlex] @@ -415,15 +399,6 @@ extern struct Battle_Config int retaliate_to_master; //Whether when a mob is attacked by another mob, it will retaliate versus the mob or the mob's master. [Skotlex] - int title_lvl1; // Players titles [Lupus] - int title_lvl2; // Players titles [Lupus] - int title_lvl3; // Players titles [Lupus] - int title_lvl4; // Players titles [Lupus] - int title_lvl5; // Players titles [Lupus] - int title_lvl6; // Players titles [Lupus] - int title_lvl7; // Players titles [Lupus] - int title_lvl8; // Players titles [Lupus] - int duel_allow_pvp; // [LuzZza] int duel_allow_gvg; // [LuzZza] int duel_allow_teleport; // [LuzZza] @@ -466,7 +441,6 @@ extern struct Battle_Config int ksprotection; int auction_feeperhour; int auction_maximumprice; - int gm_viewequip_min_lv; int homunculus_auto_vapor; //Keep Homunculus from Vaporizing when master dies. [L0ne_W0lf] int display_status_timers; //Show or hide skill buff/delay timers in recent clients [Sara] int skill_add_heal_rate; //skills that bHealPower has effect on [Inkfish] @@ -476,7 +450,6 @@ extern struct Battle_Config int autospell_check_range; //Enable range check for autospell bonus. [L0ne_W0lf] int client_reshuffle_dice; // Reshuffle /dice int client_sort_storage; - int gm_check_minlevel; // min GM level for /check int feature_buying_store; int feature_search_stores; int searchstore_querydelay; diff --git a/src/map/buyingstore.c b/src/map/buyingstore.c index 01964a56e..a556a41a2 100644 --- a/src/map/buyingstore.c +++ b/src/map/buyingstore.c @@ -98,7 +98,7 @@ void buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned cha return; } - if( !pc_can_give_items(pc_isGM(sd)) ) + if( !pc_can_give_items(sd) ) {// custom: GM is not allowed to buy (give zeny) sd->buyingstore.slots = 0; clif_displaymessage(sd->fd, msg_txt(246)); @@ -145,7 +145,7 @@ void buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned cha break; } - if( !id->flag.buyingstore || !itemdb_cantrade_sub(id, pc_isGM(sd), pc_isGM(sd)) || ( idx = pc_search_inventory(sd, nameid) ) == -1 ) + if( !id->flag.buyingstore || !itemdb_cantrade_sub(id, pc_get_group_level(sd), pc_get_group_level(sd)) || ( idx = pc_search_inventory(sd, nameid) ) == -1 ) {// restrictions: allowed, no character-bound items and at least one must be owned break; } @@ -219,7 +219,7 @@ void buyingstore_open(struct map_session_data* sd, int account_id) return; } - if( !pc_can_give_items(pc_isGM(sd)) ) + if( !pc_can_give_items(sd) ) {// custom: GM is not allowed to sell clif_displaymessage(sd->fd, msg_txt(246)); return; @@ -257,7 +257,7 @@ void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int return; } - if( !pc_can_give_items(pc_isGM(sd)) ) + if( !pc_can_give_items(sd) ) {// custom: GM is not allowed to sell clif_displaymessage(sd->fd, msg_txt(246)); clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0); @@ -312,7 +312,7 @@ void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int return; } - if( sd->status.inventory[index].expire_time || !itemdb_cantrade(&sd->status.inventory[index], pc_isGM(sd), pc_isGM(pl_sd)) || memcmp(sd->status.inventory[index].card, buyingstore_blankslots, sizeof(buyingstore_blankslots)) ) + if( sd->status.inventory[index].expire_time || !itemdb_cantrade(&sd->status.inventory[index], pc_get_group_level(sd), pc_get_group_level(pl_sd)) || memcmp(sd->status.inventory[index].card, buyingstore_blankslots, sizeof(buyingstore_blankslots)) ) {// non-tradable item clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); return; diff --git a/src/map/chat.c b/src/map/chat.c index 48c0b07f1..9a59950d4 100644 --- a/src/map/chat.c +++ b/src/map/chat.c @@ -125,7 +125,7 @@ int chat_joinchat(struct map_session_data* sd, int chatid, const char* pass) return 0; } - if( !cd->pub && strncmp(pass, cd->pass, sizeof(cd->pass)) != 0 && !(battle_config.gm_join_chat && pc_isGM(sd) >= battle_config.gm_join_chat) ) + if( !cd->pub && strncmp(pass, cd->pass, sizeof(cd->pass)) != 0 && !pc_has_permission(sd, PC_PERM_JOIN_ALL_CHAT) ) { clif_joinchatfail(sd,1); return 0; @@ -316,7 +316,7 @@ int chat_kickchat(struct map_session_data* sd, const char* kickusername) if( i == cd->users ) return -1; - if( battle_config.gm_kick_chat && pc_isGM(cd->usersd[i]) >= battle_config.gm_kick_chat ) + if (pc_has_permission(cd->usersd[i], PC_PERM_NO_CHAT_KICK)) return 0; //gm kick protection [Valaris] idb_put(cd->kick_list,cd->usersd[i]->status.char_id,(void*)1); diff --git a/src/map/chrif.c b/src/map/chrif.c index 10b7135b6..5d060a16f 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -412,7 +412,7 @@ int chrif_changemapserver(struct map_session_data* sd, uint32 ip, uint16 port) WFIFOW(char_fd,28) = htons(port); WFIFOB(char_fd,30) = sd->status.sex; WFIFOL(char_fd,31) = htonl(session[sd->fd]->client_addr); - WFIFOL(char_fd,35) = sd->gmlevel; + WFIFOL(char_fd,35) = sd->group_id; WFIFOSET(char_fd,39); return 0; } @@ -578,7 +578,7 @@ void chrif_authok(int fd) uint32 login_id1; uint32 login_id2; time_t expiration_time; - int gmlevel; + int group_id; struct mmo_charstatus* status; int char_id; struct auth_node *node; @@ -595,7 +595,7 @@ void chrif_authok(int fd) login_id1 = RFIFOL(fd,8); login_id2 = RFIFOL(fd,12); expiration_time = (time_t)(int32)RFIFOL(fd,16); - gmlevel = RFIFOL(fd,20); + group_id = RFIFOL(fd,20); changing_mapservers = (RFIFOB(fd,24)); status = (struct mmo_charstatus*)RFIFOP(fd,25); char_id = status->char_id; @@ -628,7 +628,7 @@ void chrif_authok(int fd) node->char_id == char_id && node->login_id1 == login_id1 ) { //Auth Ok - if (pc_authok(sd, login_id2, expiration_time, gmlevel, status, changing_mapservers)) + if (pc_authok(sd, login_id2, expiration_time, group_id, status, changing_mapservers)) return; } else { //Auth Failed pc_authfail(sd); diff --git a/src/map/clif.c b/src/map/clif.c index f38ce5ef2..3f7ad28ee 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -1779,7 +1779,7 @@ void clif_selllist(struct map_session_data *sd) { if( sd->status.inventory[i].nameid > 0 && sd->inventory_data[i] ) { - if( !itemdb_cansell(&sd->status.inventory[i], pc_isGM(sd)) ) + if( !itemdb_cansell(&sd->status.inventory[i], pc_get_group_level(sd)) ) continue; if( sd->status.inventory[i].expire_time ) @@ -2625,6 +2625,59 @@ void clif_guild_xy_remove(struct map_session_data *sd) clif_send(buf,packet_len(0x1eb),&sd->bl,GUILD_SAMEMAP_WOS); } +/*========================================== + * + *------------------------------------------*/ +static int clif_hpmeter_sub(struct block_list *bl, va_list ap) +{ + struct map_session_data *sd, *tsd; +#if PACKETVER < 20100126 + const int cmd = 0x106; +#else + const int cmd = 0x80e; +#endif + + sd = va_arg(ap, struct map_session_data *); + tsd = (TBL_PC *)bl; + + nullpo_ret(sd); + nullpo_ret(tsd); + + if( !tsd->fd || tsd == sd ) + return 0; + + if( !pc_has_permission(tsd, PC_PERM_VIEW_HPMETER) ) + return 0; + WFIFOHEAD(tsd->fd,packet_len(cmd)); + WFIFOW(tsd->fd,0) = cmd; + WFIFOL(tsd->fd,2) = sd->status.account_id; +#if PACKETVER < 20100126 + if( sd->battle_status.max_hp > INT16_MAX ) + { //To correctly display the %hp bar. [Skotlex] + WFIFOW(tsd->fd,6) = sd->battle_status.hp/(sd->battle_status.max_hp/100); + WFIFOW(tsd->fd,8) = 100; + } else { + WFIFOW(tsd->fd,6) = sd->battle_status.hp; + WFIFOW(tsd->fd,8) = sd->battle_status.max_hp; + } +#else + WFIFOL(tsd->fd,6) = sd->battle_status.hp; + WFIFOL(tsd->fd,10) = sd->battle_status.max_hp; +#endif + WFIFOSET(tsd->fd,packet_len(cmd)); + return 0; +} + +/*========================================== + * Server tells all players that are allowed to view HP bars + * and are nearby 'sd' that 'sd' hp bar was updated. + *------------------------------------------*/ +static int clif_hpmeter(struct map_session_data *sd) +{ + nullpo_ret(sd); + map_foreachinarea(clif_hpmeter_sub, sd->bl.m, sd->bl.x-AREA_SIZE, sd->bl.y-AREA_SIZE, sd->bl.x+AREA_SIZE, sd->bl.y+AREA_SIZE, BL_PC, sd); + return 0; +} /// Notifies client of a character parameter change. /// 00b0 <var id>.W <value>.L (ZC_PAR_CHANGE) @@ -2700,8 +2753,7 @@ void clif_updatestatus(struct map_session_data *sd,int type) case SP_HP: WFIFOL(fd,4)=sd->battle_status.hp; // TODO: Won't these overwrite the current packet? - if( battle_config.disp_hpmeter ) - clif_hpmeter(sd); + clif_hpmeter(sd); if( !battle_config.party_hp_mode && sd->status.party_id ) clif_party_hp(sd); if( sd->bg_id ) @@ -3922,7 +3974,6 @@ int clif_status_load_single(int fd, int id,int type,int flag,int val1, int val2, *------------------------------------------*/ static void clif_getareachar_pc(struct map_session_data* sd,struct map_session_data* dstsd) { - int gmlvl; struct block_list *d_bl; int i; @@ -3943,7 +3994,8 @@ static void clif_getareachar_pc(struct map_session_data* sd,struct map_session_d } if( (sd->status.party_id && dstsd->status.party_id == sd->status.party_id) || //Party-mate, or hpdisp setting. (sd->bg_id && sd->bg_id == dstsd->bg_id) || //BattleGround - (battle_config.disp_hpmeter && (gmlvl = pc_isGM(sd)) >= battle_config.disp_hpmeter && gmlvl >= pc_isGM(dstsd)) ) + pc_has_permission(sd, PC_PERM_VIEW_HPMETER) + ) clif_hpmeter_single(sd->fd, dstsd->bl.id, dstsd->battle_status.hp, dstsd->battle_status.max_hp); // display link (sd - dstsd) to sd @@ -5235,26 +5287,31 @@ void clif_status_change(struct block_list *bl,int type,int flag,unsigned int tic /// 008e <packet len>.W <message>.?B void clif_displaymessage(const int fd, const char* mes) { - // invalid pointer? nullpo_retv(mes); //Scrapped, as these are shared by disconnected players =X [Skotlex] if (fd == 0) ; else { - int len_mes = strlen(mes); - - if (len_mes > 0) { // don't send a void message (it's not displaying on the client chat). @help can send void line. - WFIFOHEAD(fd, 5 + len_mes); - WFIFOW(fd,0) = 0x8e; - WFIFOW(fd,2) = 5 + len_mes; // 4 + len + NULL teminate - memcpy(WFIFOP(fd,4), mes, len_mes + 1); - WFIFOSET(fd, 5 + len_mes); + char *message, *line; + + message = aStrdup(mes); + line = strtok(message, "\n"); + while(line != NULL) { + int len = strlen(line); + if (len > 0) { // don't send a void message (it's not displaying on the client chat). @help can send void line. + WFIFOHEAD(fd, 5 + len); + WFIFOW(fd,0) = 0x8e; + WFIFOW(fd,2) = 5 + len; // 4 + len + NULL teminate + memcpy(WFIFOP(fd,4), line, len + 1); + WFIFOSET(fd, 5 + len); + } + line = strtok(NULL, "\n"); } + aFree(message); } } - /// Send broadcast message in yellow or blue without font formatting (ZC_BROADCAST). /// 009a <packet len>.W <message>.?B void clif_broadcast(struct block_list* bl, const char* mes, int len, int type, enum send_target target) @@ -5518,7 +5575,7 @@ void clif_wis_message(int fd, const char* nick, const char* mes, int mes_len) WFIFOW(fd,2) = mes_len + NAME_LENGTH + 8; safestrncpy((char*)WFIFOP(fd,4), nick, NAME_LENGTH); WFIFOL(fd,28) = 0; // isAdmin; if nonzero, also displays text above char - // TODO: WFIFOL(fd,28) = ( pc_isGM(ssd) >= battle_config.lowest_gm_level ); + // TODO: WFIFOL(fd,28) = pc_get_group_level(ssd); safestrncpy((char*)WFIFOP(fd,32), mes, mes_len); WFIFOSET(fd,WFIFOW(fd,2)); #endif @@ -6419,64 +6476,6 @@ void clif_hpmeter_single(int fd, int id, unsigned int hp, unsigned int maxhp) WFIFOSET(fd, packet_len(cmd)); } -/*========================================== - * - *------------------------------------------*/ -int clif_hpmeter_sub(struct block_list *bl, va_list ap) -{ - struct map_session_data *sd, *tsd; - int level; -#if PACKETVER < 20100126 - const int cmd = 0x106; -#else - const int cmd = 0x80e; -#endif - - sd = va_arg(ap, struct map_session_data *); - tsd = (TBL_PC *)bl; - - nullpo_ret(sd); - nullpo_ret(tsd); - - if( !tsd->fd || tsd == sd ) - return 0; - - if( (level = pc_isGM(tsd)) < battle_config.disp_hpmeter || level < pc_isGM(sd) ) - return 0; - WFIFOHEAD(tsd->fd,packet_len(cmd)); - WFIFOW(tsd->fd,0) = cmd; - WFIFOL(tsd->fd,2) = sd->status.account_id; -#if PACKETVER < 20100126 - if( sd->battle_status.max_hp > INT16_MAX ) - { //To correctly display the %hp bar. [Skotlex] - WFIFOW(tsd->fd,6) = sd->battle_status.hp/(sd->battle_status.max_hp/100); - WFIFOW(tsd->fd,8) = 100; - } else { - WFIFOW(tsd->fd,6) = sd->battle_status.hp; - WFIFOW(tsd->fd,8) = sd->battle_status.max_hp; - } -#else - WFIFOL(tsd->fd,6) = sd->battle_status.hp; - WFIFOL(tsd->fd,10) = sd->battle_status.max_hp; -#endif - WFIFOSET(tsd->fd,packet_len(cmd)); - return 0; -} - -/*========================================== - * Server tells all nearby gms to 'sd' that 'sd' hp bar was updated - *------------------------------------------*/ -int clif_hpmeter(struct map_session_data *sd) -{ - nullpo_ret(sd); - - if( battle_config.disp_hpmeter ) - map_foreachinarea(clif_hpmeter_sub, sd->bl.m, sd->bl.x-AREA_SIZE, sd->bl.y-AREA_SIZE, sd->bl.x+AREA_SIZE, sd->bl.y+AREA_SIZE, BL_PC, sd); - - return 0; -} - - /// Notifies the client, that it's attack target is too far (ZC_ATTACK_FAILURE_FOR_DISTANCE). /// 0139 <target id>.L <target x>.W <target y>.W <x>.W <y>.W <atk range>.W void clif_movetoattack(struct map_session_data *sd,struct block_list *bl) @@ -9417,7 +9416,7 @@ void clif_parse_GetCharNameRequest(int fd, struct map_session_data *sd) sc = status_get_sc(bl); if (sc && sc->option&OPTION_INVISIBLE && !disguised(bl) && bl->type != BL_NPC && //Skip hidden NPCs which can be seen using Maya Purple - pc_isGM(sd) < battle_config.hack_info_GM_level + pc_get_group_level(sd) < battle_config.hack_info_GM_level ) { char gm_msg[256]; sprintf(gm_msg, "Hack on NameRequest: character '%s' (account: %d) requested the name of an invisible target (id: %d).\n", sd->status.name, sd->status.account_id, id); @@ -9506,21 +9505,13 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd) /// 0140 <map name>.16B <x>.W <y>.W void clif_parse_MapMove(int fd, struct map_session_data *sd) { - char output[MAP_NAME_LENGTH_EXT+15]; // Max length of a short: ' -6XXXX' -> 7 digits - char message[MAP_NAME_LENGTH_EXT+15+5]; // "/mm "+output + char command[MAP_NAME_LENGTH_EXT+25]; char* map_name; - if (battle_config.atc_gmonly && !pc_isGM(sd)) - return; - if(pc_isGM(sd) < get_atcommand_level("warp")) - return; - map_name = (char*)RFIFOP(fd,2); map_name[MAP_NAME_LENGTH_EXT-1]='\0'; - sprintf(output, "%s %d %d", map_name, RFIFOW(fd,18), RFIFOW(fd,20)); - atcommand_mapmove(fd, sd, "@mapmove", output); - sprintf(message, "/mm %s", output); - log_atcommand(sd, get_atcommand_level("warp"), message); + sprintf(command, "@mapmove %s %d %d", map_name, RFIFOW(fd,18), RFIFOW(fd,20)); + is_atcommand(fd, sd, command, 1); } @@ -9861,7 +9852,7 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd) // if player ignores everyone if (dstsd->state.ignoreAll) { - if (dstsd->sc.option & OPTION_INVISIBLE && pc_isGM(sd) < pc_isGM(dstsd)) + if (dstsd->sc.option & OPTION_INVISIBLE && pc_get_group_level(sd) < pc_get_group_level(dstsd)) clif_wis_end(fd, 1); // 1: target character is not loged in else clif_wis_end(fd, 3); // 3: everyone ignored by target @@ -9897,25 +9888,14 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd) /// 0099 <packet len>.W <text>.?B 00 void clif_parse_Broadcast(int fd, struct map_session_data* sd) { + char command[CHAT_SIZE_MAX+11]; char* msg = (char*)RFIFOP(fd,4); unsigned int len = RFIFOW(fd,2)-4; - int lv; - - if( battle_config.atc_gmonly && !pc_isGM(sd) ) - return; - if( pc_isGM(sd) < (lv=get_atcommand_level("broadcast")) ) - return; // as the length varies depending on the command used, just block unreasonably long strings len = mes_len_check(msg, len, CHAT_SIZE_MAX); - - intif_broadcast(msg, len, 0); - - { - char logmsg[CHAT_SIZE_MAX+4]; - sprintf(logmsg, "/b %s", msg); - log_atcommand(sd, lv, logmsg); - } + sprintf(command, "@broadcast %s", msg); + is_atcommand(fd, sd, command, 1); } @@ -11066,23 +11046,10 @@ void clif_parse_SolveCharName(int fd, struct map_session_data *sd) /// 1 = skill void clif_parse_ResetChar(int fd, struct map_session_data *sd) { - if( battle_config.atc_gmonly && !pc_isGM(sd) ) - return; - - if( pc_isGM(sd) < get_atcommand_level("reset") ) - return; - if( RFIFOW(fd,2) ) - pc_resetskill(sd,1); - else { - pc_resetstate(sd); - if( sd->mission_mobid ) { //bugreport:2200 - sd->mission_mobid = 0; - sd->mission_count = 0; - pc_setglobalreg(sd,"TK_MISSION_ID", 0); - } - } - log_atcommand(sd, get_atcommand_level("reset"), RFIFOW(fd,2) ? "/resetskill" : "/resetstate"); + is_atcommand(fd, sd, "@resetskill", 1); + else + is_atcommand(fd, sd, "@resetstat", 1); } @@ -11091,26 +11058,15 @@ void clif_parse_ResetChar(int fd, struct map_session_data *sd) /// 019c <packet len>.W <text>.?B void clif_parse_LocalBroadcast(int fd, struct map_session_data* sd) { + char command[CHAT_SIZE_MAX+16]; char* msg = (char*)RFIFOP(fd,4); unsigned int len = RFIFOW(fd,2)-4; - int lv; - - if( battle_config.atc_gmonly && !pc_isGM(sd) ) - return; - - if( pc_isGM(sd) < (lv=get_atcommand_level("localbroadcast")) ) - return; - + // as the length varies depending on the command used, just block unreasonably long strings len = mes_len_check(msg, len, CHAT_SIZE_MAX); - clif_broadcast(&sd->bl, msg, len, 0, ALL_SAMEMAP); - - { - char logmsg[CHAT_SIZE_MAX+5]; - sprintf(logmsg, "/lb %s", msg); - log_atcommand(sd, lv, logmsg); - } + sprintf(command, "@localbroadcast %s", msg); + is_atcommand(fd, sd, command, 1); } @@ -12168,10 +12124,7 @@ void clif_parse_ChangePetName(int fd, struct map_session_data *sd) void clif_parse_GMKick(int fd, struct map_session_data *sd) { struct block_list *target; - int tid,lv; - - if( battle_config.atc_gmonly && !pc_isGM(sd) ) - return; + int tid; tid = RFIFOL(fd,2); target = map_id2bl(tid); @@ -12183,69 +12136,36 @@ void clif_parse_GMKick(int fd, struct map_session_data *sd) switch (target->type) { case BL_PC: { - struct map_session_data *tsd = (struct map_session_data *)target; - if (pc_isGM(sd) <= pc_isGM(tsd)) - { - clif_GM_kickack(sd, 0); - return; - } - - lv = get_atcommand_level("kick"); - if( pc_isGM(sd) < lv ) - { - clif_GM_kickack(sd, 0); - return; - } - - { - char message[256]; - sprintf(message, "/kick %s (%d)", tsd->status.name, tsd->status.char_id); - log_atcommand(sd, lv, message); - } - - clif_GM_kick(sd, tsd); + char command[NAME_LENGTH+6]; + sprintf(command, "@kick %s", status_get_name(target)); + is_atcommand(fd, sd, command, 1); } break; + + /** + * This one does not invoke any atcommand, so we need to check for permissions. + */ case BL_MOB: { - lv = get_atcommand_level("killmonster"); - if( pc_isGM(sd) < lv ) - { + char command[100]; + if( !pc_can_use_command(sd, "killmonster", COMMAND_ATCOMMAND)) { clif_GM_kickack(sd, 0); return; } - - { - char message[256]; - sprintf(message, "/kick %s (%d)", status_get_name(target), status_get_class(target)); - log_atcommand(sd, lv, message); - } - + sprintf(command, "/kick %s (%d)", status_get_name(target), status_get_class(target)); + log_atcommand(sd, command); status_percent_damage(&sd->bl, target, 100, 0, true); // can invalidate 'target' } break; + case BL_NPC: { - struct npc_data* nd = (struct npc_data *)target; - lv = get_atcommand_level("unloadnpc"); - if( pc_isGM(sd) < lv ) - { - clif_GM_kickack(sd, 0); - return; - } - - { - char message[256]; - sprintf(message, "/kick %s (%d)", status_get_name(target), status_get_class(target)); - log_atcommand(sd, lv, message); - } - - // copy-pasted from atcommand_unloadnpc - npc_unload_duplicates(nd); - npc_unload(nd); // invalidates 'target' - npc_read_event_script(); + char command[NAME_LENGTH+11]; + sprintf(command, "@unloadnpc %s", status_get_name(target)); + is_atcommand(fd, sd, command, 1); } break; + default: clif_GM_kickack(sd, 0); } @@ -12271,21 +12191,13 @@ void clif_parse_GMKickAll(int fd, struct map_session_data* sd) void clif_parse_GMShift(int fd, struct map_session_data *sd) {// FIXME: remove is supposed to receive account name for clients prior 20100803RE char *player_name; - int lv; - - if( battle_config.atc_gmonly && !pc_isGM(sd) ) - return; - if( pc_isGM(sd) < (lv=get_atcommand_level("goto")) ) - return; + char command[NAME_LENGTH+8]; player_name = (char*)RFIFOP(fd,2); player_name[NAME_LENGTH-1] = '\0'; - atcommand_jumpto(fd, sd, "@jumpto", player_name); // as @jumpto - { - char message[NAME_LENGTH+7]; - sprintf(message, "/shift %s", player_name); - log_atcommand(sd, lv, message); - } + + sprintf(command, "@jumpto %s", player_name); + is_atcommand(fd, sd, command, 1); } @@ -12294,31 +12206,15 @@ void clif_parse_GMShift(int fd, struct map_session_data *sd) /// 0843 <account id>.L void clif_parse_GMRemove2(int fd, struct map_session_data* sd) { - int account_id, lv; + int account_id; struct map_session_data* pl_sd; - if( battle_config.atc_gmonly && !pc_isGM(sd) ) - { - return; - } - - if( pc_isGM(sd) < ( lv = get_atcommand_level("goto") ) ) - { - return; - } - account_id = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); - - if( ( pl_sd = map_id2sd(account_id) ) != NULL && pc_isGM(sd) >= pc_isGM(pl_sd) ) + if( (pl_sd = map_id2sd(account_id)) != NULL ) { - pc_warpto(sd, pl_sd); - } - - { - char message[32]; - - sprintf(message, "/remove %d", account_id); - log_atcommand(sd, lv, message); + char command[NAME_LENGTH+8]; + sprintf(command, "@jumpto %s", pl_sd->status.name); + is_atcommand(fd, sd, command, 1); } } @@ -12333,22 +12229,13 @@ void clif_parse_GMRemove2(int fd, struct map_session_data* sd) void clif_parse_GMRecall(int fd, struct map_session_data *sd) {// FIXME: recall is supposed to receive account name for clients prior 20100803RE char *player_name; - int lv; - - if( battle_config.atc_gmonly && !pc_isGM(sd) ) - return; - - if( pc_isGM(sd) < (lv=get_atcommand_level("recall")) ) - return; + char command [NAME_LENGTH+8]; player_name = (char*)RFIFOP(fd,2); player_name[NAME_LENGTH-1] = '\0'; - atcommand_recall(fd, sd, "@recall", player_name); // as @recall - { - char message[NAME_LENGTH+8]; - sprintf(message, "/recall %s", player_name); - log_atcommand(sd, lv, message); - } + + sprintf(command, "@recall %s", player_name); + is_atcommand(fd, sd, command, 1); } @@ -12357,31 +12244,15 @@ void clif_parse_GMRecall(int fd, struct map_session_data *sd) /// 0842 <account id>.L void clif_parse_GMRecall2(int fd, struct map_session_data* sd) { - int account_id, lv; + int account_id; struct map_session_data* pl_sd; - if( battle_config.atc_gmonly && !pc_isGM(sd) ) - { - return; - } - - if( pc_isGM(sd) < ( lv = get_atcommand_level("recall") ) ) - { - return; - } - account_id = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); - - if( ( pl_sd = map_id2sd(account_id) ) != NULL && pc_isGM(sd) >= pc_isGM(pl_sd) ) + if( (pl_sd = map_id2sd(account_id)) != NULL ) { - pc_recall(sd, pl_sd); - } - - { - char message[32]; - - sprintf(message, "/recall %d", account_id); - log_atcommand(sd, lv, message); + char command[NAME_LENGTH+8]; + sprintf(command, "@recall %s", pl_sd->status.name); + is_atcommand(fd, sd, command, 1); } } @@ -12392,33 +12263,21 @@ void clif_parse_GMRecall2(int fd, struct map_session_data* sd) void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd) { char *monster_item_name; - char message[NAME_LENGTH+10]; //For logging. - int level; - - if( battle_config.atc_gmonly && !pc_isGM(sd) ) - return; + char command[NAME_LENGTH+10]; monster_item_name = (char*)RFIFOP(fd,2); monster_item_name[NAME_LENGTH-1] = '\0'; if( mobdb_searchname(monster_item_name) ) { - if( pc_isGM(sd) < (level=get_atcommand_level("monster")) ) - return; - atcommand_monster(fd, sd, "@monster", monster_item_name); // as @monster - { //Log action. [Skotlex] - snprintf(message, sizeof(message)-1, "@monster %s", monster_item_name); - log_atcommand(sd, level, message); - } + snprintf(command, sizeof(command)-1, "@monster %s", monster_item_name); + is_atcommand(fd, sd, command, 1); return; } - if( itemdb_searchname(monster_item_name) == NULL ) - return; - if( pc_isGM(sd) < (level = get_atcommand_level("item")) ) + + if( itemdb_searchname(monster_item_name) ) { + snprintf(command, sizeof(command)-1, "@item %s", monster_item_name); + is_atcommand(fd, sd, command, 1); return; - atcommand_item(fd, sd, "@item", monster_item_name); // as @item - { //Log action. [Skotlex] - sprintf(message, "@item %s", monster_item_name); - log_atcommand(sd, level, message); } } @@ -12429,26 +12288,7 @@ void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd) /// TODO: Any OPTION_* ? void clif_parse_GMHide(int fd, struct map_session_data *sd) { - if( battle_config.atc_gmonly && !pc_isGM(sd) ) - return; - - if( pc_isGM(sd) < get_atcommand_level("hide") ) - return; - - if( sd->sc.option & OPTION_INVISIBLE ) { - sd->sc.option &= ~OPTION_INVISIBLE; - if (sd->disguise) - status_set_viewdata(&sd->bl, sd->disguise); - else - status_set_viewdata(&sd->bl, sd->status.class_); - clif_displaymessage(fd, "Invisible: Off."); - } else { - sd->sc.option |= OPTION_INVISIBLE; - sd->vd.class_ = INVISIBLE_CLASS; - clif_displaymessage(fd, "Invisible: On."); - log_atcommand(sd, get_atcommand_level("hide"), "/hide"); - } - clif_changeoption(&sd->bl); + is_atcommand(fd, sd, "@hide", 1); } @@ -12460,41 +12300,28 @@ void clif_parse_GMHide(int fd, struct map_session_data *sd) /// 2 = self mute (+10 minutes) void clif_parse_GMReqNoChat(int fd,struct map_session_data *sd) { - int id, type, value, level; + int id, type, value; struct map_session_data *dstsd; + char command[NAME_LENGTH+15]; id = RFIFOL(fd,2); type = RFIFOB(fd,6); value = RFIFOW(fd,7); if( type == 0 ) - value = 0 - value; + value = -value; //If type is 2 and the ids don't match, this is a crafted hacked packet! //Disabled because clients keep self-muting when you give players public @ commands... [Skotlex] - if (type == 2 /* && (pc_isGM(sd) > 0 || sd->bl.id != id)*/) + if (type == 2 /* && (pc_get_group_level(sd) > 0 || sd->bl.id != id)*/) return; dstsd = map_id2sd(id); if( dstsd == NULL ) return; - if( (level = pc_isGM(sd)) > pc_isGM(dstsd) && level >= get_atcommand_level("mute") ) - { - clif_manner_message(sd, 0); - clif_manner_message(dstsd, 5); - - if( dstsd->status.manner < value ) { - dstsd->status.manner -= value; - sc_start(&dstsd->bl,SC_NOCHAT,100,0,0); - } else { - dstsd->status.manner = 0; - status_change_end(&dstsd->bl, SC_NOCHAT, INVALID_TIMER); - } - - if( type != 2 ) - clif_GM_silence(sd, dstsd, type); - } + sprintf(command, "@mute %d %s", value, dstsd->status.name); + is_atcommand(fd, sd, command, 1); } @@ -12503,23 +12330,12 @@ void clif_parse_GMReqNoChat(int fd,struct map_session_data *sd) /// 0212 <char name>.24B void clif_parse_GMRc(int fd, struct map_session_data* sd) { - char* name = (char*)RFIFOP(fd,2); - struct map_session_data* dstsd; - name[23] = '\0'; - dstsd = map_nick2sd(name); - if( dstsd == NULL ) - return; - - if( pc_isGM(sd) > pc_isGM(dstsd) && pc_isGM(sd) >= get_atcommand_level("mute") ) - { - clif_manner_message(sd, 0); - clif_manner_message(dstsd, 3); - - dstsd->status.manner -= 60; - sc_start(&dstsd->bl,SC_NOCHAT,100,0,0); + char command[NAME_LENGTH+15]; + char *name = (char*)RFIFOP(fd,2); - clif_GM_silence(sd, dstsd, 1); - } + name[NAME_LENGTH-1] = '\0'; + sprintf(command, "@mute %d %s", 60, name); + is_atcommand(fd, sd, command, 1); } @@ -12552,10 +12368,7 @@ void clif_parse_GMChangeMapType(int fd, struct map_session_data *sd) { int x,y,type; - if( battle_config.atc_gmonly && !pc_isGM(sd) ) - return; - - if( pc_isGM(sd) < 99 ) //TODO: add proper check + if( pc_has_permission(sd, PC_PERM_USE_CHANGEMAPTYPE) ) return; x = RFIFOW(fd,2); @@ -12576,7 +12389,6 @@ void clif_parse_GMChangeMapType(int fd, struct map_session_data *sd) /// 1 = (/in nick) allow speech from nick void clif_parse_PMIgnore(int fd, struct map_session_data* sd) { - char output[512]; char* nick; uint8 type; int i; @@ -12592,12 +12404,7 @@ void clif_parse_PMIgnore(int fd, struct map_session_data* sd) if( type == 0 ) { // Add name to ignore list (block) - - // Bot-check... - if (strcmp(wisp_server_name, nick) == 0) - { // to find possible bot users who automaticaly ignore people - sprintf(output, "Character '%s' (account: %d) has tried to block wisps from '%s' (wisp name of the server). Bot user?", sd->status.name, sd->status.account_id, wisp_server_name); - intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, output); + if (strcmp(wisp_server_name, nick) == 0) { WFIFOB(fd,3) = 1; // fail WFIFOSET(fd, packet_len(0x0d1)); return; @@ -13412,14 +13219,12 @@ void clif_parse_Check(int fd, struct map_session_data *sd) char charname[NAME_LENGTH]; struct map_session_data* pl_sd; - if( pc_isGM(sd) < battle_config.gm_check_minlevel ) - { + if(!pc_has_permission(sd, PC_PERM_USE_CHECK)) return; - } safestrncpy(charname, (const char*)RFIFOP(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]), sizeof(charname)); - if( ( pl_sd = map_nick2sd(charname) ) == NULL || pc_isGM(sd) < pc_isGM(pl_sd) ) + if( ( pl_sd = map_nick2sd(charname) ) == NULL || pc_get_group_level(sd) < pc_get_group_level(pl_sd) ) { return; } @@ -14003,9 +13808,9 @@ void clif_parse_Auction_setitem(int fd, struct map_session_data *sd) return; } - if( !pc_can_give_items(pc_isGM(sd)) || sd->status.inventory[idx].expire_time || + if( !pc_can_give_items(sd) || sd->status.inventory[idx].expire_time || !sd->status.inventory[idx].identify || - !itemdb_canauction(&sd->status.inventory[idx],pc_isGM(sd)) ) { // Quest Item or something else + !itemdb_canauction(&sd->status.inventory[idx],pc_get_group_level(sd)) ) { // Quest Item or something else clif_Auction_setitem(sd->fd, idx, true); return; } @@ -14158,7 +13963,7 @@ void clif_parse_Auction_bid(int fd, struct map_session_data *sd) unsigned int auction_id = RFIFOL(fd,2); int bid = RFIFOL(fd,6); - if( !pc_can_give_items(pc_isGM(sd)) ) { //They aren't supposed to give zeny [Inkfish] + if( !pc_can_give_items(sd) ) { //They aren't supposed to give zeny [Inkfish] clif_displaymessage(sd->fd, msg_txt(246)); return; } @@ -14456,7 +14261,7 @@ void clif_parse_ViewPlayerEquip(int fd, struct map_session_data* sd) if (!tsd) return; - if( tsd->status.show_equip || (battle_config.gm_viewequip_min_lv && pc_isGM(sd) >= battle_config.gm_viewequip_min_lv) ) + if( tsd->status.show_equip || pc_has_permission(sd, PC_PERM_VIEW_EQUIPMENT) ) clif_viewequip_ack(sd, tsd); else clif_viewequip_fail(sd); @@ -15995,11 +15800,11 @@ static int clif_parse(int fd) //Disassociate character from the socket connection. session[fd]->session_data = NULL; sd->fd = 0; - ShowInfo("%sCharacter '"CL_WHITE"%s"CL_RESET"' logged off (using @autotrade).\n", (pc_isGM(sd))?"GM ":"", sd->status.name); + ShowInfo("Character '"CL_WHITE"%s"CL_RESET"' logged off (using @autotrade).\n", sd->status.name); } else if (sd->state.active) { // Player logout display [Valaris] - ShowInfo("%sCharacter '"CL_WHITE"%s"CL_RESET"' logged off.\n", (pc_isGM(sd))?"GM ":"", sd->status.name); + ShowInfo("Character '"CL_WHITE"%s"CL_RESET"' logged off.\n", sd->status.name); clif_quitsave(fd, sd); } else { //Unusual logout (during log on/off/map-changer procedure) diff --git a/src/map/clif.h b/src/map/clif.h index 206b7d68e..3994541b5 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -504,8 +504,6 @@ void clif_party_xy(struct map_session_data *sd); void clif_party_xy_single(int fd, struct map_session_data *sd); void clif_party_hp(struct map_session_data *sd); void clif_hpmeter_single(int fd, int id, unsigned int hp, unsigned int maxhp); -int clif_hpmeter(struct map_session_data *sd); -int clif_hpmeter_sub(struct block_list *bl, va_list ap); // guild void clif_guild_created(struct map_session_data *sd,int flag); diff --git a/src/map/intif.c b/src/map/intif.c index 51002f027..f074b032b 100644 --- a/src/map/intif.c +++ b/src/map/intif.c @@ -237,22 +237,22 @@ int intif_wis_replay(int id, int flag) } // The transmission of GM only Wisp/Page from server to inter-server -int intif_wis_message_to_gm(char *Wisp_name, int min_gm_level, char *mes) +int intif_wis_message_to_gm(char *wisp_name, int permission, char *mes) { int mes_len; if (CheckForCharServer()) return 0; mes_len = strlen(mes) + 1; // + null - WFIFOHEAD(inter_fd, mes_len + 30); + WFIFOHEAD(inter_fd, mes_len + 32); WFIFOW(inter_fd,0) = 0x3003; - WFIFOW(inter_fd,2) = mes_len + 30; - memcpy(WFIFOP(inter_fd,4), Wisp_name, NAME_LENGTH); - WFIFOW(inter_fd,4+NAME_LENGTH) = (short)min_gm_level; - memcpy(WFIFOP(inter_fd,6+NAME_LENGTH), mes, mes_len); + WFIFOW(inter_fd,2) = mes_len + 32; + memcpy(WFIFOP(inter_fd,4), wisp_name, NAME_LENGTH); + WFIFOL(inter_fd,4+NAME_LENGTH) = permission; + memcpy(WFIFOP(inter_fd,8+NAME_LENGTH), mes, mes_len); WFIFOSET(inter_fd, WFIFOW(inter_fd,2)); if (battle_config.etc_log) - ShowNotice("intif_wis_message_to_gm: from: '%s', min level: %d, message: '%s'.\n", Wisp_name, min_gm_level, mes); + ShowNotice("intif_wis_message_to_gm: from: '%s', required permission: %d, message: '%s'.\n", wisp_name, permission, mes); return 0; } @@ -860,11 +860,13 @@ int intif_parse_WisEnd(int fd) static int mapif_parse_WisToGM_sub(struct map_session_data* sd,va_list va) { - int min_gm_level = va_arg(va, int); + int permission = va_arg(va, int); char *wisp_name; char *message; int len; - if (pc_isGM(sd) < min_gm_level) return 0; + + if (!pc_has_permission(sd, permission)) + return 0; wisp_name = va_arg(va, char*); message = va_arg(va, char*); len = va_arg(va, int); @@ -873,22 +875,22 @@ static int mapif_parse_WisToGM_sub(struct map_session_data* sd,va_list va) } // Received wisp message from map-server via char-server for ALL gm -// 0x3003/0x3803 <packet_len>.w <wispname>.24B <min_gm_level>.w <message>.?B +// 0x3003/0x3803 <packet_len>.w <wispname>.24B <permission>.l <message>.?B int mapif_parse_WisToGM(int fd) { - int min_gm_level, mes_len; + int permission, mes_len; char Wisp_name[NAME_LENGTH]; char mbuf[255]; char *message; - mes_len = RFIFOW(fd,2) - 30; + mes_len = RFIFOW(fd,2) - 32; message = (char *) (mes_len >= 255 ? (char *) aMallocA(mes_len) : mbuf); - min_gm_level = (int)RFIFOW(fd,28); + permission = RFIFOL(fd,28); safestrncpy(Wisp_name, (char*)RFIFOP(fd,4), NAME_LENGTH); - safestrncpy(message, (char*)RFIFOP(fd,30), mes_len); - // information is sended to all online GM - map_foreachpc(mapif_parse_WisToGM_sub, min_gm_level, Wisp_name, message, mes_len); + safestrncpy(message, (char*)RFIFOP(fd,32), mes_len); + // information is sent to all online GM + map_foreachpc(mapif_parse_WisToGM_sub, permission, Wisp_name, message, mes_len); if (message != mbuf) aFree(message); diff --git a/src/map/intif.h b/src/map/intif.h index 88e1f1ce7..b1315f40c 100644 --- a/src/map/intif.h +++ b/src/map/intif.h @@ -20,7 +20,7 @@ int intif_broadcast(const char* mes, int len, int type); int intif_broadcast2(const char* mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY); int intif_wis_message(struct map_session_data *sd,char *nick,char *mes,int mes_len); -int intif_wis_message_to_gm(char *Wisp_name, int min_gm_level, char *mes); +int intif_wis_message_to_gm(char *Wisp_name, int permission, char *mes); int intif_saveregistry(struct map_session_data *sd, int type); int intif_request_registry(struct map_session_data *sd, int flag); diff --git a/src/map/log.c b/src/map/log.c index 7823b5e02..4d4fa166a 100644 --- a/src/map/log.c +++ b/src/map/log.c @@ -282,12 +282,13 @@ void log_mvpdrop(struct map_session_data* sd, int monster_id, int* log_mvp) } -/// logs used GM commands -void log_atcommand(struct map_session_data* sd, int cmdlvl, const char* message) +/// logs used atcommands +void log_atcommand(struct map_session_data* sd, const char* message) { nullpo_retv(sd); - if( cmdlvl < log_config.gm ) + if( !log_config.commands || + !pc_should_log_commands(sd) ) return; if( log_config.sql_logs ) @@ -460,8 +461,8 @@ int log_config_read(const char* cfgName) log_config.filter = config_switch(w2); else if( strcmpi(w1, "log_zeny") == 0 ) log_config.zeny = config_switch(w2); - else if( strcmpi(w1, "log_gm") == 0 ) - log_config.gm = config_switch(w2); + else if( strcmpi(w1, "log_commands") == 0 ) + log_config.commands = config_switch(w2); else if( strcmpi(w1, "log_npc") == 0 ) log_config.npc = config_switch(w2); else if( strcmpi(w1, "log_chat") == 0 ) @@ -508,9 +509,9 @@ int log_config_read(const char* cfgName) { ShowInfo("Logging chat to %s '%s'.\n", target, log_config.log_chat); } - if( log_config.gm ) + if( log_config.commands ) { - ShowInfo("Logging gm commands to %s '%s'.\n", target, log_config.log_gm); + ShowInfo("Logging commands to %s '%s'.\n", target, log_config.log_gm); } if( log_config.mvpdrop ) { diff --git a/src/map/log.h b/src/map/log.h index 5324bb599..ac85b7ccb 100644 --- a/src/map/log.h +++ b/src/map/log.h @@ -59,7 +59,7 @@ void log_zeny(struct map_session_data* sd, e_log_pick_type type, struct map_sess void log_npc(struct map_session_data* sd, const char *message); void log_chat(e_log_chat_type type, int type_id, int src_charid, int src_accid, const char* map, int x, int y, const char* dst_charname, const char* message); -void log_atcommand(struct map_session_data* sd, int cmdlvl, const char* message); +void log_atcommand(struct map_session_data* sd, const char* message); /// old, but useful logs void log_branch(struct map_session_data* sd); @@ -74,7 +74,7 @@ extern struct Log_Config bool sql_logs; bool log_chat_woe_disable; int rare_items_log,refine_items_log,price_items_log,amount_items_log; //for filter - int branch, mvpdrop, zeny, gm, npc, chat; + int branch, mvpdrop, zeny, commands, npc, chat; char log_branch[64], log_pick[64], log_zeny[64], log_mvpdrop[64], log_gm[64], log_npc[64], log_chat[64]; } log_config; diff --git a/src/map/mail.c b/src/map/mail.c index 7c1b9be21..b839c3d1f 100644 --- a/src/map/mail.c +++ b/src/map/mail.c @@ -63,7 +63,7 @@ unsigned char mail_setitem(struct map_session_data *sd, int idx, int amount) { if( idx == 0 ) { // Zeny Transfer - if( amount < 0 || !pc_can_give_items(pc_isGM(sd)) ) + if( amount < 0 || !pc_can_give_items(sd) ) return 1; if( amount > sd->status.zeny ) @@ -82,8 +82,8 @@ unsigned char mail_setitem(struct map_session_data *sd, int idx, int amount) return 1; if( amount < 0 || amount > sd->status.inventory[idx].amount ) return 1; - if( !pc_can_give_items(pc_isGM(sd)) || sd->status.inventory[idx].expire_time || - !itemdb_canmail(&sd->status.inventory[idx],pc_isGM(sd)) ) + if( !pc_can_give_items(sd) || sd->status.inventory[idx].expire_time || + !itemdb_canmail(&sd->status.inventory[idx],pc_get_group_level(sd)) ) return 1; sd->mail.index = idx; @@ -184,7 +184,7 @@ void mail_deliveryfail(struct map_session_data *sd, struct mail_message *msg) // This function only check if the mail operations are valid bool mail_invalid_operation(struct map_session_data *sd) { - if( !map[sd->bl.m].flag.town && pc_isGM(sd) < get_atcommand_level("mail") ) + if( !map[sd->bl.m].flag.town && !pc_can_use_command(sd, "mail", COMMAND_ATCOMMAND) ) { ShowWarning("clif_parse_Mail: char '%s' trying to do invalid mail operations.\n", sd->status.name); return true; diff --git a/src/map/party.c b/src/map/party.c index 2c9b45a11..8f8a0cd8a 100644 --- a/src/map/party.c +++ b/src/map/party.c @@ -344,12 +344,8 @@ int party_invite(struct map_session_data *sd,struct map_session_data *tsd) return 0; } - if ( (pc_isGM(sd) >= battle_config.lowest_gm_level && pc_isGM(tsd) < battle_config.lowest_gm_level && !battle_config.gm_can_party && pc_isGM(sd) < battle_config.gm_cant_party_min_lv) - || ( pc_isGM(sd) < battle_config.lowest_gm_level && pc_isGM(tsd) >= battle_config.lowest_gm_level && !battle_config.gm_can_party && pc_isGM(tsd) < battle_config.gm_cant_party_min_lv) ) - { - //GMs can't invite non GMs to the party if not above the invite trust level - //Likewise, as long as gm_can_party is off, players can't invite GMs. - clif_displaymessage(sd->fd, msg_txt(81)); + if (!pc_has_permission(sd, PC_PERM_PARTY) || !pc_has_permission(tsd, PC_PERM_PARTY)) { + clif_displaymessage(sd->fd, msg_txt(81)); // "Your GM level doesn't authorize you to preform this action on the specified player." return 0; } diff --git a/src/map/pc.c b/src/map/pc.c index 22f165374..94d505c15 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -37,6 +37,7 @@ #include "skill.h" #include "status.h" // struct status_data #include "pc.h" +#include "pc_groups.h" #include "quest.h" #include <stdio.h> @@ -81,9 +82,14 @@ int pc_class2idx(int class_) { return class_; } -int pc_isGM(struct map_session_data* sd) +int inline pc_get_group_id(struct map_session_data *sd) { - return sd->gmlevel; + return sd->group_id; +} + +int inline pc_get_group_level(struct map_session_data *sd) +{ + return pc_group_id2level(pc_get_group_id(sd)); } static int pc_invincible_timer(int tid, unsigned int tick, int id, intptr_t data) @@ -478,13 +484,12 @@ void pc_inventory_rental_add(struct map_session_data *sd, int seconds) sd->rental_timer = add_timer(gettick() + min(tick,3600000), pc_inventory_rental_end, sd->bl.id, 0); } -/*========================================== - Determines if the GM can give / drop / trade / vend items - Args: GM Level (current player GM level) - *------------------------------------------*/ -bool pc_can_give_items(int level) +/** + * Determines if player can give / drop / trade / vend items + */ +bool pc_can_give_items(struct map_session_data *sd) { - return( level < battle_config.gm_cant_drop_min_lv || level > battle_config.gm_cant_drop_max_lv ); + return pc_has_permission(sd, PC_PERM_TRADE); } /*========================================== @@ -815,7 +820,7 @@ int pc_isequip(struct map_session_data *sd,int n) item = sd->inventory_data[n]; - if( battle_config.gm_allequip>0 && pc_isGM(sd)>=battle_config.gm_allequip ) + if(pc_has_permission(sd, PC_PERM_USE_ALL_EQUIPMENT)) return 1; if(item == NULL) @@ -885,14 +890,14 @@ int pc_isequip(struct map_session_data *sd,int n) * session idɖ薳 * charI瑗ĂXe?^Xݒ *------------------------------------------*/ -bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_time, int gmlevel, struct mmo_charstatus *st, bool changing_mapservers) +bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_time, int group_id, struct mmo_charstatus *st, bool changing_mapservers) { int i; unsigned long tick = gettick(); uint32 ip = session[sd->fd]->client_addr; sd->login_id2 = login_id2; - sd->gmlevel = gmlevel; + sd->group_id = group_id; memcpy(&sd->status, st, sizeof(*st)); if (st->sex != sd->status.sex) { @@ -975,7 +980,7 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim pc_setequipindex(sd); status_change_init(&sd->bl); - if ((battle_config.atc_gmonly == 0 || pc_isGM(sd)) && (pc_isGM(sd) >= get_atcommand_level("hide"))) + if (pc_can_use_command(sd, "hide", COMMAND_ATCOMMAND)) sd->status.option &= (OPTION_MASK | OPTION_INVISIBLE); else sd->status.option &= OPTION_MASK; @@ -1015,20 +1020,12 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim sd->die_counter=-1; //display login notice - if( sd->gmlevel >= battle_config.lowest_gm_level ) - ShowInfo("GM '"CL_WHITE"%s"CL_RESET"' logged in." - " (AID/CID: '"CL_WHITE"%d/%d"CL_RESET"'," - " Packet Ver: '"CL_WHITE"%d"CL_RESET"', IP: '"CL_WHITE"%d.%d.%d.%d"CL_RESET"'," - " GM Level '"CL_WHITE"%d"CL_RESET"').\n", - sd->status.name, sd->status.account_id, sd->status.char_id, - sd->packet_ver, CONVIP(ip), sd->gmlevel); - else - ShowInfo("'"CL_WHITE"%s"CL_RESET"' logged in." - " (AID/CID: '"CL_WHITE"%d/%d"CL_RESET"'," - " Packet Ver: '"CL_WHITE"%d"CL_RESET"', IP: '"CL_WHITE"%d.%d.%d.%d"CL_RESET"').\n", - sd->status.name, sd->status.account_id, sd->status.char_id, - sd->packet_ver, CONVIP(ip)); - + ShowInfo("'"CL_WHITE"%s"CL_RESET"' logged in." + " (AID/CID: '"CL_WHITE"%d/%d"CL_RESET"'," + " Packet Ver: '"CL_WHITE"%d"CL_RESET"', IP: '"CL_WHITE"%d.%d.%d.%d"CL_RESET"'," + " Group '"CL_WHITE"%d"CL_RESET"').\n", + sd->status.name, sd->status.account_id, sd->status.char_id, + sd->packet_ver, CONVIP(ip), sd->group_id); // Send friends list clif_friendslist_send(sd); @@ -1280,7 +1277,7 @@ int pc_calc_skilltree(struct map_session_data *sd) } } - if( battle_config.gm_allskill > 0 && pc_isGM(sd) >= battle_config.gm_allskill ) { + if( pc_has_permission(sd, PC_PERM_ALL_SKILL) ) { for( i = 0; i < MAX_SKILL; i++ ) { switch(i) { /** @@ -4004,7 +4001,7 @@ int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amoun return 1; data = itemdb_search(item_data->nameid); - if( !itemdb_cancartstore(item_data, pc_isGM(sd)) ) + if( !itemdb_cancartstore(item_data, pc_get_group_level(sd)) ) { // Check item trade restrictions [Skotlex] clif_displaymessage (sd->fd, msg_txt(264)); return 1; @@ -4451,45 +4448,6 @@ int pc_randomwarp(struct map_session_data *sd, clr_type type) return 0; } - -/// Warps one player to another. -/// @param sd player to warp. -/// @param pl_sd player to warp to. -int pc_warpto(struct map_session_data* sd, struct map_session_data* pl_sd) -{ - if( map[sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd) ) - { - return -2; - } - - if( map[pl_sd->bl.m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd) ) - { - return -3; - } - - return pc_setpos(sd, pl_sd->mapindex, pl_sd->bl.x, pl_sd->bl.y, CLR_TELEPORT); -} - - -/// Recalls one player to another. -/// @param sd player to warp to. -/// @param pl_sd player to warp. -int pc_recall(struct map_session_data* sd, struct map_session_data* pl_sd) -{ - if( map[pl_sd->bl.m].flag.nowarp && battle_config.any_warp_GM_min_level > pc_isGM(sd) ) - { - return -2; - } - - if( map[sd->bl.m].flag.nowarpto && battle_config.any_warp_GM_min_level > pc_isGM(sd) ) - { - return -3; - } - - return pc_setpos(pl_sd, sd->mapindex, sd->bl.x, sd->bl.y, CLR_RESPAWN); -} - - /*========================================== * Records a memo point at sd's current position * pos - entry to replace, (-1: shift oldest entry out) @@ -4501,7 +4459,7 @@ int pc_memo(struct map_session_data* sd, int pos) nullpo_ret(sd); // check mapflags - if( sd->bl.m >= 0 && (map[sd->bl.m].flag.nomemo || map[sd->bl.m].flag.nowarpto) && battle_config.any_warp_GM_min_level > pc_isGM(sd) ) { + if( sd->bl.m >= 0 && (map[sd->bl.m].flag.nomemo || map[sd->bl.m].flag.nowarpto) && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE) ) { clif_skill_teleportmessage(sd, 1); // "Saved point cannot be memorized." return 0; } @@ -5586,7 +5544,7 @@ int pc_allskillup(struct map_session_data *sd) } //pc_calc_skilltree takes care of setting the ID to valid skills. [Skotlex] - if (battle_config.gm_allskill > 0 && pc_isGM(sd) >= battle_config.gm_allskill) + if (pc_has_permission(sd, PC_PERM_ALL_SKILL)) { //Get ALL skills except npc/guild ones. [Skotlex] //and except SG_DEVIL [Komurka] and MO_TRIPLEATTACK and RG_SNATCHER [ultramage] for(i=0;i<MAX_SKILL;i++){ @@ -5761,6 +5719,13 @@ int pc_resetstate(struct map_session_data* sd) clif_updatestatus(sd,SP_ULUK); // End Addition clif_updatestatus(sd,SP_STATUSPOINT); + + if( sd->mission_mobid ) { //bugreport:2200 + sd->mission_mobid = 0; + sd->mission_count = 0; + pc_setglobalreg(sd,"TK_MISSION_ID", 0); + } + status_calc_pc(sd,0); return 1; @@ -7026,14 +6991,13 @@ int pc_setriding(TBL_PC* sd, int flag) /*========================================== * ACehbvs *------------------------------------------*/ -int pc_candrop(struct map_session_data *sd,struct item *item) +int pc_candrop(struct map_session_data *sd, struct item *item) { - int level = pc_isGM(sd); if( item && item->expire_time ) return 0; - if( !pc_can_give_items(level) ) //check if this GM level can drop items + if( !pc_can_give_items(sd) ) //check if this GM level can drop items return 0; - return (itemdb_isdropable(item, level)); + return (itemdb_isdropable(item, pc_get_group_level(sd))); } /*========================================== @@ -8255,6 +8219,37 @@ bool pc_isautolooting(struct map_session_data *sd, int nameid) return (i != AUTOLOOTITEM_SIZE); } +/** + * Checks if player can use @/#command + * @param sd Player map session data + * @param command Command name without @/# and params + * @param type is it atcommand or charcommand + */ +bool pc_can_use_command(struct map_session_data *sd, const char *command, AtCommandType type) +{ + return pc_group_can_use_command(pc_get_group_id(sd), command, type); +} + +/** + * Checks if player has a permission + * @param sd Player map session data + * @param permission permission to check + */ +bool pc_has_permission(struct map_session_data *sd, int permission) +{ + return pc_group_has_permission(pc_get_group_id(sd), permission); +} + +/** + * Checks if commands used by a player should be logged + * according to their group setting. + * @param sd Player map session data + */ +bool pc_should_log_commands(struct map_session_data *sd) +{ + return pc_group_should_log_commands(pc_get_group_id(sd)); +} + int pc_split_str(char *str,char **val,int num) { int i; @@ -8628,6 +8623,7 @@ int pc_read_motd(void) *------------------------------------------*/ void do_final_pc(void) { + do_final_pc_groups(); return; } @@ -8665,5 +8661,7 @@ int do_init_pc(void) } } + do_init_pc_groups(); + return 0; } diff --git a/src/map/pc.h b/src/map/pc.h index 34c05d7b8..47d9edead 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -6,6 +6,7 @@ #include "../common/mmo.h" // JOB_*, MAX_FAME_LIST, struct fame_list, struct mmo_charstatus #include "../common/timer.h" // INVALID_TIMER +#include "atcommand.h" // AtCommandType #include "battle.h" // battle_config #include "buyingstore.h" // struct s_buyingstore #include "itemdb.h" // MAX_ITEMGROUP @@ -159,7 +160,7 @@ struct map_session_data { } special_state; int login_id1, login_id2; unsigned short class_; //This is the internal job ID used by the map server to simplify comparisons/queries/etc. [Skotlex] - int gmlevel; + int group_id; int packet_ver; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 ... 18 struct mmo_charstatus status; @@ -568,6 +569,27 @@ enum equip_index { EQI_MAX }; +enum e_pc_permission { + PC_PERM_NONE = 0, + PC_PERM_TRADE = 0x00001, + PC_PERM_PARTY = 0x00002, + PC_PERM_ALL_SKILL = 0x00004, + PC_PERM_USE_ALL_EQUIPMENT = 0x00008, + PC_PERM_SKILL_UNCONDITIONAL = 0x00010, + PC_PERM_JOIN_ALL_CHAT = 0x00020, + PC_PERM_NO_CHAT_KICK = 0x00040, + PC_PERM_HIDE_SESSION = 0x00080, + PC_PERM_WHO_DISPLAY_AID = 0x00100, + PC_PERM_RECEIVE_HACK_INFO = 0x00200, + PC_PERM_WARP_ANYWHERE = 0x00400, + PC_PERM_VIEW_HPMETER = 0x00800, + PC_PERM_VIEW_EQUIPMENT = 0x01000, + PC_PERM_USE_CHECK = 0x02000, + PC_PERM_USE_CHANGEMAPTYPE = 0x04000, + PC_PERM_USE_ALL_COMMANDS = 0x08000, + PC_PERM_RECEIVE_REQUESTS = 0x10000, +}; + #define pc_setdead(sd) ( (sd)->state.dead_sit = (sd)->vd.dead_sit = 1 ) #define pc_setsit(sd) ( (sd)->state.dead_sit = (sd)->vd.dead_sit = 2 ) #define pc_isdead(sd) ( (sd)->state.dead_sit == 1 ) @@ -608,15 +630,20 @@ enum equip_index { ) int pc_class2idx(int class_); -int pc_isGM(struct map_session_data *sd); +int pc_get_group_level(struct map_session_data *sd); +int pc_get_group_id(struct map_session_data *sd); int pc_getrefinebonus(int lv,int type); -bool pc_can_give_items(int level); +bool pc_can_give_items(struct map_session_data *sd); + +bool pc_can_use_command(struct map_session_data *sd, const char *command, AtCommandType type); +bool pc_has_permission(struct map_session_data *sd, int permission); +bool pc_should_log_commands(struct map_session_data *sd); int pc_setrestartvalue(struct map_session_data *sd,int type); int pc_makesavestatus(struct map_session_data *); void pc_respawn(struct map_session_data* sd, clr_type clrtype); int pc_setnewpc(struct map_session_data*,int,int,int,unsigned int,int,int); -bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_time, int gmlevel, struct mmo_charstatus *st, bool changing_mapservers); +bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_time, int group_id, struct mmo_charstatus *st, bool changing_mapservers); void pc_authfail(struct map_session_data *); int pc_reg_received(struct map_session_data *sd); @@ -638,8 +665,6 @@ int pc_clean_skilltree(struct map_session_data *sd); int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y, clr_type clrtype); int pc_setsavepoint(struct map_session_data*,short,int,int); int pc_randomwarp(struct map_session_data *sd,clr_type type); -int pc_warpto(struct map_session_data* sd, struct map_session_data* pl_sd); -int pc_recall(struct map_session_data* sd, struct map_session_data* pl_sd); int pc_memo(struct map_session_data* sd, int pos); int pc_checkadditem(struct map_session_data*,int,int); diff --git a/src/map/pc_groups.c b/src/map/pc_groups.c new file mode 100644 index 000000000..3ceb905ba --- /dev/null +++ b/src/map/pc_groups.c @@ -0,0 +1,459 @@ +// Copyright (c) Athena Dev Teams - Licensed under GNU GPL +// For more information, see LICENCE in the main folder + +#include "../common/conf.h" +#include "../common/db.h" +#include "../common/malloc.h" +#include "../common/nullpo.h" +#include "../common/showmsg.h" +#include "../common/strlib.h" // strcmp + +#include "atcommand.h" // AtCommandType +#include "pc_groups.h" +#include "pc.h" // e_pc_permission + + +typedef struct GroupSettings GroupSettings; + +// Cached config settings/pointers for quick lookup +struct GroupSettings { + unsigned int id; // groups.[].id + int level; // groups.[].level + const char *name; // groups.[].name + config_setting_t *commands; // groups.[].commands + unsigned int e_permissions; // packed groups.[].permissions + bool log_commands; // groups.[].log_commands + /// Following are used only during config reading + config_setting_t *permissions; // groups.[].permissions + config_setting_t *inherit; // groups.[].inherit + bool inheritance_done; // have all inheritance rules been evaluated? + config_setting_t *root; // groups.[] +}; + + +static config_t pc_group_config; +static DBMap* pc_group_db; // id -> GroupSettings +static DBMap* pc_groupname_db; // name -> GroupSettings + +static const struct { + const char *name; + int permission; +} permission_name[] = { + { "can_trade", PC_PERM_TRADE }, + { "can_party", PC_PERM_PARTY }, + { "all_skill", PC_PERM_ALL_SKILL }, + { "all_equipment", PC_PERM_USE_ALL_EQUIPMENT }, + { "skill_unconditional", PC_PERM_SKILL_UNCONDITIONAL }, + { "join_chat", PC_PERM_JOIN_ALL_CHAT }, + { "kick_chat", PC_PERM_NO_CHAT_KICK }, + { "hide_session", PC_PERM_HIDE_SESSION }, + { "who_display_aid", PC_PERM_WHO_DISPLAY_AID }, + { "hack_info", PC_PERM_RECEIVE_HACK_INFO }, + { "any_warp", PC_PERM_WARP_ANYWHERE }, + { "view_hpmeter", PC_PERM_VIEW_HPMETER }, + { "view_equipment", PC_PERM_VIEW_EQUIPMENT }, + { "use_check", PC_PERM_USE_CHECK }, + { "use_changemaptype", PC_PERM_USE_CHANGEMAPTYPE }, + { "all_commands", PC_PERM_USE_ALL_COMMANDS }, + { "receive_requests", PC_PERM_RECEIVE_REQUESTS }, +}; + +/** + * @retval NULL if not found + * @private + */ +static inline GroupSettings* id2group(int group_id) +{ + return (GroupSettings*)idb_get(pc_group_db, group_id); +} + +/** + * @retval NULL if not found + * @private + */ +static inline GroupSettings* name2group(const char* group_name) +{ + return (GroupSettings*)strdb_get(pc_groupname_db, group_name); +} + +/** + * Loads group configuration from config file into memory. + * @private + */ +static void read_config(void) +{ + config_setting_t *groups = NULL; + const char *config_filename = "conf/groups.conf"; // FIXME hardcoded name + int group_count = 0; + + if (conf_read_file(&pc_group_config, config_filename)) + return; + + groups = config_lookup(&pc_group_config, "groups"); + + if (groups != NULL) { + GroupSettings *group_settings = NULL; + DBIterator *iter = NULL; + int i, loop = 0; + + group_count = config_setting_length(groups); + for (i = 0; i < group_count; ++i) { + int id = 0, level = 0; + const char *groupname = NULL; + int log_commands = 0; + config_setting_t *group = config_setting_get_elem(groups, i); + + if (!config_setting_lookup_int(group, "id", &id)) { + ShowConfigWarning(group, "pc_groups:read_config: \"groups\" list member #%d has undefined id, removing...", i); + config_setting_remove_elem(groups, i); + --i; + --group_count; + continue; + } + + if (id2group(id) != NULL) { + ShowConfigWarning(group, "pc_groups:read_config: duplicate group id %d, removing...", i); + config_setting_remove_elem(groups, i); + --i; + --group_count; + continue; + } + + config_setting_lookup_int(group, "level", &level); + config_setting_lookup_int(group, "log_commands", &log_commands); + + if (!config_setting_lookup_string(group, "name", &groupname)) { + char temp[20]; + config_setting_t *name = NULL; + snprintf(temp, sizeof(temp), "Group %d", id); + if ((name = config_setting_add(group, "name", CONFIG_TYPE_STRING)) == NULL || + !config_setting_set_string(name, temp)) { + ShowError("pc_groups:read_config: failed to set missing group name, id=%d, skipping... (%s:%d)\n", + id, config_setting_source_file(group), config_setting_source_line(group)); + continue; + } + config_setting_lookup_string(group, "name", &groupname); // Retrieve the pointer + } + + if (name2group(groupname) != NULL) { + ShowConfigWarning(group, "pc_groups:read_config: duplicate group name %s, removing...", groupname); + config_setting_remove_elem(groups, i); + --i; + --group_count; + continue; + } + + CREATE(group_settings, GroupSettings, 1); + group_settings->id = id; + group_settings->level = level; + group_settings->name = groupname; + group_settings->log_commands = (bool)log_commands; + group_settings->inherit = config_setting_get_member(group, "inherit"); + group_settings->commands = config_setting_get_member(group, "commands"); + group_settings->permissions = config_setting_get_member(group, "permissions"); + group_settings->inheritance_done = false; + group_settings->root = group; + + strdb_put(pc_groupname_db, groupname, group_settings); + idb_put(pc_group_db, id, group_settings); + + } + group_count = config_setting_length(groups); // Save number of groups + + // Check if all commands and permissions exist + iter = pc_group_db->iterator(pc_group_db); + for (group_settings = (GroupSettings*)iter->first(iter, NULL); + iter->exists(iter); + group_settings = (GroupSettings*)iter->next(iter, NULL)) { + config_setting_t *commands = group_settings->commands, *permissions = group_settings->permissions; + int count = 0, i; + + // Make sure there is "commands" group + if (commands == NULL) + commands = group_settings->commands = config_setting_add(group_settings->root, "commands", CONFIG_TYPE_GROUP); + count = config_setting_length(commands); + + for (i = 0; i < count; ++i) { + config_setting_t *command = config_setting_get_elem(commands, i); + const char *name = config_setting_name(command); + if (!atcommand_exists(name)) { + ShowConfigWarning(command, "pc_groups:read_config: non-existent command name '%s', removing...", name); + config_setting_remove(commands, name); + --i; + --count; + } + } + + // Make sure there is "permissions" group + if (permissions == NULL) + permissions = group_settings->permissions = config_setting_add(group_settings->root, "permissions", CONFIG_TYPE_GROUP); + count = config_setting_length(permissions); + + for(i = 0; i < count; ++i) { + config_setting_t *permission = config_setting_get_elem(permissions, i); + const char *name = config_setting_name(permission); + int j; + + ARR_FIND(0, ARRAYLENGTH(permission_name), j, strcmp(permission_name[j].name, name) == 0); + if (j == ARRAYLENGTH(permission_name)) { + ShowConfigWarning(permission, "pc_groups:read_config: non-existent permission name '%s', removing...", name); + config_setting_remove(permissions, name); + --i; + --count; + } + } + } + iter->destroy(iter); + + // Apply inheritance + i = 0; // counter for processed groups + while (i < group_count) { + iter = pc_group_db->iterator(pc_group_db); + for (group_settings = (GroupSettings*)iter->first(iter, NULL); + iter->exists(iter); + group_settings = (GroupSettings*)iter->next(iter, NULL)) { + config_setting_t *inherit = NULL, + *commands = group_settings->commands, + *permissions = group_settings->permissions; + int j, inherit_count = 0, done = 0; + + if (group_settings->inheritance_done) // group already processed + continue; + + if ((inherit = group_settings->inherit) == NULL || + (inherit_count = config_setting_length(inherit)) <= 0) { // this group does not inherit from others + ++i; + group_settings->inheritance_done = true; + continue; + } + + for (j = 0; j < inherit_count; ++j) { + GroupSettings *inherited_group = NULL; + const char *groupname = config_setting_get_string_elem(inherit, j); + + if (groupname == NULL) { + ShowConfigWarning(inherit, "pc_groups:read_config: \"inherit\" array member #%d is not a name, removing...", j); + config_setting_remove_elem(inherit,j); + continue; + } + if ((inherited_group = name2group(groupname)) == NULL) { + ShowConfigWarning(inherit, "pc_groups:read_config: non-existent group name \"%s\", removing...", groupname); + config_setting_remove_elem(inherit,j); + continue; + } + if (!inherited_group->inheritance_done) + continue; // we need to do that group first + + // Copy settings (commands/permissions) that are not defined yet + if (inherited_group->commands != NULL) { + int i = 0, commands_count = config_setting_length(inherited_group->commands); + for (i = 0; i < commands_count; ++i) + config_setting_copy(commands, config_setting_get_elem(inherited_group->commands, i)); + } + + if (inherited_group->permissions != NULL) { + int i = 0, permissions_count = config_setting_length(inherited_group->permissions); + for (i = 0; i < permissions_count; ++i) + config_setting_copy(permissions, config_setting_get_elem(inherited_group->permissions, i)); + } + + ++done; // copied commands and permissions from one of inherited groups + } + + if (done == inherit_count) { // copied commands from all of inherited groups + ++i; + group_settings->inheritance_done = true; // we're done with this group + } + } + iter->destroy(iter); + + if (++loop > group_count) { + ShowWarning("pc_groups:read_config: Could not process inheritance rules, check your config '%s' for cycles...\n", + config_filename); + break; + } + } // while(i < group_count) + + // Pack permissions into GroupSettings.e_permissions for faster checking + iter = db_iterator(pc_group_db); + for (group_settings = (GroupSettings*)dbi_first(iter); + dbi_exists(iter); + group_settings = (GroupSettings*)dbi_next(iter)) { + config_setting_t *permissions = group_settings->permissions; + int i, count = config_setting_length(permissions); + + for (i = 0; i < count; ++i) { + config_setting_t *perm = config_setting_get_elem(permissions, i); + const char *name = config_setting_name(perm); + int j; + + ARR_FIND(0, ARRAYLENGTH(permission_name), j, strcmp(permission_name[j].name, name) == 0); + group_settings->e_permissions |= permission_name[j].permission; + } + } + iter->destroy(iter); + } + + ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' groups in '"CL_WHITE"%s"CL_RESET"'.\n", group_count, config_filename); +} + +/** + * Removes group configuration from memory. + * @private + */ +static void destroy_config(void) +{ + config_destroy(&pc_group_config); +} + +/** + * In group configuration file, setting for each command is either + * <commandname> : <bool> (only atcommand), or + * <commandname> : [ <bool>, <bool> ] ([ atcommand, charcommand ]) + * Maps AtCommandType enums to indexes of <commandname> value array, + * COMMAND_ATCOMMAND (1) being index 0, COMMAND_CHARCOMMAND (2) being index 1. + * @private + */ +static inline int AtCommandType2idx(AtCommandType type) { return (type-1); } + +/** + * Checks if player group can use @/#command + * @param group_id ID of the group + * @param command Command name without @/# and params + * @param type enum AtCommanndType { COMMAND_ATCOMMAND = 1, COMMAND_CHARCOMMAND = 2 } + */ +bool pc_group_can_use_command(int group_id, const char *command, AtCommandType type) +{ + int result = 0; + config_setting_t *commands = NULL; + GroupSettings *group = NULL; + + if (pc_group_has_permission(group_id, PC_PERM_USE_ALL_COMMANDS)) + return true; + + if ((group = id2group(group_id)) == NULL) + return false; + + commands = group->commands; + if (commands != NULL) { + config_setting_t *cmd = NULL; + + // <commandname> : <bool> (only atcommand) + if (type == COMMAND_ATCOMMAND && config_setting_lookup_bool(commands, command, &result)) + return (bool)result; + + // <commandname> : [ <bool>, <bool> ] ([ atcommand, charcommand ]) + if ((cmd = config_setting_get_member(commands, command)) != NULL && + config_setting_is_aggregate(cmd) && config_setting_length(cmd) == 2) + return (bool)config_setting_get_bool_elem(cmd, AtCommandType2idx(type)); + } + return false; +} + +/** + * Checks if player group has a permission + * @param group_id ID of the group + * @param permission permission to check + */ +bool pc_group_has_permission(int group_id, int permission) +{ + GroupSettings *group = NULL; + if ((group = id2group(group_id)) == NULL) + return false; + return ((group->e_permissions&permission) != 0); +} + +/** + * Checks commands used by player group should be logged + * @param group_id ID of the group + */ +bool pc_group_should_log_commands(int group_id) +{ + GroupSettings *group = NULL; + if ((group = id2group(group_id)) == NULL) + return false; + return group->log_commands; +} + +/** + * Checks if player group with given ID exists. + * @param group_id group id + * @returns true if group exists, false otherwise + */ +bool pc_group_exists(int group_id) +{ + return idb_exists(pc_group_db, group_id); +} + +/** + * Group ID -> group name lookup. Used only in @who atcommands. + * @param group_id group id + * @return group name + * @public + */ +const char* pc_group_id2name(int group_id) +{ + GroupSettings *group = id2group(group_id); + if (group == NULL) + return "Non-existent group!"; + return group->name; +} + +/** + * Group ID -> group level lookup. A way to provide backward compatibility with GM level system. + * @param group id + * @return group level + * @public + */ +int pc_group_id2level(int group_id) +{ + GroupSettings *group = id2group(group_id); + if (group == NULL) + return 0; + return group->level; +} + +/** + * Initialize PC Groups: allocate DBMaps and read config. + * @public + */ +void do_init_pc_groups(void) +{ + pc_group_db = idb_alloc(DB_OPT_BASE); + pc_groupname_db = stridb_alloc(DB_OPT_DUP_KEY, 0); + read_config(); +} + +/** + * DBApply helper function for do_final_pc_groups + * @private + */ +static int group_db_free(DBKey key, void *data, va_list args) +{ + aFree((GroupSettings*)data); + return 1; +} + +/** + * Finalize PC Groups: free DBMaps and config. + * @public + */ +void do_final_pc_groups(void) +{ + if (pc_group_db != NULL) + pc_group_db->destroy(pc_group_db, group_db_free); + if (pc_groupname_db != NULL ) + db_destroy(pc_groupname_db); + destroy_config(); +} + +/** + * Reload PC Groups + * Used in @reloadatcommand + * @public + */ +void pc_groups_reload(void) +{ + do_final_pc_groups(); + do_init_pc_groups(); +}
\ No newline at end of file diff --git a/src/map/pc_groups.h b/src/map/pc_groups.h new file mode 100644 index 000000000..1134bc01a --- /dev/null +++ b/src/map/pc_groups.h @@ -0,0 +1,20 @@ +// Copyright (c) Athena Dev Teams - Licensed under GNU GPL +// For more information, see LICENCE in the main folder + +#ifndef _PC_GROUPS_H_ +#define _PC_GROUPS_H_ + +#include "atcommand.h" // AtCommandType + +bool pc_group_exists(int group_id); +bool pc_group_can_use_command(int group_id, const char *command, AtCommandType type); +bool pc_group_has_permission(int group_id, int permission); +bool pc_group_should_log_commands(int group_id); +const char* pc_group_id2name(int group_id); +int pc_group_id2level(int group_id); + +void do_init_pc_groups(void); +void do_final_pc_groups(void); +void pc_groups_reload(void); + +#endif // _PC_GROUPS_H_
\ No newline at end of file diff --git a/src/map/script.c b/src/map/script.c index 0a92ae835..705eb041b 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -7345,7 +7345,7 @@ BUILDIN_FUNC(getgmlevel) if( sd == NULL ) return 0;// no player attached, report source - script_pushint(st, pc_isGM(sd)); + script_pushint(st, pc_get_group_level(sd)); return 0; } @@ -8704,17 +8704,18 @@ BUILDIN_FUNC(getusers) BUILDIN_FUNC(getusersname) { TBL_PC *sd, *pl_sd; - int disp_num=1; + int disp_num=1, group_level = 0; struct s_mapiterator* iter; sd = script_rid2sd(st); if (!sd) return 0; + group_level = pc_get_group_level(sd); iter = mapit_getallusers(); for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) { - if( battle_config.hide_GM_session && pc_isGM(pl_sd) ) - continue; // skip hidden GMs + if (pc_has_permission(pl_sd, PC_PERM_HIDE_SESSION) && pc_get_group_level(pl_sd) > group_level) + continue; // skip hidden sessions if((disp_num++)%10==0) clif_scriptnext(sd,st->oid); @@ -11586,9 +11587,6 @@ BUILDIN_FUNC(nude) /*========================================== * gmcommand [MouseJstr] - * - * suggested on the forums... - * splitted into atcommand & charcommand by [Skotlex] *------------------------------------------*/ BUILDIN_FUNC(atcommand) { @@ -11616,51 +11614,12 @@ BUILDIN_FUNC(atcommand) } } - // compatibility with previous implementation (deprecated!) - if(cmd[0] != atcommand_symbol) - { - cmd += strlen(sd->status.name); - while(*cmd != atcommand_symbol && *cmd != 0) - cmd++; - } - - is_atcommand(fd, sd, cmd, 0); - return 0; -} - -BUILDIN_FUNC(charcommand) -{ - TBL_PC dummy_sd; - TBL_PC* sd; - int fd; - const char* cmd; - - cmd = script_getstr(st,2); - - if (st->rid) { - sd = script_rid2sd(st); - fd = sd->fd; - } else { //Use a dummy character. - sd = &dummy_sd; - fd = 0; - - memset(&dummy_sd, 0, sizeof(TBL_PC)); - if (st->oid) - { - struct block_list* bl = map_id2bl(st->oid); - memcpy(&dummy_sd.bl, bl, sizeof(struct block_list)); - if (bl->type == BL_NPC) - safestrncpy(dummy_sd.status.name, ((TBL_NPC*)bl)->name, NAME_LENGTH); - } - } - - if (*cmd != charcommand_symbol) { - ShowWarning("script: buildin_charcommand: No '#' symbol!\n"); + if (!is_atcommand(fd, sd, cmd, 0)) { + ShowWarning("script: buildin_atcommand: failed to execute command '%s'\n", cmd); script_reportsrc(st); return 1; } - - is_atcommand(fd, sd, cmd, 0); + return 0; } @@ -16170,7 +16129,7 @@ struct script_function buildin_func[] = { BUILDIN_DEF(nude,""), // nude command [Valaris] BUILDIN_DEF(mapwarp,"ssii??"), // Added by RoVeRT BUILDIN_DEF(atcommand,"s"), // [MouseJstr] - BUILDIN_DEF(charcommand,"s"), // [MouseJstr] + BUILDIN_DEF2(atcommand,"charcommand","s"), // [MouseJstr] BUILDIN_DEF(movenpc,"sii?"), // [MouseJstr] BUILDIN_DEF(message,"ss"), // [MouseJstr] BUILDIN_DEF(npctalk,"s"), // [Valaris] diff --git a/src/map/skill.c b/src/map/skill.c index 2fef37baf..9bf915917 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -436,8 +436,8 @@ int skillnotok (int skillid, struct map_session_data *sd) if (i == 0) return 1; // invalid skill id - if (battle_config.gm_skilluncond && pc_isGM(sd) >= battle_config.gm_skilluncond) - return 0; // GMs can do any damn thing they want + if (pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL)) + return 0; // can do any damn thing they want if( skillid == AL_TELEPORT && sd->skillitem == skillid && sd->skillitemlv > 2 ) return 0; // Teleport lv 3 bypasses this check.[Inkfish] @@ -5412,7 +5412,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in case MC_VENDING: if(sd) { //Prevent vending of GMs with unnecessary Level to trade/drop. [Skotlex] - if ( !pc_can_give_items(pc_isGM(sd)) ) + if ( !pc_can_give_items(sd) ) clif_skill_fail(sd,skillid,USESKILL_FAIL_LEVEL,0); else { sd->state.prevend = 1; @@ -10256,8 +10256,7 @@ int skill_check_pc_partner (struct map_session_data *sd, short skill_id, short* static int p_sd[2] = { 0, 0 }; int i; - if (!battle_config.player_skill_partner_check || - (battle_config.gm_skilluncond && pc_isGM(sd) >= battle_config.gm_skilluncond)) + if (!battle_config.player_skill_partner_check || pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL)) return 99; //As if there were infinite partners. if (cast_flag) @@ -10352,7 +10351,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh if (lv <= 0 || sd->chatID) return 0; - if( battle_config.gm_skilluncond && pc_isGM(sd)>= battle_config.gm_skilluncond && sd->skillitem != skill ) + if( pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL) && sd->skillitem != skill ) { //GMs don't override the skillItem check, otherwise they can use items without them being consumed! [Skotlex] sd->state.arrow_atk = skill_get_ammotype(skill)?1:0; //Need to do arrow state check. sd->spiritball_old = sd->spiritball; //Need to do Spiritball check. @@ -11028,7 +11027,7 @@ int skill_check_condition_castend(struct map_session_data* sd, short skill, shor if( lv <= 0 || sd->chatID ) return 0; - if( battle_config.gm_skilluncond && pc_isGM(sd) >= battle_config.gm_skilluncond && sd->skillitem != skill ) + if( pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL) && sd->skillitem != skill ) { //GMs don't override the skillItem check, otherwise they can use items without them being consumed! [Skotlex] sd->state.arrow_atk = skill_get_ammotype(skill)?1:0; //Need to do arrow state check. sd->spiritball_old = sd->spiritball; //Need to do Spiritball check. diff --git a/src/map/storage.c b/src/map/storage.c index 12d9a8107..4f6dfff0e 100644 --- a/src/map/storage.c +++ b/src/map/storage.c @@ -95,7 +95,7 @@ int storage_storageopen(struct map_session_data *sd) if(sd->state.storage_flag) return 1; //Already open? - if( !pc_can_give_items(pc_isGM(sd)) ) + if( !pc_can_give_items(sd) ) { //check is this GM level is allowed to put items to storage clif_displaymessage(sd->fd, msg_txt(246)); return 1; @@ -138,7 +138,7 @@ static int storage_additem(struct map_session_data* sd, struct item* item_data, data = itemdb_search(item_data->nameid); - if( !itemdb_canstore(item_data, pc_isGM(sd)) ) + if( !itemdb_canstore(item_data, pc_get_group_level(sd)) ) { //Check if item is storable. [Skotlex] clif_displaymessage (sd->fd, msg_txt(264)); return 1; @@ -357,7 +357,7 @@ int storage_guild_storageopen(struct map_session_data* sd) if(sd->state.storage_flag) return 1; //Can't open both storages at a time. - if( !pc_can_give_items(pc_isGM(sd)) ) { //check is this GM level can open guild storage and store items [Lupus] + if( !pc_can_give_items(sd) ) { //check is this GM level can open guild storage and store items [Lupus] clif_displaymessage(sd->fd, msg_txt(246)); return 1; } @@ -391,7 +391,7 @@ int guild_storage_additem(struct map_session_data* sd, struct guild_storage* sto data = itemdb_search(item_data->nameid); - if( !itemdb_canguildstore(item_data, pc_isGM(sd)) || item_data->expire_time ) + if( !itemdb_canguildstore(item_data, pc_get_group_level(sd)) || item_data->expire_time ) { //Check if item is storable. [Skotlex] clif_displaymessage (sd->fd, msg_txt(264)); return 1; diff --git a/src/map/trade.c b/src/map/trade.c index 3c398ab83..cfc4992e8 100644 --- a/src/map/trade.c +++ b/src/map/trade.c @@ -29,8 +29,6 @@ *------------------------------------------*/ void trade_traderequest(struct map_session_data *sd, struct map_session_data *target_sd) { - int level; - nullpo_retv(sd); if (map[sd->bl.m].flag.notrade) { @@ -61,18 +59,16 @@ void trade_traderequest(struct map_session_data *sd, struct map_session_data *ta return; } - level = pc_isGM(sd); - if ( !pc_can_give_items(level) || !pc_can_give_items(pc_isGM(target_sd)) ) //check if both GMs are allowed to trade + if (!pc_can_give_items(sd) || !pc_can_give_items(target_sd)) //check if both GMs are allowed to trade { clif_displaymessage(sd->fd, msg_txt(246)); clif_tradestart(sd, 2); // GM is not allowed to trade return; } - //Fixed. Only real GMs can request trade from far away! [Lupus] - if (level < battle_config.lowest_gm_level && (sd->bl.m != target_sd->bl.m || - !check_distance_bl(&sd->bl, &target_sd->bl, TRADE_DISTANCE) - )) { + // Players can not request trade from far away, unless they are allowed to use @trade. + if (!pc_can_use_command(sd, "trade", COMMAND_ATCOMMAND) && + (sd->bl.m != target_sd->bl.m || !check_distance_bl(&sd->bl, &target_sd->bl, TRADE_DISTANCE))) { clif_tradestart(sd, 0); // too far return ; } @@ -127,10 +123,10 @@ void trade_tradeack(struct map_session_data *sd, int type) if (type != 3) return; //If client didn't send accept, it's a broken packet? - //Copied here as well since the original character could had warped. - if (pc_isGM(tsd) < battle_config.lowest_gm_level && (sd->bl.m != tsd->bl.m || - !check_distance_bl(&sd->bl, &tsd->bl, TRADE_DISTANCE) - )) { + // Players can not request trade from far away, unless they are allowed to use @trade. + // Check here as well since the original character could had warped. + if (!pc_can_use_command(sd, "trade", COMMAND_ATCOMMAND) && + (sd->bl.m != tsd->bl.m || !check_distance_bl(&sd->bl, &tsd->bl, TRADE_DISTANCE))) { clif_tradestart(sd, 0); // too far sd->trade_partner=0; tsd->trade_partner = 0; @@ -196,9 +192,9 @@ int impossible_trade_check(struct map_session_data *sd) if (inventory[index].amount < sd->deal.item[i].amount) { // if more than the player have -> hack sprintf(message_to_gm, msg_txt(538), sd->status.name, sd->status.account_id); // Hack on trade: character '%s' (account: %d) try to trade more items that he has. - intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, message_to_gm); + intif_wis_message_to_gm(wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm); sprintf(message_to_gm, msg_txt(539), inventory[index].amount, inventory[index].nameid, sd->deal.item[i].amount); // This player has %d of a kind of item (id: %d), and try to trade %d of them. - intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, message_to_gm); + intif_wis_message_to_gm(wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm); // if we block people if (battle_config.ban_hack_trade < 0) { chrif_char_ask_name(-1, sd->status.name, 1, 0, 0, 0, 0, 0, 0); // type: 1 - block @@ -215,7 +211,7 @@ int impossible_trade_check(struct map_session_data *sd) // message about the ban strcpy(message_to_gm, msg_txt(508)); // This player hasn't been banned (Ban option is disabled). - intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, message_to_gm); + intif_wis_message_to_gm(wisp_server_name, PC_PERM_RECEIVE_HACK_INFO, message_to_gm); return 1; } inventory[index].amount -= sd->deal.item[i].amount; // remove item from inventory @@ -345,8 +341,8 @@ void trade_tradeadditem(struct map_session_data *sd, short index, short amount) return; item = &sd->status.inventory[index]; - src_lv = pc_isGM(sd); - dst_lv = pc_isGM(target_sd); + src_lv = pc_get_group_level(sd); + dst_lv = pc_get_group_level(target_sd); if( !itemdb_cantrade(item, src_lv, dst_lv) && //Can't trade (pc_get_partner(sd) != target_sd || !itemdb_canpartnertrade(item, src_lv, dst_lv)) ) //Can't partner-trade { diff --git a/src/map/vending.c b/src/map/vending.c index 0db4ee85b..6deba0e55 100644 --- a/src/map/vending.c +++ b/src/map/vending.c @@ -54,7 +54,7 @@ void vending_vendinglistreq(struct map_session_data* sd, int id) if( !vsd->state.vending ) return; // not vending - if ( !pc_can_give_items(pc_isGM(sd)) || !pc_can_give_items(pc_isGM(vsd)) ) //check if both GMs are allowed to trade + if (!pc_can_give_items(sd) || !pc_can_give_items(vsd)) //check if both GMs are allowed to trade { // GM is not allowed to trade clif_displaymessage(sd->fd, msg_txt(246)); return; @@ -281,7 +281,7 @@ void vending_openvending(struct map_session_data* sd, const char* message, bool || !sd->status.cart[index].identify // unidentified item || sd->status.cart[index].attribute == 1 // broken item || sd->status.cart[index].expire_time // It should not be in the cart but just in case - || !itemdb_cantrade(&sd->status.cart[index], pc_isGM(sd), pc_isGM(sd)) ) // untradeable item + || !itemdb_cantrade(&sd->status.cart[index], pc_get_group_level(sd), pc_get_group_level(sd)) ) // untradeable item continue; sd->vending[i].index = index; diff --git a/src/tool/Makefile.in b/src/tool/Makefile.in index a7f8afbf4..8d14d9ed2 100644 --- a/src/tool/Makefile.in +++ b/src/tool/Makefile.in @@ -6,6 +6,13 @@ COMMON_H = ../common/core.h ../common/mmo.h ../common/version.h \ ../common/malloc.h ../common/showmsg.h ../common/strlib.h \ ../common/utils.h ../common/cbasetypes.h ../common/des.h ../common/grfio.h +LIBCONFIG_OBJ = ../../3rdparty/libconfig/libconfig.o ../../3rdparty/libconfig/grammar.o \ + ../../3rdparty/libconfig/scanctx.o ../../3rdparty/libconfig/scanner.o ../../3rdparty/libconfig/strbuf.o +LIBCONFIG_H = ../../3rdparty/libconfig/libconfig.h ../../3rdparty/libconfig/grammar.h \ + ../../3rdparty/libconfig/parsectx.h ../../3rdparty/libconfig/scanctx.h ../../3rdparty/libconfig/scanner.h \ + ../../3rdparty/libconfig/strbuf.h ../../3rdparty/libconfig/wincompat.h +LIBCONFIG_INCLUDE = -I../../3rdparty/libconfig + MAPCACHE_OBJ = obj_all/mapcache.o @SET_MAKE@ @@ -15,8 +22,8 @@ MAPCACHE_OBJ = obj_all/mapcache.o all: mapcache -mapcache: obj_all $(MAPCACHE_OBJ) $(COMMON_OBJ) - @CC@ @LDFLAGS@ -o ../../mapcache@EXEEXT@ $(MAPCACHE_OBJ) $(COMMON_OBJ) @LIBS@ +mapcache: obj_all $(MAPCACHE_OBJ) $(COMMON_OBJ) $(LIBCONFIG_OBJ) + @CC@ @LDFLAGS@ $(LIBCONFIG_INCLUDE) -o ../../mapcache@EXEEXT@ $(MAPCACHE_OBJ) $(COMMON_OBJ) $(LIBCONFIG_OBJ) @LIBS@ clean: rm -rf obj_all/*.o ../../mapcache@EXEEXT@ @@ -42,3 +49,6 @@ obj_all/%.o: %.c $(COMMON_H) ../common/obj_all/mini%.o: @$(MAKE) -C ../common txt + +LIBCONFIG_OBJ: + @$(MAKE) -C ../../3rdparty/libconfig
\ No newline at end of file diff --git a/vcproj-10/char-server_sql.vcxproj b/vcproj-10/char-server_sql.vcxproj index e7fd17017..afa7f85d3 100644 --- a/vcproj-10/char-server_sql.vcxproj +++ b/vcproj-10/char-server_sql.vcxproj @@ -51,8 +51,8 @@ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ClCompile> <Optimization>Disabled</Optimization> - <AdditionalIncludeDirectories>..\3rdparty\mysql\include;..\3rdparty\msinttypes\include;..\3rdparty\mt19937ar;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>WIN32;_WIN32;__WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;FD_SETSIZE=4096;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>..\3rdparty\libconfig;..\3rdparty\mysql\include;..\3rdparty\msinttypes\include;..\3rdparty\mt19937ar;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN32;_WIN32;__WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;FD_SETSIZE=4096;LIBCONFIG_STATIC;YY_USE_CONST;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessToFile>false</PreprocessToFile> <PreprocessSuppressLineNumbers>false</PreprocessSuppressLineNumbers> <ExceptionHandling> @@ -94,8 +94,8 @@ <OmitFramePointers>true</OmitFramePointers> <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations> <WholeProgramOptimization>true</WholeProgramOptimization> - <AdditionalIncludeDirectories>..\3rdparty\mysql\include;..\3rdparty\msinttypes\include;..\3rdparty\mt19937ar;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>WIN32;_WIN32;__WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;FD_SETSIZE=4096;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>..\3rdparty\libconfig;..\3rdparty\mysql\include;..\3rdparty\msinttypes\include;..\3rdparty\mt19937ar;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN32;_WIN32;__WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;LIBCONFIG_STATIC;YY_USE_CONST;FD_SETSIZE=4096;%(PreprocessorDefinitions)</PreprocessorDefinitions> <StringPooling>true</StringPooling> <RuntimeLibrary>MultiThreaded</RuntimeLibrary> <AdditionalOptions> @@ -127,6 +127,13 @@ </Link> </ItemDefinitionGroup> <ItemGroup> + <ClInclude Include="..\3rdparty\libconfig\grammar.h" /> + <ClInclude Include="..\3rdparty\libconfig\libconfig.h" /> + <ClInclude Include="..\3rdparty\libconfig\parsectx.h" /> + <ClInclude Include="..\3rdparty\libconfig\scanctx.h" /> + <ClInclude Include="..\3rdparty\libconfig\scanner.h" /> + <ClInclude Include="..\3rdparty\libconfig\strbuf.h" /> + <ClInclude Include="..\3rdparty\libconfig\wincompat.h" /> <ClInclude Include="..\3rdparty\mt19937ar\mt19937ar.h" /> <ClInclude Include="..\src\common\cbasetypes.h" /> <ClInclude Include="..\src\common\core.h" /> @@ -159,6 +166,11 @@ <ClInclude Include="..\src\char\inter.h" /> </ItemGroup> <ItemGroup> + <ClCompile Include="..\3rdparty\libconfig\grammar.c" /> + <ClCompile Include="..\3rdparty\libconfig\libconfig.c" /> + <ClCompile Include="..\3rdparty\libconfig\scanctx.c" /> + <ClCompile Include="..\3rdparty\libconfig\scanner.c" /> + <ClCompile Include="..\3rdparty\libconfig\strbuf.c" /> <ClCompile Include="..\3rdparty\mt19937ar\mt19937ar.c" /> <ClCompile Include="..\src\common\core.c" /> <ClCompile Include="..\src\common\db.c" /> diff --git a/vcproj-10/char-server_sql.vcxproj.filters b/vcproj-10/char-server_sql.vcxproj.filters index 189c72e79..3b11113ee 100644 --- a/vcproj-10/char-server_sql.vcxproj.filters +++ b/vcproj-10/char-server_sql.vcxproj.filters @@ -1,9 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <ItemGroup> - <ClCompile Include="..\3rdparty\mt19937ar\mt19937ar.c"> - <Filter>3rdparty</Filter> - </ClCompile> <ClCompile Include="..\src\common\core.c"> <Filter>common</Filter> </ClCompile> @@ -79,11 +76,26 @@ <ClCompile Include="..\src\char\inter.c"> <Filter>char_sql</Filter> </ClCompile> + <ClCompile Include="..\3rdparty\mt19937ar\mt19937ar.c"> + <Filter>3rdparty\mt19937ar</Filter> + </ClCompile> + <ClCompile Include="..\3rdparty\libconfig\grammar.c"> + <Filter>3rdparty\libconfig</Filter> + </ClCompile> + <ClCompile Include="..\3rdparty\libconfig\libconfig.c"> + <Filter>3rdparty\libconfig</Filter> + </ClCompile> + <ClCompile Include="..\3rdparty\libconfig\scanctx.c"> + <Filter>3rdparty\libconfig</Filter> + </ClCompile> + <ClCompile Include="..\3rdparty\libconfig\scanner.c"> + <Filter>3rdparty\libconfig</Filter> + </ClCompile> + <ClCompile Include="..\3rdparty\libconfig\strbuf.c"> + <Filter>3rdparty\libconfig</Filter> + </ClCompile> </ItemGroup> <ItemGroup> - <ClInclude Include="..\3rdparty\mt19937ar\mt19937ar.h"> - <Filter>3rdparty</Filter> - </ClInclude> <ClInclude Include="..\src\common\cbasetypes.h"> <Filter>common</Filter> </ClInclude> @@ -171,6 +183,30 @@ <ClInclude Include="..\src\char\int_storage.h"> <Filter>char_sql</Filter> </ClInclude> + <ClInclude Include="..\3rdparty\mt19937ar\mt19937ar.h"> + <Filter>3rdparty\mt19937ar</Filter> + </ClInclude> + <ClInclude Include="..\3rdparty\libconfig\grammar.h"> + <Filter>3rdparty\libconfig</Filter> + </ClInclude> + <ClInclude Include="..\3rdparty\libconfig\libconfig.h"> + <Filter>3rdparty\libconfig</Filter> + </ClInclude> + <ClInclude Include="..\3rdparty\libconfig\parsectx.h"> + <Filter>3rdparty\libconfig</Filter> + </ClInclude> + <ClInclude Include="..\3rdparty\libconfig\scanctx.h"> + <Filter>3rdparty\libconfig</Filter> + </ClInclude> + <ClInclude Include="..\3rdparty\libconfig\scanner.h"> + <Filter>3rdparty\libconfig</Filter> + </ClInclude> + <ClInclude Include="..\3rdparty\libconfig\strbuf.h"> + <Filter>3rdparty\libconfig</Filter> + </ClInclude> + <ClInclude Include="..\3rdparty\libconfig\wincompat.h"> + <Filter>3rdparty\libconfig</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <Filter Include="common"> @@ -182,5 +218,11 @@ <Filter Include="3rdparty"> <UniqueIdentifier>{b3f5c857-79c0-4a55-b8c5-7e7f56a8f948}</UniqueIdentifier> </Filter> + <Filter Include="3rdparty\mt19937ar"> + <UniqueIdentifier>{847768ab-8c4b-431b-8667-00f8ae3b915c}</UniqueIdentifier> + </Filter> + <Filter Include="3rdparty\libconfig"> + <UniqueIdentifier>{9e8badd7-548f-4eb4-9e87-613e87e772ff}</UniqueIdentifier> + </Filter> </ItemGroup> </Project>
\ No newline at end of file diff --git a/vcproj-10/login-server_sql.vcxproj b/vcproj-10/login-server_sql.vcxproj index 34f5a33af..6cd25c88c 100644 --- a/vcproj-10/login-server_sql.vcxproj +++ b/vcproj-10/login-server_sql.vcxproj @@ -51,8 +51,8 @@ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ClCompile> <Optimization>Disabled</Optimization> - <AdditionalIncludeDirectories>..\3rdparty\mysql\include;..\3rdparty\msinttypes\include;..\3rdparty\mt19937ar;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>WIN32;_WIN32;__WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;FD_SETSIZE=4096;WITH_SQL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>..\3rdparty\libconfig;..\3rdparty\mysql\include;..\3rdparty\msinttypes\include;..\3rdparty\mt19937ar;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN32;_WIN32;__WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;FD_SETSIZE=4096;WITH_SQL;LIBCONFIG_STATIC;YY_USE_CONST;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessToFile>false</PreprocessToFile> <PreprocessSuppressLineNumbers>false</PreprocessSuppressLineNumbers> <ExceptionHandling> @@ -94,8 +94,8 @@ <OmitFramePointers>true</OmitFramePointers> <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations> <WholeProgramOptimization>true</WholeProgramOptimization> - <AdditionalIncludeDirectories>..\3rdparty\mysql\include;..\3rdparty\msinttypes\include;..\3rdparty\mt19937ar;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>WIN32;_WIN32;__WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;FD_SETSIZE=4096;WITH_SQL;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>..\3rdparty\libconfig;..\3rdparty\mysql\include;..\3rdparty\msinttypes\include;..\3rdparty\mt19937ar;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN32;_WIN32;__WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;FD_SETSIZE=4096;WITH_SQL;LIBCONFIG_STATIC;YY_USE_CONST;%(PreprocessorDefinitions)</PreprocessorDefinitions> <StringPooling>true</StringPooling> <RuntimeLibrary>MultiThreaded</RuntimeLibrary> <AdditionalOptions> @@ -131,6 +131,13 @@ </Link> </ItemDefinitionGroup> <ItemGroup> + <ClInclude Include="..\3rdparty\libconfig\grammar.h" /> + <ClInclude Include="..\3rdparty\libconfig\libconfig.h" /> + <ClInclude Include="..\3rdparty\libconfig\parsectx.h" /> + <ClInclude Include="..\3rdparty\libconfig\scanctx.h" /> + <ClInclude Include="..\3rdparty\libconfig\scanner.h" /> + <ClInclude Include="..\3rdparty\libconfig\strbuf.h" /> + <ClInclude Include="..\3rdparty\libconfig\wincompat.h" /> <ClInclude Include="..\src\login\account.h" /> <ClInclude Include="..\src\login\ipban.h" /> <ClInclude Include="..\src\login\login.h" /> @@ -156,6 +163,11 @@ <ClInclude Include="..\3rdparty\mt19937ar\mt19937ar.h" /> </ItemGroup> <ItemGroup> + <ClCompile Include="..\3rdparty\libconfig\grammar.c" /> + <ClCompile Include="..\3rdparty\libconfig\libconfig.c" /> + <ClCompile Include="..\3rdparty\libconfig\scanctx.c" /> + <ClCompile Include="..\3rdparty\libconfig\scanner.c" /> + <ClCompile Include="..\3rdparty\libconfig\strbuf.c" /> <ClCompile Include="..\src\login\account_sql.c" /> <ClCompile Include="..\src\login\ipban_sql.c" /> <ClCompile Include="..\src\login\login.c" /> diff --git a/vcproj-10/login-server_sql.vcxproj.filters b/vcproj-10/login-server_sql.vcxproj.filters index 4171d33cd..4af055584 100644 --- a/vcproj-10/login-server_sql.vcxproj.filters +++ b/vcproj-10/login-server_sql.vcxproj.filters @@ -13,9 +13,6 @@ <ClCompile Include="..\src\login\loginlog_sql.c"> <Filter>login_sql</Filter> </ClCompile> - <ClCompile Include="..\3rdparty\mt19937ar\mt19937ar.c"> - <Filter>3rdparty</Filter> - </ClCompile> <ClCompile Include="..\src\common\core.c"> <Filter>common</Filter> </ClCompile> @@ -58,6 +55,24 @@ <ClCompile Include="..\src\common\utils.c"> <Filter>common</Filter> </ClCompile> + <ClCompile Include="..\3rdparty\mt19937ar\mt19937ar.c"> + <Filter>3rdparty\mt19937ar</Filter> + </ClCompile> + <ClCompile Include="..\3rdparty\libconfig\grammar.c"> + <Filter>3rdparty\libconfig</Filter> + </ClCompile> + <ClCompile Include="..\3rdparty\libconfig\libconfig.c"> + <Filter>3rdparty\libconfig</Filter> + </ClCompile> + <ClCompile Include="..\3rdparty\libconfig\scanctx.c"> + <Filter>3rdparty\libconfig</Filter> + </ClCompile> + <ClCompile Include="..\3rdparty\libconfig\scanner.c"> + <Filter>3rdparty\libconfig</Filter> + </ClCompile> + <ClCompile Include="..\3rdparty\libconfig\strbuf.c"> + <Filter>3rdparty\libconfig</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="..\src\login\account.h"> @@ -72,9 +87,6 @@ <ClInclude Include="..\src\login\login.h"> <Filter>login_sql</Filter> </ClInclude> - <ClInclude Include="..\3rdparty\mt19937ar\mt19937ar.h"> - <Filter>3rdparty</Filter> - </ClInclude> <ClInclude Include="..\src\common\cbasetypes.h"> <Filter>common</Filter> </ClInclude> @@ -129,6 +141,30 @@ <ClInclude Include="..\src\common\utils.h"> <Filter>common</Filter> </ClInclude> + <ClInclude Include="..\3rdparty\mt19937ar\mt19937ar.h"> + <Filter>3rdparty\mt19937ar</Filter> + </ClInclude> + <ClInclude Include="..\3rdparty\libconfig\grammar.h"> + <Filter>3rdparty\libconfig</Filter> + </ClInclude> + <ClInclude Include="..\3rdparty\libconfig\libconfig.h"> + <Filter>3rdparty\libconfig</Filter> + </ClInclude> + <ClInclude Include="..\3rdparty\libconfig\parsectx.h"> + <Filter>3rdparty\libconfig</Filter> + </ClInclude> + <ClInclude Include="..\3rdparty\libconfig\scanctx.h"> + <Filter>3rdparty\libconfig</Filter> + </ClInclude> + <ClInclude Include="..\3rdparty\libconfig\scanner.h"> + <Filter>3rdparty\libconfig</Filter> + </ClInclude> + <ClInclude Include="..\3rdparty\libconfig\strbuf.h"> + <Filter>3rdparty\libconfig</Filter> + </ClInclude> + <ClInclude Include="..\3rdparty\libconfig\wincompat.h"> + <Filter>3rdparty\libconfig</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <Filter Include="common"> @@ -140,5 +176,11 @@ <Filter Include="3rdparty"> <UniqueIdentifier>{ab5c90ec-923d-4847-a214-45b40818211e}</UniqueIdentifier> </Filter> + <Filter Include="3rdparty\mt19937ar"> + <UniqueIdentifier>{68e3bcee-28d9-4b2d-8701-614d50f32999}</UniqueIdentifier> + </Filter> + <Filter Include="3rdparty\libconfig"> + <UniqueIdentifier>{779e8145-9bb2-4a88-9149-60586ab0bdd4}</UniqueIdentifier> + </Filter> </ItemGroup> </Project>
\ No newline at end of file diff --git a/vcproj-10/map-server_sql.vcxproj b/vcproj-10/map-server_sql.vcxproj index daa739ba0..55ad74671 100644 --- a/vcproj-10/map-server_sql.vcxproj +++ b/vcproj-10/map-server_sql.vcxproj @@ -50,8 +50,8 @@ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ClCompile> <Optimization>Disabled</Optimization> - <AdditionalIncludeDirectories>..\3rdparty\mysql\include;..\3rdparty\zlib\include;..\3rdparty\pcre\include;..\3rdparty\msinttypes\include;..\3rdparty\mt19937ar;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>WIN32;_WIN32;__WIN32;_DEBUG;PCRE_SUPPORT;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;FD_SETSIZE=4096;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>..\3rdparty\mysql\include;..\3rdparty\zlib\include;..\3rdparty\pcre\include;..\3rdparty\msinttypes\include;..\3rdparty\mt19937ar;..\3rdparty\libconfig;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN32;_WIN32;__WIN32;_DEBUG;PCRE_SUPPORT;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;FD_SETSIZE=4096;LIBCONFIG_STATIC;YY_USE_CONST;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessToFile>false</PreprocessToFile> <PreprocessSuppressLineNumbers>false</PreprocessSuppressLineNumbers> <ExceptionHandling> @@ -93,8 +93,8 @@ <OmitFramePointers>true</OmitFramePointers> <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations> <WholeProgramOptimization>true</WholeProgramOptimization> - <AdditionalIncludeDirectories>..\3rdparty\mysql\include;..\3rdparty\zlib\include;..\3rdparty\pcre\include;..\3rdparty\msinttypes\include;..\3rdparty\mt19937ar;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>WIN32;_WIN32;__WIN32;NDEBUG;PCRE_SUPPORT;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;FD_SETSIZE=4096;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>..\3rdparty\mysql\include;..\3rdparty\zlib\include;..\3rdparty\pcre\include;..\3rdparty\msinttypes\include;..\3rdparty\mt19937ar;..\3rdparty\libconfig;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN32;_WIN32;__WIN32;NDEBUG;PCRE_SUPPORT;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;FD_SETSIZE=4096;LIBCONFIG_STATIC;YY_USE_CONST;%(PreprocessorDefinitions)</PreprocessorDefinitions> <StringPooling>true</StringPooling> <RuntimeLibrary>MultiThreaded</RuntimeLibrary> <AdditionalOptions> @@ -126,8 +126,16 @@ </Link> </ItemDefinitionGroup> <ItemGroup> + <ClInclude Include="..\3rdparty\libconfig\grammar.h" /> + <ClInclude Include="..\3rdparty\libconfig\libconfig.h" /> + <ClInclude Include="..\3rdparty\libconfig\parsectx.h" /> + <ClInclude Include="..\3rdparty\libconfig\scanctx.h" /> + <ClInclude Include="..\3rdparty\libconfig\scanner.h" /> + <ClInclude Include="..\3rdparty\libconfig\strbuf.h" /> + <ClInclude Include="..\3rdparty\libconfig\wincompat.h" /> <ClInclude Include="..\3rdparty\mt19937ar\mt19937ar.h" /> <ClInclude Include="..\src\common\cbasetypes.h" /> + <ClInclude Include="..\src\common\conf.h" /> <ClInclude Include="..\src\common\core.h" /> <ClInclude Include="..\src\common\db.h" /> <ClInclude Include="..\src\common\des.h" /> @@ -172,6 +180,7 @@ <ClInclude Include="..\src\map\party.h" /> <ClInclude Include="..\src\map\path.h" /> <ClInclude Include="..\src\map\pc.h" /> + <ClInclude Include="..\src\map\pc_groups.h" /> <ClInclude Include="..\src\map\pet.h" /> <ClInclude Include="..\src\map\quest.h" /> <ClInclude Include="..\src\map\config\Core.h" /> @@ -191,7 +200,13 @@ <ClInclude Include="..\src\map\vending.h" /> </ItemGroup> <ItemGroup> + <ClCompile Include="..\3rdparty\libconfig\grammar.c" /> + <ClCompile Include="..\3rdparty\libconfig\libconfig.c" /> + <ClCompile Include="..\3rdparty\libconfig\scanctx.c" /> + <ClCompile Include="..\3rdparty\libconfig\scanner.c" /> + <ClCompile Include="..\3rdparty\libconfig\strbuf.c" /> <ClCompile Include="..\3rdparty\mt19937ar\mt19937ar.c" /> + <ClCompile Include="..\src\common\conf.c" /> <ClCompile Include="..\src\common\core.c" /> <ClCompile Include="..\src\common\db.c" /> <ClCompile Include="..\src\common\des.c" /> @@ -234,6 +249,7 @@ <ClCompile Include="..\src\map\party.c" /> <ClCompile Include="..\src\map\path.c" /> <ClCompile Include="..\src\map\pc.c" /> + <ClCompile Include="..\src\map\pc_groups.c" /> <ClCompile Include="..\src\map\pet.c" /> <ClCompile Include="..\src\map\quest.c" /> <ClCompile Include="..\src\map\script.c" /> diff --git a/vcproj-10/map-server_sql.vcxproj.filters b/vcproj-10/map-server_sql.vcxproj.filters index 818de17b7..a1b51acce 100644 --- a/vcproj-10/map-server_sql.vcxproj.filters +++ b/vcproj-10/map-server_sql.vcxproj.filters @@ -88,9 +88,6 @@ <ClCompile Include="..\src\map\searchstore.c"> <Filter>map_sql</Filter> </ClCompile> - <ClCompile Include="..\src\common\showmsg.c"> - <Filter>map_sql</Filter> - </ClCompile> <ClCompile Include="..\src\map\skill.c"> <Filter>map_sql</Filter> </ClCompile> @@ -109,9 +106,6 @@ <ClCompile Include="..\src\map\vending.c"> <Filter>map_sql</Filter> </ClCompile> - <ClCompile Include="..\3rdparty\mt19937ar\mt19937ar.c"> - <Filter>3rdparty</Filter> - </ClCompile> <ClCompile Include="..\src\common\core.c"> <Filter>common</Filter> </ClCompile> @@ -160,6 +154,33 @@ <ClCompile Include="..\src\common\utils.c"> <Filter>common</Filter> </ClCompile> + <ClCompile Include="..\src\common\conf.c"> + <Filter>common</Filter> + </ClCompile> + <ClCompile Include="..\src\map\pc_groups.c"> + <Filter>map_sql</Filter> + </ClCompile> + <ClCompile Include="..\src\common\showmsg.c"> + <Filter>common</Filter> + </ClCompile> + <ClCompile Include="..\3rdparty\mt19937ar\mt19937ar.c"> + <Filter>3rdparty\mt19937ar</Filter> + </ClCompile> + <ClCompile Include="..\3rdparty\libconfig\grammar.c"> + <Filter>3rdparty\libconfig</Filter> + </ClCompile> + <ClCompile Include="..\3rdparty\libconfig\libconfig.c"> + <Filter>3rdparty\libconfig</Filter> + </ClCompile> + <ClCompile Include="..\3rdparty\libconfig\scanctx.c"> + <Filter>3rdparty\libconfig</Filter> + </ClCompile> + <ClCompile Include="..\3rdparty\libconfig\scanner.c"> + <Filter>3rdparty\libconfig</Filter> + </ClCompile> + <ClCompile Include="..\3rdparty\libconfig\strbuf.c"> + <Filter>3rdparty\libconfig</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="..\src\map\atcommand.h"> @@ -246,9 +267,6 @@ <ClInclude Include="..\src\map\searchstore.h"> <Filter>map_sql</Filter> </ClInclude> - <ClInclude Include="..\src\common\showmsg.h"> - <Filter>map_sql</Filter> - </ClInclude> <ClInclude Include="..\src\map\skill.h"> <Filter>map_sql</Filter> </ClInclude> @@ -267,9 +285,6 @@ <ClInclude Include="..\src\map\vending.h"> <Filter>map_sql</Filter> </ClInclude> - <ClInclude Include="..\3rdparty\mt19937ar\mt19937ar.h"> - <Filter>3rdparty</Filter> - </ClInclude> <ClInclude Include="..\src\common\version.h"> <Filter>common</Filter> </ClInclude> @@ -330,6 +345,46 @@ <ClInclude Include="..\src\common\utils.h"> <Filter>common</Filter> </ClInclude> + <ClInclude Include="..\src\map\config\Core.h" /> + <ClInclude Include="..\src\map\config\Renewal.h" /> + <ClInclude Include="..\src\map\config\Secure.h" /> + <ClInclude Include="..\src\map\config\Data\Const.h" /> + <ClInclude Include="..\src\map\config\Skills\General.h" /> + <ClInclude Include="..\src\map\config\Skills\Mage_Classes.h" /> + <ClInclude Include="..\src\map\config\Skills\Swordsman_Classes.h" /> + <ClInclude Include="..\src\common\conf.h"> + <Filter>common</Filter> + </ClInclude> + <ClInclude Include="..\src\map\pc_groups.h"> + <Filter>map_sql</Filter> + </ClInclude> + <ClInclude Include="..\src\common\showmsg.h"> + <Filter>common</Filter> + </ClInclude> + <ClInclude Include="..\3rdparty\mt19937ar\mt19937ar.h"> + <Filter>3rdparty\mt19937ar</Filter> + </ClInclude> + <ClInclude Include="..\3rdparty\libconfig\grammar.h"> + <Filter>3rdparty\libconfig</Filter> + </ClInclude> + <ClInclude Include="..\3rdparty\libconfig\libconfig.h"> + <Filter>3rdparty\libconfig</Filter> + </ClInclude> + <ClInclude Include="..\3rdparty\libconfig\parsectx.h"> + <Filter>3rdparty\libconfig</Filter> + </ClInclude> + <ClInclude Include="..\3rdparty\libconfig\scanctx.h"> + <Filter>3rdparty\libconfig</Filter> + </ClInclude> + <ClInclude Include="..\3rdparty\libconfig\scanner.h"> + <Filter>3rdparty\libconfig</Filter> + </ClInclude> + <ClInclude Include="..\3rdparty\libconfig\strbuf.h"> + <Filter>3rdparty\libconfig</Filter> + </ClInclude> + <ClInclude Include="..\3rdparty\libconfig\wincompat.h"> + <Filter>3rdparty\libconfig</Filter> + </ClInclude> </ItemGroup> <ItemGroup> <Filter Include="common"> @@ -341,5 +396,11 @@ <Filter Include="3rdparty"> <UniqueIdentifier>{c4845ea8-bcc7-411b-af29-e3842adb6714}</UniqueIdentifier> </Filter> + <Filter Include="3rdparty\mt19937ar"> + <UniqueIdentifier>{fcf23386-ddba-4a72-9b41-62f8e2d0e6c0}</UniqueIdentifier> + </Filter> + <Filter Include="3rdparty\libconfig"> + <UniqueIdentifier>{9caf40b7-c4d1-43b4-bd1f-0376b4f920e7}</UniqueIdentifier> + </Filter> </ItemGroup> </Project>
\ No newline at end of file diff --git a/vcproj-10/mapcache.vcxproj b/vcproj-10/mapcache.vcxproj index 15a010c15..b0f58b70b 100644 --- a/vcproj-10/mapcache.vcxproj +++ b/vcproj-10/mapcache.vcxproj @@ -49,8 +49,8 @@ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ClCompile> <Optimization>Disabled</Optimization> - <AdditionalIncludeDirectories>..\3rdparty\zlib\include;..\3rdparty\msinttypes\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>WIN32;_WIN32;__WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;MINICORE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>..\3rdparty\libconfig;..\3rdparty\zlib\include;..\3rdparty\msinttypes\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN32;_WIN32;__WIN32;_DEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;MINICORE;LIBCONFIG_STATIC;YY_USE_CONST;%(PreprocessorDefinitions)</PreprocessorDefinitions> <PreprocessToFile>false</PreprocessToFile> <PreprocessSuppressLineNumbers>false</PreprocessSuppressLineNumbers> <ExceptionHandling> @@ -91,8 +91,8 @@ <OmitFramePointers>true</OmitFramePointers> <EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations> <WholeProgramOptimization>true</WholeProgramOptimization> - <AdditionalIncludeDirectories>..\3rdparty\zlib\include;..\3rdparty\msinttypes\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> - <PreprocessorDefinitions>WIN32;_WIN32;__WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;MINICORE;%(PreprocessorDefinitions)</PreprocessorDefinitions> + <AdditionalIncludeDirectories>..\3rdparty\libconfig;..\3rdparty\zlib\include;..\3rdparty\msinttypes\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> + <PreprocessorDefinitions>WIN32;_WIN32;__WIN32;NDEBUG;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;MINICORE;LIBCONFIG_STATIC;YY_USE_CONST;%(PreprocessorDefinitions)</PreprocessorDefinitions> <StringPooling>true</StringPooling> <RuntimeLibrary>MultiThreaded</RuntimeLibrary> <FunctionLevelLinking>false</FunctionLevelLinking> diff --git a/vcproj-9/char-server_sql.vcproj b/vcproj-9/char-server_sql.vcproj index 06c006cd4..43b959827 100644 --- a/vcproj-9/char-server_sql.vcproj +++ b/vcproj-9/char-server_sql.vcproj @@ -43,8 +43,8 @@ Name="VCCLCompilerTool" AdditionalOptions="/MP" Optimization="0" - AdditionalIncludeDirectories="..\3rdparty\mysql\include;..\3rdparty\msinttypes\include;..\3rdparty\mt19937ar" - PreprocessorDefinitions="WIN32;_WIN32;__WIN32;_DEBUG;FD_SETSIZE=4096" + AdditionalIncludeDirectories="..\3rdparty\libconfig;..\3rdparty\mysql\include;..\3rdparty\msinttypes\include;..\3rdparty\mt19937ar" + PreprocessorDefinitions="WIN32;_WIN32;__WIN32;_DEBUG;FD_SETSIZE=4096;LIBCONFIG_STATIC;YY_USE_CONST" GeneratePreprocessedFile="0" ExceptionHandling="0" BasicRuntimeChecks="3" @@ -137,8 +137,8 @@ OmitFramePointers="true" EnableFiberSafeOptimizations="true" WholeProgramOptimization="true" - AdditionalIncludeDirectories="..\3rdparty\mysql\include;..\3rdparty\msinttypes\include;..\3rdparty\mt19937ar" - PreprocessorDefinitions="WIN32;_WIN32;__WIN32;NDEBUG;FD_SETSIZE=4096" + AdditionalIncludeDirectories="..\3rdparty\libconfig;..\3rdparty\mysql\include;..\3rdparty\msinttypes\include;..\3rdparty\mt19937ar" + PreprocessorDefinitions="WIN32;_WIN32;__WIN32;NDEBUG;FD_SETSIZE=4096;LIBCONFIG_STATIC;YY_USE_CONST" StringPooling="true" RuntimeLibrary="0" DefaultCharIsUnsigned="false" @@ -204,20 +204,84 @@ <Filter Name="3rdparty" > + <Filter + Name="mt19937ar" + > + <File + RelativePath="..\3rdparty\mt19937ar\mt19937ar.c" + > + </File> + <File + RelativePath="..\3rdparty\mt19937ar\mt19937ar.h" + > + </File> + </Filter> + <Filter + Name="libconfig" + > + <File + RelativePath="..\3rdparty\libconfig\grammar.c" + > + </File> + <File + RelativePath="..\3rdparty\libconfig\grammar.h" + > + </File> + <File + RelativePath="..\3rdparty\libconfig\libconfig.c" + > + </File> + <File + RelativePath="..\3rdparty\libconfig\libconfig.h" + > + </File> + <File + RelativePath="..\3rdparty\libconfig\parsectx.h" + > + </File> + <File + RelativePath="..\3rdparty\libconfig\scanctx.c" + > + </File> + <File + RelativePath="..\3rdparty\libconfig\scanctx.h" + > + </File> + <File + RelativePath="..\3rdparty\libconfig\scanner.c" + > + </File> + <File + RelativePath="..\3rdparty\libconfig\scanner.h" + > + </File> + <File + RelativePath="..\3rdparty\libconfig\strbuf.c" + > + </File> + <File + RelativePath="..\3rdparty\libconfig\strbuf.h" + > + </File> + <File + RelativePath="..\3rdparty\libconfig\wincompat.h" + > + </File> + </Filter> + </Filter> + <Filter + Name="common" + > <File - RelativePath="..\3rdparty\mt19937ar\mt19937ar.c" + RelativePath="..\src\common\cbasetypes.h" > </File> <File - RelativePath="..\3rdparty\mt19937ar\mt19937ar.h" + RelativePath="..\src\common\conf.c" > </File> - </Filter> - <Filter - Name="common" - > <File - RelativePath="..\src\common\cbasetypes.h" + RelativePath="..\src\common\conf.h" > </File> <File diff --git a/vcproj-9/login-server_sql.vcproj b/vcproj-9/login-server_sql.vcproj index d2f9d34d9..a0ce7ceae 100644 --- a/vcproj-9/login-server_sql.vcproj +++ b/vcproj-9/login-server_sql.vcproj @@ -43,8 +43,8 @@ Name="VCCLCompilerTool" AdditionalOptions="/MP" Optimization="0" - AdditionalIncludeDirectories="..\3rdparty\mysql\include;..\3rdparty\msinttypes\include;..\3rdparty\mt19937ar" - PreprocessorDefinitions="WIN32;_WIN32;__WIN32;_DEBUG;FD_SETSIZE=4096;WITH_SQL" + AdditionalIncludeDirectories="..\3rdparty\libconfig;..\3rdparty\mysql\include;..\3rdparty\msinttypes\include;..\3rdparty\mt19937ar" + PreprocessorDefinitions="WIN32;_WIN32;__WIN32;_DEBUG;FD_SETSIZE=4096;LIBCONFIG_STATIC;YY_USE_CONST;WITH_SQL" GeneratePreprocessedFile="0" ExceptionHandling="0" BasicRuntimeChecks="3" @@ -137,8 +137,8 @@ OmitFramePointers="true" EnableFiberSafeOptimizations="true" WholeProgramOptimization="true" - AdditionalIncludeDirectories="..\3rdparty\mysql\include;..\3rdparty\msinttypes\include;..\3rdparty\mt19937ar" - PreprocessorDefinitions="WIN32;_WIN32;__WIN32;NDEBUG;FD_SETSIZE=4096;WITH_SQL" + AdditionalIncludeDirectories="..\3rdparty\libconfig;..\3rdparty\mysql\include;..\3rdparty\msinttypes\include;..\3rdparty\mt19937ar" + PreprocessorDefinitions="WIN32;_WIN32;__WIN32;NDEBUG;FD_SETSIZE=4096;LIBCONFIG_STATIC;YY_USE_CONST;WITH_SQL" StringPooling="true" RuntimeLibrary="0" DefaultCharIsUnsigned="false" @@ -247,6 +247,14 @@ > </File> <File + RelativePath="..\src\common\conf.c" + > + </File> + <File + RelativePath="..\src\common\conf.h" + > + </File> + <File RelativePath="..\src\common\core.c" > </File> @@ -382,14 +390,70 @@ <Filter Name="3rdparty" > - <File - RelativePath="..\3rdparty\mt19937ar\mt19937ar.c" - > - </File> - <File - RelativePath="..\3rdparty\mt19937ar\mt19937ar.h" - > - </File> + <Filter + Name="mt19937ar" + > + <File + RelativePath="..\3rdparty\mt19937ar\mt19937ar.c" + > + </File> + <File + RelativePath="..\3rdparty\mt19937ar\mt19937ar.h" + > + </File> + </Filter> + <Filter + Name="libconfig" + > + <File + RelativePath="..\3rdparty\libconfig\grammar.c" + > + </File> + <File + RelativePath="..\3rdparty\libconfig\grammar.h" + > + </File> + <File + RelativePath="..\3rdparty\libconfig\libconfig.c" + > + </File> + <File + RelativePath="..\3rdparty\libconfig\libconfig.h" + > + </File> + <File + RelativePath="..\3rdparty\libconfig\parsectx.h" + > + </File> + <File + RelativePath="..\3rdparty\libconfig\scanctx.c" + > + </File> + <File + RelativePath="..\3rdparty\libconfig\scanctx.h" + > + </File> + <File + RelativePath="..\3rdparty\libconfig\scanner.c" + > + </File> + <File + RelativePath="..\3rdparty\libconfig\scanner.h" + > + </File> + <File + RelativePath="..\3rdparty\libconfig\strbuf.c" + > + </File> + <File + RelativePath="..\3rdparty\libconfig\strbuf.h" + > + </File> + <File + RelativePath="..\3rdparty\libconfig\wincompat.h" + > + </File> + </Filter> </Filter> </Files> <Globals> diff --git a/vcproj-9/map-server_sql.vcproj b/vcproj-9/map-server_sql.vcproj index 14c807bcb..39a58e47d 100644 --- a/vcproj-9/map-server_sql.vcproj +++ b/vcproj-9/map-server_sql.vcproj @@ -42,8 +42,8 @@ Name="VCCLCompilerTool" AdditionalOptions="/MP" Optimization="0" - AdditionalIncludeDirectories="..\3rdparty\mysql\include;..\3rdparty\zlib\include;..\3rdparty\pcre\include;..\3rdparty\msinttypes\include;..\3rdparty\mt19937ar" - PreprocessorDefinitions="WIN32;_WIN32;__WIN32;_DEBUG;PCRE_SUPPORT;FD_SETSIZE=4096" + AdditionalIncludeDirectories="..\3rdparty\libconfig;..\3rdparty\mysql\include;..\3rdparty\zlib\include;..\3rdparty\pcre\include;..\3rdparty\msinttypes\include;..\3rdparty\mt19937ar" + PreprocessorDefinitions="WIN32;_WIN32;__WIN32;_DEBUG;PCRE_SUPPORT;FD_SETSIZE=4096;LIBCONFIG_STATIC;YY_USE_CONST" GeneratePreprocessedFile="0" ExceptionHandling="0" BasicRuntimeChecks="3" @@ -136,8 +136,8 @@ OmitFramePointers="true" EnableFiberSafeOptimizations="true" WholeProgramOptimization="true" - AdditionalIncludeDirectories="..\3rdparty\mysql\include;..\3rdparty\zlib\include;..\3rdparty\pcre\include;..\3rdparty\msinttypes\include;..\3rdparty\mt19937ar" - PreprocessorDefinitions="WIN32;_WIN32;__WIN32;NDEBUG;PCRE_SUPPORT;FD_SETSIZE=4096" + AdditionalIncludeDirectories="..\3rdparty\libconfig;..\3rdparty\mysql\include;..\3rdparty\zlib\include;..\3rdparty\pcre\include;..\3rdparty\msinttypes\include;..\3rdparty\mt19937ar" + PreprocessorDefinitions="WIN32;_WIN32;__WIN32;NDEBUG;PCRE_SUPPORT;FD_SETSIZE=4096;LIBCONFIG_STATIC;YY_USE_CONST" StringPooling="true" RuntimeLibrary="0" DefaultCharIsUnsigned="false" @@ -203,20 +203,84 @@ <Filter Name="3rdparty" > + <Filter + Name="mt19937ar" + > + <File + RelativePath="..\3rdparty\mt19937ar\mt19937ar.c" + > + </File> + <File + RelativePath="..\3rdparty\mt19937ar\mt19937ar.h" + > + </File> + </Filter> + <Filter + Name="libconfig" + > + <File + RelativePath="..\3rdparty\libconfig\grammar.c" + > + </File> + <File + RelativePath="..\3rdparty\libconfig\grammar.h" + > + </File> + <File + RelativePath="..\3rdparty\libconfig\libconfig.c" + > + </File> + <File + RelativePath="..\3rdparty\libconfig\libconfig.h" + > + </File> + <File + RelativePath="..\3rdparty\libconfig\parsectx.h" + > + </File> + <File + RelativePath="..\3rdparty\libconfig\scanctx.c" + > + </File> + <File + RelativePath="..\3rdparty\libconfig\scanctx.h" + > + </File> + <File + RelativePath="..\3rdparty\libconfig\scanner.c" + > + </File> + <File + RelativePath="..\3rdparty\libconfig\scanner.h" + > + </File> + <File + RelativePath="..\3rdparty\libconfig\strbuf.c" + > + </File> + <File + RelativePath="..\3rdparty\libconfig\strbuf.h" + > + </File> + <File + RelativePath="..\3rdparty\libconfig\wincompat.h" + > + </File> + </Filter> + </Filter> + <Filter + Name="common" + > <File - RelativePath="..\3rdparty\mt19937ar\mt19937ar.c" + RelativePath="..\src\common\cbasetypes.h" > </File> <File - RelativePath="..\3rdparty\mt19937ar\mt19937ar.h" + RelativePath="..\src\common\conf.c" > </File> - </Filter> - <Filter - Name="common" - > <File - RelativePath="..\src\common\cbasetypes.h" + RelativePath="..\src\common\conf.h" > </File> <File @@ -436,6 +500,14 @@ > </File> <File + RelativePath="..\src\map\config\Data\Const.h" + > + </File> + <File + RelativePath="..\src\map\config\Core.h" + > + </File> + <File RelativePath="..\src\map\date.c" > </File> @@ -452,6 +524,10 @@ > </File> <File + RelativePath="..\src\map\config\Skills\General.h" + > + </File> + <File RelativePath="..\src\map\guild.c" > </File> @@ -500,6 +576,10 @@ > </File> <File + RelativePath="..\src\map\config\Skills\Mage_Classes.h" + > + </File> + <File RelativePath="..\src\map\mail.c" > </File> @@ -576,47 +656,31 @@ > </File> <File - RelativePath="..\src\map\pet.c" + RelativePath="..\src\map\pc_groups.c" > </File> <File - RelativePath="..\src\map\pet.h" + RelativePath="..\src\map\pc_groups.h" > </File> <File - RelativePath="..\src\map\quest.c" - > - </File> - <File - RelativePath="..\src\map\quest.h" + RelativePath="..\src\map\pet.c" > </File> <File - RelativePath="..\src\map\config\Core.h" + RelativePath="..\src\map\pet.h" > </File> <File - RelativePath="..\src\map\config\Renewal.h" + RelativePath="..\src\map\quest.c" > </File> <File - RelativePath="..\src\map\config\Secure.h" + RelativePath="..\src\map\quest.h" > </File> <File - RelativePath="..\src\map\config\Data\Const.h" - > - </File> - <File - RelativePath="..\src\map\config\Skills\General.h" - > - </File> - <File - RelativePath="..\src\map\config\Skills\Mage_Classes.h" - > - </File> - <File - RelativePath="..\src\map\config\Skills\Swordsman_Classes.h" + RelativePath="..\src\map\config\Renewal.h" > </File> <File @@ -636,6 +700,10 @@ > </File> <File + RelativePath="..\src\map\config\Secure.h" + > + </File> + <File RelativePath="..\src\map\skill.c" > </File> @@ -660,6 +728,10 @@ > </File> <File + RelativePath="..\src\map\config\Skills\Swordsman_Classes.h" + > + </File> + <File RelativePath="..\src\map\trade.c" > </File> diff --git a/vcproj-9/mapcache.vcproj b/vcproj-9/mapcache.vcproj index 645ae0b5e..e13f7ab27 100644 --- a/vcproj-9/mapcache.vcproj +++ b/vcproj-9/mapcache.vcproj @@ -42,8 +42,8 @@ Name="VCCLCompilerTool" AdditionalOptions="/MP" Optimization="0" - AdditionalIncludeDirectories="..\3rdparty\zlib\include;..\3rdparty\msinttypes\include" - PreprocessorDefinitions="WIN32;_WIN32;__WIN32;_DEBUG;MINICORE" + AdditionalIncludeDirectories="..\3rdparty\libconfig;..\3rdparty\zlib\include;..\3rdparty\msinttypes\include" + PreprocessorDefinitions="WIN32;_WIN32;__WIN32;_DEBUG;MINICORE;LIBCONFIG_STATIC;YY_USE_CONST" GeneratePreprocessedFile="0" ExceptionHandling="0" BasicRuntimeChecks="3" @@ -135,8 +135,8 @@ OmitFramePointers="true" EnableFiberSafeOptimizations="true" WholeProgramOptimization="true" - AdditionalIncludeDirectories="..\3rdparty\zlib\include;..\3rdparty\msinttypes\include" - PreprocessorDefinitions="WIN32;_WIN32;__WIN32;NDEBUG;MINICORE" + AdditionalIncludeDirectories="..\3rdparty\libconfig;..\3rdparty\zlib\include;..\3rdparty\msinttypes\include" + PreprocessorDefinitions="WIN32;_WIN32;__WIN32;NDEBUG;MINICORE;LIBCONFIG_STATIC;YY_USE_CONST" StringPooling="true" RuntimeLibrary="0" EnableFunctionLevelLinking="false" @@ -211,11 +211,11 @@ > </File> <File - RelativePath="..\src\common\des.h" + RelativePath="..\src\common\des.c" > </File> <File - RelativePath="..\src\common\des.c" + RelativePath="..\src\common\des.h" > </File> <File |